1/* 2 * (c) 1995 Microsoft Corporation. All rights reserved. 3 * Developed by ActiveWare Internet Corp., http://www.ActiveWare.com 4 * 5 * Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy 6 * <gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net> 7 * 8 * You may distribute under the terms of either the GNU General Public 9 * License or the Artistic License, as specified in the README file 10 * of the Perl distribution. 11 * 12 */ 13 14/* 15 modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@nifty.ne.jp> 16 */ 17 18#include "ruby/ruby.h" 19#include "ruby/st.h" 20#include "ruby/encoding.h" 21 22#define GNUC_OLDER_3_4_4 \ 23 ((__GNUC__ < 3) || \ 24 ((__GNUC__ <= 3) && (__GNUC_MINOR__ < 4)) || \ 25 ((__GNUC__ <= 3) && (__GNUC_MINOR__ <= 4) && (__GNUC_PATCHLEVEL__ <= 4))) 26 27#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) 28#ifndef NONAMELESSUNION 29#define NONAMELESSUNION 1 30#endif 31#endif 32 33#include <ctype.h> 34 35#include <windows.h> 36#include <ocidl.h> 37#include <olectl.h> 38#include <ole2.h> 39#if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE) 40#include <mlang.h> 41#endif 42#include <stdlib.h> 43#include <math.h> 44#ifdef HAVE_STDARG_PROTOTYPES 45#include <stdarg.h> 46#define va_init_list(a,b) va_start(a,b) 47#else 48#include <varargs.h> 49#define va_init_list(a,b) va_start(a) 50#endif 51#include <objidl.h> 52 53#define DOUT fprintf(stderr,"[%d]\n",__LINE__) 54#define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x) 55#define DOUTMSG(x) fprintf(stderr, "[%d]:" #x "\n",__LINE__) 56#define DOUTI(x) fprintf(stderr, "[%ld]:" #x "=%d\n",__LINE__,x) 57#define DOUTD(x) fprintf(stderr, "[%d]:" #x "=%f\n",__LINE__,x) 58 59#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) 60#define V_UNION1(X, Y) ((X)->u.Y) 61#else 62#define V_UNION1(X, Y) ((X)->Y) 63#endif 64 65#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) 66#undef V_UNION 67#define V_UNION(X,Y) ((X)->n1.n2.n3.Y) 68 69#undef V_VT 70#define V_VT(X) ((X)->n1.n2.vt) 71 72#undef V_BOOL 73#define V_BOOL(X) V_UNION(X,boolVal) 74#endif 75 76#ifndef V_I1REF 77#define V_I1REF(X) V_UNION(X, pcVal) 78#endif 79 80#ifndef V_UI2REF 81#define V_UI2REF(X) V_UNION(X, puiVal) 82#endif 83 84#ifndef V_INT 85#define V_INT(X) V_UNION(X, intVal) 86#endif 87 88#ifndef V_INTREF 89#define V_INTREF(X) V_UNION(X, pintVal) 90#endif 91 92#ifndef V_UINT 93#define V_UINT(X) V_UNION(X, uintVal) 94#endif 95 96#ifndef V_UINTREF 97#define V_UINTREF(X) V_UNION(X, puintVal) 98#endif 99 100/* 101 * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a 102 * in Cygwin(mingw32). 103 */ 104#if defined(__CYGWIN__) || defined(__MINGW32__) 105#undef IID_IMultiLanguage2 106const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}}; 107#endif 108 109#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0 110 111#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0 112 113#define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y))) 114#define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y))) 115 116#define OLE_FREE(x) {\ 117 if(g_ole_initialized == TRUE) {\ 118 if(x) {\ 119 OLE_RELEASE(x);\ 120 (x) = 0;\ 121 }\ 122 }\ 123} 124 125#define OLEData_Get_Struct(obj, pole) {\ 126 Data_Get_Struct(obj, struct oledata, pole);\ 127 if(!pole->pDispatch) {\ 128 rb_raise(rb_eRuntimeError, "failed to get Dispatch Interface");\ 129 }\ 130} 131 132#ifdef HAVE_LONG_LONG 133#define I8_2_NUM LL2NUM 134#define UI8_2_NUM ULL2NUM 135#define NUM2I8 NUM2LL 136#define NUM2UI8 NUM2ULL 137#else 138#define I8_2_NUM INT2NUM 139#define UI8_2_NUM UINT2NUM 140#define NUM2I8 NUM2INT 141#define NUM2UI8 NUM2UINT 142#endif 143 144#define WC2VSTR(x) ole_wc2vstr((x), TRUE) 145 146#define WIN32OLE_VERSION "1.5.4" 147 148typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) 149 (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); 150 151typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile, 152 UINT uCommand, DWORD dwData); 153typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD); 154typedef struct { 155 struct IEventSinkVtbl * lpVtbl; 156} IEventSink, *PEVENTSINK; 157 158typedef struct IEventSinkVtbl IEventSinkVtbl; 159 160struct IEventSinkVtbl { 161 STDMETHOD(QueryInterface)( 162 PEVENTSINK, 163 REFIID, 164 LPVOID *); 165 STDMETHOD_(ULONG, AddRef)(PEVENTSINK); 166 STDMETHOD_(ULONG, Release)(PEVENTSINK); 167 168 STDMETHOD(GetTypeInfoCount)( 169 PEVENTSINK, 170 UINT *); 171 STDMETHOD(GetTypeInfo)( 172 PEVENTSINK, 173 UINT, 174 LCID, 175 ITypeInfo **); 176 STDMETHOD(GetIDsOfNames)( 177 PEVENTSINK, 178 REFIID, 179 OLECHAR **, 180 UINT, 181 LCID, 182 DISPID *); 183 STDMETHOD(Invoke)( 184 PEVENTSINK, 185 DISPID, 186 REFIID, 187 LCID, 188 WORD, 189 DISPPARAMS *, 190 VARIANT *, 191 EXCEPINFO *, 192 UINT *); 193}; 194 195typedef struct tagIEVENTSINKOBJ { 196 IEventSinkVtbl *lpVtbl; 197 DWORD m_cRef; 198 IID m_iid; 199 int m_event_id; 200 ITypeInfo *pTypeInfo; 201}IEVENTSINKOBJ, *PIEVENTSINKOBJ; 202 203VALUE cWIN32OLE; 204VALUE cWIN32OLE_TYPELIB; 205VALUE cWIN32OLE_TYPE; 206VALUE cWIN32OLE_VARIABLE; 207VALUE cWIN32OLE_METHOD; 208VALUE cWIN32OLE_PARAM; 209VALUE cWIN32OLE_EVENT; 210VALUE cWIN32OLE_VARIANT; 211VALUE eWIN32OLERuntimeError; 212VALUE mWIN32OLE_VARIANT; 213VALUE cWIN32OLE_PROPERTY; 214 215static VALUE ary_ole_event; 216static ID id_events; 217#if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__) || defined(__MINGW32__)) 218static RB_THREAD_SPECIFIC BOOL g_ole_initialized; 219# define g_ole_initialized_init() ((void)0) 220# define g_ole_initialized_set(val) (g_ole_initialized = (val)) 221#else 222static volatile DWORD g_ole_initialized_key = TLS_OUT_OF_INDEXES; 223# define g_ole_initialized (BOOL)TlsGetValue(g_ole_initialized_key) 224# define g_ole_initialized_init() (g_ole_initialized_key = TlsAlloc()) 225# define g_ole_initialized_set(val) TlsSetValue(g_ole_initialized_key, (void*)(val)) 226#endif 227static BOOL g_uninitialize_hooked = FALSE; 228static BOOL g_cp_installed = FALSE; 229static BOOL g_lcid_installed = FALSE; 230static HINSTANCE ghhctrl = NULL; 231static HINSTANCE gole32 = NULL; 232static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL; 233static VALUE com_hash; 234static IDispatchVtbl com_vtbl; 235static UINT cWIN32OLE_cp = CP_ACP; 236static LCID cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT; 237static rb_encoding *cWIN32OLE_enc; 238static UINT g_cp_to_check = CP_ACP; 239static char g_lcid_to_check[8 + 1]; 240static VARTYPE g_nil_to = VT_ERROR; 241static st_table *enc2cp_table; 242static IMessageFilterVtbl message_filter; 243static IMessageFilter imessage_filter = { &message_filter }; 244static IMessageFilter* previous_filter; 245 246#if defined(HAVE_TYPE_IMULTILANGUAGE2) 247static IMultiLanguage2 *pIMultiLanguage = NULL; 248#elif defined(HAVE_TYPE_IMULTILANGUAGE) 249static IMultiLanguage *pIMultiLanguage = NULL; 250#else 251#define pIMultiLanguage NULL /* dummy */ 252#endif 253 254struct oledata { 255 IDispatch *pDispatch; 256}; 257 258struct oletypelibdata { 259 ITypeLib *pTypeLib; 260}; 261 262struct oletypedata { 263 ITypeInfo *pTypeInfo; 264}; 265 266struct olemethoddata { 267 ITypeInfo *pOwnerTypeInfo; 268 ITypeInfo *pTypeInfo; 269 UINT index; 270}; 271 272struct olevariabledata { 273 ITypeInfo *pTypeInfo; 274 UINT index; 275}; 276 277struct oleparamdata { 278 ITypeInfo *pTypeInfo; 279 UINT method_index; 280 UINT index; 281}; 282 283struct oleeventdata { 284 DWORD dwCookie; 285 IConnectionPoint *pConnectionPoint; 286 long event_id; 287}; 288 289struct oleparam { 290 DISPPARAMS dp; 291 OLECHAR** pNamedArgs; 292}; 293 294struct olevariantdata { 295 VARIANT realvar; 296 VARIANT var; 297}; 298 299 300static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject); 301static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This); 302static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This); 303static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo); 304static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo); 305static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId); 306static HRESULT ( STDMETHODCALLTYPE Invoke )( IDispatch __RPC_FAR * This, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS __RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr); 307static IDispatch* val2dispatch(VALUE val); 308static double rbtime2vtdate(VALUE tmobj); 309static VALUE vtdate2rbtime(double date); 310static rb_encoding *ole_cp2encoding(UINT cp); 311static UINT ole_encoding2cp(rb_encoding *enc); 312NORETURN(static void failed_load_conv51932(void)); 313#ifndef pIMultiLanguage 314static void load_conv_function51932(void); 315#endif 316static UINT ole_init_cp(void); 317static char *ole_wc2mb(LPWSTR pw); 318static VALUE ole_hresult2msg(HRESULT hr); 319static void ole_freeexceptinfo(EXCEPINFO *pExInfo); 320static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo); 321static void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...); 322static void ole_initialize(void); 323static void ole_msg_loop(void); 324static void ole_free(struct oledata *pole); 325static void oletypelib_free(struct oletypelibdata *poletypelib); 326static void oletype_free(struct oletypedata *poletype); 327static void olemethod_free(struct olemethoddata *polemethod); 328static void olevariable_free(struct olevariabledata *polevar); 329static void oleparam_free(struct oleparamdata *pole); 330static LPWSTR ole_vstr2wc(VALUE vstr); 331static LPWSTR ole_mb2wc(char *pm, int len); 332static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree); 333static VALUE ole_ary_m_entry(VALUE val, long *pid); 334static void * get_ptr_of_variant(VARIANT *pvar); 335static VALUE is_all_index_under(long *pid, long *pub, long dim); 336static void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt); 337static long dimension(VALUE val); 338static long ary_len_of_dim(VALUE ary, long dim); 339static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt); 340static void ole_val2variant(VALUE val, VARIANT *var); 341static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt); 342static void ole_val2ptr_variant(VALUE val, VARIANT *var); 343static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt); 344static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar); 345static void ole_val2variant2(VALUE val, VARIANT *var); 346static VALUE make_inspect(const char *class_name, VALUE detail); 347static VALUE default_inspect(VALUE self, const char *class_name); 348static VALUE ole_set_member(VALUE self, IDispatch *dispatch); 349static VALUE fole_s_allocate(VALUE klass); 350static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv); 351static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim); 352static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val); 353static VALUE ole_variant2val(VARIANT *pvar); 354static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey); 355static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey); 356static VALUE reg_enum_key(HKEY hkey, DWORD i); 357static VALUE reg_get_val(HKEY hkey, const char *subkey); 358static VALUE reg_get_typelib_file_path(HKEY hkey); 359static VALUE typelib_file_from_clsid(VALUE ole); 360static VALUE typelib_file_from_typelib(VALUE ole); 361static VALUE typelib_file(VALUE ole); 362static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self); 363static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid); 364static VALUE ole_create_dcom(int argc, VALUE *argv, VALUE self); 365static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self); 366static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self); 367static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self); 368static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes); 369static ULONG reference_count(struct oledata * pole); 370static VALUE fole_s_reference_count(VALUE self, VALUE obj); 371static VALUE fole_s_free(VALUE self, VALUE obj); 372static HWND ole_show_help(VALUE helpfile, VALUE helpcontext); 373static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self); 374static VALUE fole_s_get_code_page(VALUE self); 375static BOOL CALLBACK installed_code_page_proc(LPTSTR str); 376static BOOL code_page_installed(UINT cp); 377static VALUE fole_s_set_code_page(VALUE self, VALUE vcp); 378static VALUE fole_s_get_locale(VALUE self); 379static BOOL CALLBACK installed_lcid_proc(LPTSTR str); 380static BOOL lcid_installed(LCID lcid); 381static VALUE fole_s_set_locale(VALUE self, VALUE vlcid); 382static VALUE fole_s_create_guid(VALUE self); 383static VALUE fole_s_ole_initialize(VALUE self); 384static VALUE fole_s_ole_uninitialize(VALUE self); 385static VALUE fole_initialize(int argc, VALUE *argv, VALUE self); 386static VALUE hash2named_arg(VALUE pair, struct oleparam* pOp); 387static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end); 388static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket); 389static VALUE fole_invoke(int argc, VALUE *argv, VALUE self); 390static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind); 391static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types); 392static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types); 393static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types); 394static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self); 395static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self); 396static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self); 397static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value); 398static VALUE fole_free(VALUE self); 399static VALUE ole_each_sub(VALUE pEnumV); 400static VALUE ole_ienum_free(VALUE pEnumV); 401static VALUE fole_each(VALUE self); 402static VALUE fole_missing(int argc, VALUE *argv, VALUE self); 403static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name); 404static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name); 405static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask); 406static VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask); 407static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti); 408static VALUE ole_methods(VALUE self, int mask); 409static VALUE fole_methods(VALUE self); 410static VALUE fole_get_methods(VALUE self); 411static VALUE fole_put_methods(VALUE self); 412static VALUE fole_func_methods(VALUE self); 413static VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo); 414static VALUE fole_type(VALUE self); 415static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo); 416static VALUE fole_typelib(VALUE self); 417static VALUE fole_query_interface(VALUE self, VALUE str_iid); 418static VALUE fole_respond_to(VALUE self, VALUE method); 419static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); 420static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); 421static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); 422static VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); 423static VALUE fole_method_help(VALUE self, VALUE cmdname); 424static VALUE fole_activex_initialize(VALUE self); 425static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib); 426static VALUE foletype_s_typelibs(VALUE self); 427static VALUE foletype_s_progids(VALUE self); 428static VALUE foletype_s_allocate(VALUE klass); 429static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name); 430static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass); 431static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib); 432static ITypeLib * oletypelib_get_typelib(VALUE self); 433static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr); 434static VALUE foletypelib_s_typelibs(VALUE self); 435static VALUE make_version_str(VALUE major, VALUE minor); 436static VALUE oletypelib_search_registry2(VALUE self, VALUE args); 437static VALUE oletypelib_search_registry(VALUE self, VALUE typelib); 438static VALUE foletypelib_s_allocate(VALUE klass); 439static VALUE foletypelib_initialize(VALUE self, VALUE args); 440static VALUE foletypelib_guid(VALUE self); 441static VALUE foletypelib_name(VALUE self); 442static VALUE foletypelib_version(VALUE self); 443static VALUE foletypelib_major_version(VALUE self); 444static VALUE foletypelib_minor_version(VALUE self); 445static VALUE oletypelib_path(VALUE guid, VALUE version); 446static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib); 447static VALUE foletypelib_path(VALUE self); 448static VALUE foletypelib_visible(VALUE self); 449static VALUE foletypelib_library_name(VALUE self); 450static VALUE foletypelib_ole_types(VALUE self); 451static VALUE foletypelib_inspect(VALUE self); 452static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass); 453static VALUE foletype_name(VALUE self); 454static VALUE ole_ole_type(ITypeInfo *pTypeInfo); 455static VALUE foletype_ole_type(VALUE self); 456static VALUE ole_type_guid(ITypeInfo *pTypeInfo); 457static VALUE foletype_guid(VALUE self); 458static VALUE ole_type_progid(ITypeInfo *pTypeInfo); 459static VALUE foletype_progid(VALUE self); 460static VALUE ole_type_visible(ITypeInfo *pTypeInfo); 461static VALUE foletype_visible(VALUE self); 462static VALUE ole_type_major_version(ITypeInfo *pTypeInfo); 463static VALUE foletype_major_version(VALUE self); 464static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo); 465static VALUE foletype_minor_version(VALUE self); 466static VALUE ole_type_typekind(ITypeInfo *pTypeInfo); 467static VALUE foletype_typekind(VALUE self); 468static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo); 469static VALUE foletype_helpstring(VALUE self); 470static VALUE ole_type_src_type(ITypeInfo *pTypeInfo); 471static VALUE foletype_src_type(VALUE self); 472static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo); 473static VALUE foletype_helpfile(VALUE self); 474static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo); 475static VALUE foletype_helpcontext(VALUE self); 476static VALUE foletype_ole_typelib(VALUE self); 477static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags); 478static VALUE foletype_impl_ole_types(VALUE self); 479static VALUE foletype_source_ole_types(VALUE self); 480static VALUE foletype_default_event_sources(VALUE self); 481static VALUE foletype_default_ole_types(VALUE self); 482static VALUE foletype_inspect(VALUE self); 483static VALUE ole_variables(ITypeInfo *pTypeInfo); 484static VALUE foletype_variables(VALUE self); 485static VALUE foletype_methods(VALUE self); 486static VALUE folevariable_name(VALUE self); 487static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index); 488static VALUE folevariable_ole_type(VALUE self); 489static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index); 490static VALUE folevariable_ole_type_detail(VALUE self); 491static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index); 492static VALUE folevariable_value(VALUE self); 493static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index); 494static VALUE folevariable_visible(VALUE self); 495static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index); 496static VALUE folevariable_variable_kind(VALUE self); 497static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index); 498static VALUE folevariable_varkind(VALUE self); 499static VALUE folevariable_inspect(VALUE self); 500static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name); 501static VALUE folemethod_s_allocate(VALUE klass); 502static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method); 503static VALUE folemethod_name(VALUE self); 504static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index); 505static VALUE folemethod_return_type(VALUE self); 506static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index); 507static VALUE folemethod_return_vtype(VALUE self); 508static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index); 509static VALUE folemethod_return_type_detail(VALUE self); 510static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index); 511static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index); 512static VALUE folemethod_invkind(VALUE self); 513static VALUE folemethod_invoke_kind(VALUE self); 514static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index); 515static VALUE folemethod_visible(VALUE self); 516static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name); 517static VALUE folemethod_event(VALUE self); 518static VALUE folemethod_event_interface(VALUE self); 519static VALUE ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); 520static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index); 521static VALUE folemethod_helpstring(VALUE self); 522static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index); 523static VALUE folemethod_helpfile(VALUE self); 524static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index); 525static VALUE folemethod_helpcontext(VALUE self); 526static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index); 527static VALUE folemethod_dispid(VALUE self); 528static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index); 529static VALUE folemethod_offset_vtbl(VALUE self); 530static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index); 531static VALUE folemethod_size_params(VALUE self); 532static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index); 533static VALUE folemethod_size_opt_params(VALUE self); 534static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index); 535static VALUE folemethod_params(VALUE self); 536static VALUE folemethod_inspect(VALUE self); 537static VALUE foleparam_s_allocate(VALUE klass); 538static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index); 539static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n); 540static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n); 541static VALUE foleparam_name(VALUE self); 542static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index); 543static VALUE foleparam_ole_type(VALUE self); 544static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index); 545static VALUE foleparam_ole_type_detail(VALUE self); 546static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask); 547static VALUE foleparam_input(VALUE self); 548static VALUE foleparam_output(VALUE self); 549static VALUE foleparam_optional(VALUE self); 550static VALUE foleparam_retval(VALUE self); 551static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index); 552static VALUE foleparam_default(VALUE self); 553static VALUE foleparam_inspect(VALUE self); 554static long ole_search_event_at(VALUE ary, VALUE ev); 555static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default); 556static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler); 557static void ole_delete_event(VALUE ary, VALUE ev); 558static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams); 559static VALUE hash2result(VALUE hash); 560static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams); 561static VALUE exec_callback(VALUE arg); 562static VALUE rescue_callback(VALUE arg); 563static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo); 564static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2); 565static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo); 566static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo); 567static void ole_event_free(struct oleeventdata *poleev); 568static VALUE fev_s_allocate(VALUE klass); 569static VALUE ev_advise(int argc, VALUE *argv, VALUE self); 570static VALUE fev_initialize(int argc, VALUE *argv, VALUE self); 571static VALUE fev_s_msg_loop(VALUE klass); 572static void add_event_call_back(VALUE obj, VALUE event, VALUE data); 573static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg); 574static VALUE fev_on_event(int argc, VALUE *argv, VALUE self); 575static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self); 576static VALUE fev_off_event(int argc, VALUE *argv, VALUE self); 577static VALUE fev_unadvise(VALUE self); 578static VALUE fev_set_handler(VALUE self, VALUE val); 579static VALUE fev_get_handler(VALUE self); 580static VALUE evs_push(VALUE ev); 581static VALUE evs_delete(long i); 582static VALUE evs_entry(long i); 583static VALUE evs_length(void); 584static void olevariant_free(struct olevariantdata *pvar); 585static VALUE folevariant_s_allocate(VALUE klass); 586static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt); 587static VALUE folevariant_initialize(VALUE self, VALUE args); 588static long *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa); 589static void unlock_safe_array(SAFEARRAY *psa); 590static SAFEARRAY *get_locked_safe_array(VALUE val); 591static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self); 592static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt); 593static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self); 594static VALUE folevariant_value(VALUE self); 595static VALUE folevariant_vartype(VALUE self); 596static VALUE folevariant_set_value(VALUE self, VALUE val); 597static void init_enc2cp(void); 598static void free_enc2cp(void); 599 600static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)( 601 IMessageFilter __RPC_FAR * This, 602 /* [in] */ REFIID riid, 603 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) 604{ 605 if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 606 || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0) 607 { 608 *ppvObject = &message_filter; 609 return S_OK; 610 } 611 return E_NOINTERFACE; 612} 613 614static ULONG (STDMETHODCALLTYPE mf_AddRef)( 615 IMessageFilter __RPC_FAR * This) 616{ 617 return 1; 618} 619 620static ULONG (STDMETHODCALLTYPE mf_Release)( 621 IMessageFilter __RPC_FAR * This) 622{ 623 return 1; 624} 625 626static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)( 627 IMessageFilter __RPC_FAR * pThis, 628 DWORD dwCallType, //Type of incoming call 629 HTASK threadIDCaller, //Task handle calling this task 630 DWORD dwTickCount, //Elapsed tick count 631 LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure 632 ) 633{ 634#ifdef DEBUG_MESSAGEFILTER 635 printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount); 636 fflush(stdout); 637#endif 638 switch (dwCallType) 639 { 640 case CALLTYPE_ASYNC: 641 case CALLTYPE_TOPLEVEL_CALLPENDING: 642 case CALLTYPE_ASYNC_CALLPENDING: 643 if (rb_during_gc()) { 644 return SERVERCALL_RETRYLATER; 645 } 646 break; 647 default: 648 break; 649 } 650 if (previous_filter) { 651 return previous_filter->lpVtbl->HandleInComingCall(previous_filter, 652 dwCallType, 653 threadIDCaller, 654 dwTickCount, 655 lpInterfaceInfo); 656 } 657 return SERVERCALL_ISHANDLED; 658} 659 660static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)( 661 IMessageFilter* pThis, 662 HTASK threadIDCallee, //Server task handle 663 DWORD dwTickCount, //Elapsed tick count 664 DWORD dwRejectType //Returned rejection message 665 ) 666{ 667 if (previous_filter) { 668 return previous_filter->lpVtbl->RetryRejectedCall(previous_filter, 669 threadIDCallee, 670 dwTickCount, 671 dwRejectType); 672 } 673 return 1000; 674} 675 676static DWORD (STDMETHODCALLTYPE mf_MessagePending)( 677 IMessageFilter* pThis, 678 HTASK threadIDCallee, //Called applications task handle 679 DWORD dwTickCount, //Elapsed tick count 680 DWORD dwPendingType //Call type 681 ) 682{ 683 if (rb_during_gc()) { 684 return PENDINGMSG_WAITNOPROCESS; 685 } 686 if (previous_filter) { 687 return previous_filter->lpVtbl->MessagePending(previous_filter, 688 threadIDCallee, 689 dwTickCount, 690 dwPendingType); 691 } 692 return PENDINGMSG_WAITNOPROCESS; 693} 694 695typedef struct _Win32OLEIDispatch 696{ 697 IDispatch dispatch; 698 ULONG refcount; 699 VALUE obj; 700} Win32OLEIDispatch; 701 702static HRESULT ( STDMETHODCALLTYPE QueryInterface )( 703 IDispatch __RPC_FAR * This, 704 /* [in] */ REFIID riid, 705 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) 706{ 707 if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 708 || MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0) 709 { 710 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 711 p->refcount++; 712 *ppvObject = This; 713 return S_OK; 714 } 715 return E_NOINTERFACE; 716} 717 718static ULONG ( STDMETHODCALLTYPE AddRef )( 719 IDispatch __RPC_FAR * This) 720{ 721 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 722 return ++(p->refcount); 723} 724 725static ULONG ( STDMETHODCALLTYPE Release )( 726 IDispatch __RPC_FAR * This) 727{ 728 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 729 ULONG u = --(p->refcount); 730 if (u == 0) { 731 st_data_t key = p->obj; 732 st_delete(DATA_PTR(com_hash), &key, 0); 733 free(p); 734 } 735 return u; 736} 737 738static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )( 739 IDispatch __RPC_FAR * This, 740 /* [out] */ UINT __RPC_FAR *pctinfo) 741{ 742 return E_NOTIMPL; 743} 744 745static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )( 746 IDispatch __RPC_FAR * This, 747 /* [in] */ UINT iTInfo, 748 /* [in] */ LCID lcid, 749 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo) 750{ 751 return E_NOTIMPL; 752} 753 754 755static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )( 756 IDispatch __RPC_FAR * This, 757 /* [in] */ REFIID riid, 758 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames, 759 /* [in] */ UINT cNames, 760 /* [in] */ LCID lcid, 761 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) 762{ 763 /* 764 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 765 */ 766 char* psz = ole_wc2mb(*rgszNames); // support only one method 767 *rgDispId = rb_intern(psz); 768 free(psz); 769 return S_OK; 770} 771 772static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )( 773 IDispatch __RPC_FAR * This, 774 /* [in] */ DISPID dispIdMember, 775 /* [in] */ REFIID riid, 776 /* [in] */ LCID lcid, 777 /* [in] */ WORD wFlags, 778 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams, 779 /* [out] */ VARIANT __RPC_FAR *pVarResult, 780 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo, 781 /* [out] */ UINT __RPC_FAR *puArgErr) 782{ 783 VALUE v; 784 int i; 785 int args = pDispParams->cArgs; 786 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 787 VALUE* parg = ALLOCA_N(VALUE, args); 788 for (i = 0; i < args; i++) { 789 *(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]); 790 } 791 if (dispIdMember == DISPID_VALUE) { 792 if (wFlags == DISPATCH_METHOD) { 793 dispIdMember = rb_intern("call"); 794 } else if (wFlags & DISPATCH_PROPERTYGET) { 795 dispIdMember = rb_intern("value"); 796 } 797 } 798 v = rb_funcall2(p->obj, dispIdMember, args, parg); 799 ole_val2variant(v, pVarResult); 800 return S_OK; 801} 802 803static IDispatch* 804val2dispatch(VALUE val) 805{ 806 struct st_table *tbl = DATA_PTR(com_hash); 807 Win32OLEIDispatch* pdisp; 808 st_data_t data; 809 810 if (st_lookup(tbl, val, &data)) { 811 pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG); 812 pdisp->refcount++; 813 } 814 else { 815 pdisp = ALLOC(Win32OLEIDispatch); 816 pdisp->dispatch.lpVtbl = &com_vtbl; 817 pdisp->refcount = 1; 818 pdisp->obj = val; 819 st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG); 820 } 821 return &pdisp->dispatch; 822} 823 824static double 825rbtime2vtdate(VALUE tmobj) 826{ 827 SYSTEMTIME st; 828 double t = 0; 829 memset(&st, 0, sizeof(SYSTEMTIME)); 830 st.wYear = FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0)); 831 st.wMonth = FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0)); 832 st.wDay = FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0)); 833 st.wHour = FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0)); 834 st.wMinute = FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0)); 835 st.wSecond = FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0)); 836 st.wMilliseconds = FIX2INT(rb_funcall(tmobj, rb_intern("nsec"), 0)) / 1000000; 837 SystemTimeToVariantTime(&st, &t); 838 return t; 839} 840 841static VALUE 842vtdate2rbtime(double date) 843{ 844 SYSTEMTIME st; 845 VALUE v; 846 VariantTimeToSystemTime(date, &st); 847 848 v = rb_funcall(rb_cTime, rb_intern("new"), 6, 849 INT2FIX(st.wYear), 850 INT2FIX(st.wMonth), 851 INT2FIX(st.wDay), 852 INT2FIX(st.wHour), 853 INT2FIX(st.wMinute), 854 INT2FIX(st.wSecond)); 855 if (st.wMilliseconds > 0) { 856 return rb_funcall(v, rb_intern("+"), 1, rb_float_new((double)(st.wMilliseconds / 1000.0))); 857 } 858 return v; 859} 860 861#define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp 862 863static UINT ole_encoding2cp(rb_encoding *enc) 864{ 865 /* 866 * Is there any better solution to convert 867 * Ruby encoding to Windows codepage??? 868 */ 869 ENC_MACHING_CP(enc, "Big5", 950); 870 ENC_MACHING_CP(enc, "CP51932", 51932); 871 ENC_MACHING_CP(enc, "CP850", 850); 872 ENC_MACHING_CP(enc, "CP852", 852); 873 ENC_MACHING_CP(enc, "CP855", 855); 874 ENC_MACHING_CP(enc, "CP949", 949); 875 ENC_MACHING_CP(enc, "EUC-JP", 20932); 876 ENC_MACHING_CP(enc, "EUC-KR", 51949); 877 ENC_MACHING_CP(enc, "EUC-TW", 51950); 878 ENC_MACHING_CP(enc, "GB18030", 54936); 879 ENC_MACHING_CP(enc, "GB2312", 20936); 880 ENC_MACHING_CP(enc, "GBK", 936); 881 ENC_MACHING_CP(enc, "IBM437", 437); 882 ENC_MACHING_CP(enc, "IBM737", 737); 883 ENC_MACHING_CP(enc, "IBM775", 775); 884 ENC_MACHING_CP(enc, "IBM852", 852); 885 ENC_MACHING_CP(enc, "IBM855", 855); 886 ENC_MACHING_CP(enc, "IBM857", 857); 887 ENC_MACHING_CP(enc, "IBM860", 860); 888 ENC_MACHING_CP(enc, "IBM861", 861); 889 ENC_MACHING_CP(enc, "IBM862", 862); 890 ENC_MACHING_CP(enc, "IBM863", 863); 891 ENC_MACHING_CP(enc, "IBM864", 864); 892 ENC_MACHING_CP(enc, "IBM865", 865); 893 ENC_MACHING_CP(enc, "IBM866", 866); 894 ENC_MACHING_CP(enc, "IBM869", 869); 895 ENC_MACHING_CP(enc, "ISO-2022-JP", 50220); 896 ENC_MACHING_CP(enc, "ISO-8859-1", 28591); 897 ENC_MACHING_CP(enc, "ISO-8859-15", 28605); 898 ENC_MACHING_CP(enc, "ISO-8859-2", 28592); 899 ENC_MACHING_CP(enc, "ISO-8859-3", 28593); 900 ENC_MACHING_CP(enc, "ISO-8859-4", 28594); 901 ENC_MACHING_CP(enc, "ISO-8859-5", 28595); 902 ENC_MACHING_CP(enc, "ISO-8859-6", 28596); 903 ENC_MACHING_CP(enc, "ISO-8859-7", 28597); 904 ENC_MACHING_CP(enc, "ISO-8859-8", 28598); 905 ENC_MACHING_CP(enc, "ISO-8859-9", 28599); 906 ENC_MACHING_CP(enc, "KOI8-R", 20866); 907 ENC_MACHING_CP(enc, "KOI8-U", 21866); 908 ENC_MACHING_CP(enc, "Shift_JIS", 932); 909 ENC_MACHING_CP(enc, "UTF-16BE", 1201); 910 ENC_MACHING_CP(enc, "UTF-16LE", 1200); 911 ENC_MACHING_CP(enc, "UTF-7", 65000); 912 ENC_MACHING_CP(enc, "UTF-8", 65001); 913 ENC_MACHING_CP(enc, "Windows-1250", 1250); 914 ENC_MACHING_CP(enc, "Windows-1251", 1251); 915 ENC_MACHING_CP(enc, "Windows-1252", 1252); 916 ENC_MACHING_CP(enc, "Windows-1253", 1253); 917 ENC_MACHING_CP(enc, "Windows-1254", 1254); 918 ENC_MACHING_CP(enc, "Windows-1255", 1255); 919 ENC_MACHING_CP(enc, "Windows-1256", 1256); 920 ENC_MACHING_CP(enc, "Windows-1257", 1257); 921 ENC_MACHING_CP(enc, "Windows-1258", 1258); 922 ENC_MACHING_CP(enc, "Windows-31J", 932); 923 ENC_MACHING_CP(enc, "Windows-874", 874); 924 ENC_MACHING_CP(enc, "eucJP-ms", 20932); 925 return CP_ACP; 926} 927 928static void 929failed_load_conv51932(void) 930{ 931 rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932"); 932} 933 934#ifndef pIMultiLanguage 935static void 936load_conv_function51932(void) 937{ 938 HRESULT hr = E_NOINTERFACE; 939 void *p; 940 if (!pIMultiLanguage) { 941#if defined(HAVE_TYPE_IMULTILANGUAGE2) 942 hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, 943 &IID_IMultiLanguage2, &p); 944#elif defined(HAVE_TYPE_IMULTILANGUAGE) 945 hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, 946 &IID_IMultiLanguage, &p); 947#endif 948 if (FAILED(hr)) { 949 failed_load_conv51932(); 950 } 951 pIMultiLanguage = p; 952 } 953} 954#else 955#define load_conv_function51932() failed_load_conv51932() 956#endif 957 958#define conv_51932(cp) ((cp) == 51932 && (load_conv_function51932(), 1)) 959 960static void 961set_ole_codepage(UINT cp) 962{ 963 if (code_page_installed(cp)) { 964 cWIN32OLE_cp = cp; 965 } else { 966 switch(cp) { 967 case CP_ACP: 968 case CP_OEMCP: 969 case CP_MACCP: 970 case CP_THREAD_ACP: 971 case CP_SYMBOL: 972 case CP_UTF7: 973 case CP_UTF8: 974 cWIN32OLE_cp = cp; 975 break; 976 case 51932: 977 cWIN32OLE_cp = cp; 978 load_conv_function51932(); 979 break; 980 default: 981 rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage."); 982 break; 983 } 984 } 985 cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp); 986} 987 988 989static UINT 990ole_init_cp(void) 991{ 992 UINT cp; 993 rb_encoding *encdef; 994 encdef = rb_default_internal_encoding(); 995 if (!encdef) { 996 encdef = rb_default_external_encoding(); 997 } 998 cp = ole_encoding2cp(encdef); 999 set_ole_codepage(cp); 1000 return cp; 1001} 1002 1003struct myCPINFOEX { 1004 UINT MaxCharSize; 1005 BYTE DefaultChar[2]; 1006 BYTE LeadByte[12]; 1007 WCHAR UnicodeDefaultChar; 1008 UINT CodePage; 1009 char CodePageName[MAX_PATH]; 1010}; 1011 1012static rb_encoding * 1013ole_cp2encoding(UINT cp) 1014{ 1015 static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL; 1016 struct myCPINFOEX* buf; 1017 VALUE enc_name; 1018 char *enc_cstr; 1019 int idx; 1020 1021 if (!code_page_installed(cp)) { 1022 switch(cp) { 1023 case CP_ACP: 1024 cp = GetACP(); 1025 break; 1026 case CP_OEMCP: 1027 cp = GetOEMCP(); 1028 break; 1029 case CP_MACCP: 1030 case CP_THREAD_ACP: 1031 if (!pGetCPInfoEx) { 1032 pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *)) 1033 GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx"); 1034 if (!pGetCPInfoEx) { 1035 pGetCPInfoEx = (void*)-1; 1036 } 1037 } 1038 buf = ALLOCA_N(struct myCPINFOEX, 1); 1039 ZeroMemory(buf, sizeof(struct myCPINFOEX)); 1040 if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) { 1041 rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding."); 1042 break; /* never reach here */ 1043 } 1044 cp = buf->CodePage; 1045 break; 1046 case CP_SYMBOL: 1047 case CP_UTF7: 1048 case CP_UTF8: 1049 break; 1050 case 51932: 1051 load_conv_function51932(); 1052 break; 1053 default: 1054 rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage."); 1055 break; 1056 } 1057 } 1058 1059 enc_name = rb_sprintf("CP%d", cp); 1060 idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name)); 1061 if (idx < 0) 1062 idx = rb_define_dummy_encoding(enc_cstr); 1063 return rb_enc_from_index(idx); 1064} 1065 1066static char * 1067ole_wc2mb(LPWSTR pw) 1068{ 1069 LPSTR pm; 1070 UINT size = 0; 1071 if (conv_51932(cWIN32OLE_cp)) { 1072#ifndef pIMultiLanguage 1073 DWORD dw = 0; 1074 HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage, 1075 &dw, cWIN32OLE_cp, pw, NULL, NULL, &size); 1076 if (FAILED(hr)) { 1077 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); 1078 } 1079 pm = ALLOC_N(char, size + 1); 1080 hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage, 1081 &dw, cWIN32OLE_cp, pw, NULL, pm, &size); 1082 if (FAILED(hr)) { 1083 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); 1084 } 1085 pm[size] = '\0'; 1086#endif 1087 return pm; 1088 } 1089 size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL); 1090 if (size) { 1091 pm = ALLOC_N(char, size + 1); 1092 WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, pm, size, NULL, NULL); 1093 pm[size] = '\0'; 1094 } 1095 else { 1096 pm = ALLOC_N(char, 1); 1097 *pm = '\0'; 1098 } 1099 return pm; 1100} 1101 1102static VALUE 1103ole_hresult2msg(HRESULT hr) 1104{ 1105 VALUE msg = Qnil; 1106 char *p_msg = NULL; 1107 char *term = NULL; 1108 DWORD dwCount; 1109 1110 char strhr[100]; 1111 sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr); 1112 msg = rb_str_new2(strhr); 1113 dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 1114 FORMAT_MESSAGE_FROM_SYSTEM | 1115 FORMAT_MESSAGE_IGNORE_INSERTS, 1116 NULL, hr, 1117 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 1118 (LPTSTR)&p_msg, 0, NULL); 1119 if (dwCount == 0) { 1120 dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 1121 FORMAT_MESSAGE_FROM_SYSTEM | 1122 FORMAT_MESSAGE_IGNORE_INSERTS, 1123 NULL, hr, cWIN32OLE_lcid, 1124 (LPTSTR)&p_msg, 0, NULL); 1125 } 1126 if (dwCount > 0) { 1127 term = p_msg + strlen(p_msg); 1128 while (p_msg < term) { 1129 term--; 1130 if (*term == '\r' || *term == '\n') 1131 *term = '\0'; 1132 else break; 1133 } 1134 if (p_msg[0] != '\0') { 1135 rb_str_cat2(msg, p_msg); 1136 } 1137 } 1138 LocalFree(p_msg); 1139 return msg; 1140} 1141 1142static void 1143ole_freeexceptinfo(EXCEPINFO *pExInfo) 1144{ 1145 SysFreeString(pExInfo->bstrDescription); 1146 SysFreeString(pExInfo->bstrSource); 1147 SysFreeString(pExInfo->bstrHelpFile); 1148} 1149 1150static VALUE 1151ole_excepinfo2msg(EXCEPINFO *pExInfo) 1152{ 1153 char error_code[40]; 1154 char *pSource = NULL; 1155 char *pDescription = NULL; 1156 VALUE error_msg; 1157 if(pExInfo->pfnDeferredFillIn != NULL) { 1158 (*pExInfo->pfnDeferredFillIn)(pExInfo); 1159 } 1160 if (pExInfo->bstrSource != NULL) { 1161 pSource = ole_wc2mb(pExInfo->bstrSource); 1162 } 1163 if (pExInfo->bstrDescription != NULL) { 1164 pDescription = ole_wc2mb(pExInfo->bstrDescription); 1165 } 1166 if(pExInfo->wCode == 0) { 1167 sprintf(error_code, "\n OLE error code:%lX in ", pExInfo->scode); 1168 } 1169 else{ 1170 sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode); 1171 } 1172 error_msg = rb_str_new2(error_code); 1173 if(pSource != NULL) { 1174 rb_str_cat(error_msg, pSource, strlen(pSource)); 1175 } 1176 else { 1177 rb_str_cat(error_msg, "<Unknown>", 9); 1178 } 1179 rb_str_cat2(error_msg, "\n "); 1180 if(pDescription != NULL) { 1181 rb_str_cat2(error_msg, pDescription); 1182 } 1183 else { 1184 rb_str_cat2(error_msg, "<No Description>"); 1185 } 1186 if(pSource) free(pSource); 1187 if(pDescription) free(pDescription); 1188 ole_freeexceptinfo(pExInfo); 1189 return error_msg; 1190} 1191 1192static void 1193ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...) 1194{ 1195 va_list args; 1196 VALUE msg; 1197 VALUE err_msg; 1198 va_init_list(args, fmt); 1199 msg = rb_vsprintf(fmt, args); 1200 va_end(args); 1201 1202 err_msg = ole_hresult2msg(hr); 1203 if(err_msg != Qnil) { 1204 rb_str_cat2(msg, "\n"); 1205 rb_str_append(msg, err_msg); 1206 } 1207 rb_exc_raise(rb_exc_new3(ecs, msg)); 1208} 1209 1210void 1211ole_uninitialize(void) 1212{ 1213 if (!g_ole_initialized) return; 1214 OleUninitialize(); 1215 g_ole_initialized_set(FALSE); 1216} 1217 1218static void 1219ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass) 1220{ 1221 ole_uninitialize(); 1222} 1223 1224static void 1225ole_initialize(void) 1226{ 1227 HRESULT hr; 1228 1229 if(!g_uninitialize_hooked) { 1230 rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil); 1231 g_uninitialize_hooked = TRUE; 1232 } 1233 1234 if(g_ole_initialized == FALSE) { 1235 hr = OleInitialize(NULL); 1236 if(FAILED(hr)) { 1237 ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize"); 1238 } 1239 g_ole_initialized_set(TRUE); 1240 1241 hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter); 1242 if(FAILED(hr)) { 1243 previous_filter = NULL; 1244 ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter"); 1245 } 1246 } 1247} 1248 1249static void 1250ole_msg_loop() { 1251 MSG msg; 1252 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { 1253 TranslateMessage(&msg); 1254 DispatchMessage(&msg); 1255 } 1256} 1257 1258static void 1259ole_free(struct oledata *pole) 1260{ 1261 OLE_FREE(pole->pDispatch); 1262 free(pole); 1263} 1264 1265static void 1266oletypelib_free(struct oletypelibdata *poletypelib) 1267{ 1268 OLE_FREE(poletypelib->pTypeLib); 1269 free(poletypelib); 1270} 1271 1272static void 1273oletype_free(struct oletypedata *poletype) 1274{ 1275 OLE_FREE(poletype->pTypeInfo); 1276 free(poletype); 1277} 1278 1279static void 1280olemethod_free(struct olemethoddata *polemethod) 1281{ 1282 OLE_FREE(polemethod->pTypeInfo); 1283 OLE_FREE(polemethod->pOwnerTypeInfo); 1284 free(polemethod); 1285} 1286 1287static void 1288olevariable_free(struct olevariabledata *polevar) 1289{ 1290 OLE_FREE(polevar->pTypeInfo); 1291 free(polevar); 1292} 1293 1294static void 1295oleparam_free(struct oleparamdata *pole) 1296{ 1297 OLE_FREE(pole->pTypeInfo); 1298 free(pole); 1299} 1300 1301 1302static LPWSTR 1303ole_vstr2wc(VALUE vstr) 1304{ 1305 rb_encoding *enc; 1306 int cp; 1307 UINT size = 0; 1308 LPWSTR pw; 1309 st_data_t data; 1310 enc = rb_enc_get(vstr); 1311 1312 if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) { 1313 cp = data; 1314 } else { 1315 cp = ole_encoding2cp(enc); 1316 if (code_page_installed(cp) || 1317 cp == CP_ACP || 1318 cp == CP_OEMCP || 1319 cp == CP_MACCP || 1320 cp == CP_THREAD_ACP || 1321 cp == CP_SYMBOL || 1322 cp == CP_UTF7 || 1323 cp == CP_UTF8 || 1324 cp == 51932) { 1325 st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp); 1326 } else { 1327 rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc)); 1328 } 1329 } 1330 if (conv_51932(cp)) { 1331#ifndef pIMultiLanguage 1332 DWORD dw = 0; 1333 UINT len = RSTRING_LENINT(vstr); 1334 HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 1335 &dw, cp, RSTRING_PTR(vstr), &len, NULL, &size); 1336 if (FAILED(hr)) { 1337 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp); 1338 } 1339 pw = SysAllocStringLen(NULL, size); 1340 len = RSTRING_LEN(vstr); 1341 hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 1342 &dw, cp, RSTRING_PTR(vstr), &len, pw, &size); 1343 if (FAILED(hr)) { 1344 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp); 1345 } 1346#endif 1347 return pw; 1348 } 1349 size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0); 1350 pw = SysAllocStringLen(NULL, size); 1351 MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size); 1352 return pw; 1353} 1354 1355static LPWSTR 1356ole_mb2wc(char *pm, int len) 1357{ 1358 UINT size = 0; 1359 LPWSTR pw; 1360 1361 if (conv_51932(cWIN32OLE_cp)) { 1362#ifndef pIMultiLanguage 1363 DWORD dw = 0; 1364 UINT n = len; 1365 HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 1366 &dw, cWIN32OLE_cp, pm, &n, NULL, &size); 1367 if (FAILED(hr)) { 1368 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp); 1369 } 1370 pw = SysAllocStringLen(NULL, size); 1371 hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 1372 &dw, cWIN32OLE_cp, pm, &n, pw, &size); 1373 if (FAILED(hr)) { 1374 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp); 1375 } 1376#endif 1377 return pw; 1378 } 1379 size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0); 1380 pw = SysAllocStringLen(NULL, size - 1); 1381 MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size); 1382 return pw; 1383} 1384 1385static VALUE 1386ole_wc2vstr(LPWSTR pw, BOOL isfree) 1387{ 1388 char *p = ole_wc2mb(pw); 1389 VALUE vstr = rb_enc_str_new(p, strlen(p), cWIN32OLE_enc); 1390 if(isfree) 1391 SysFreeString(pw); 1392 free(p); 1393 return vstr; 1394} 1395 1396static VALUE 1397ole_ary_m_entry(VALUE val, long *pid) 1398{ 1399 VALUE obj = Qnil; 1400 int i = 0; 1401 obj = val; 1402 while(TYPE(obj) == T_ARRAY) { 1403 obj = rb_ary_entry(obj, pid[i]); 1404 i++; 1405 } 1406 return obj; 1407} 1408 1409static void * 1410get_ptr_of_variant(VARIANT *pvar) 1411{ 1412 switch(V_VT(pvar)) { 1413 case VT_UI1: 1414 return &V_UI1(pvar); 1415 break; 1416 case VT_I2: 1417 return &V_I2(pvar); 1418 break; 1419 case VT_UI2: 1420 return &V_UI2(pvar); 1421 break; 1422 case VT_I4: 1423 return &V_I4(pvar); 1424 break; 1425 case VT_UI4: 1426 return &V_UI4(pvar); 1427 break; 1428 case VT_R4: 1429 return &V_R4(pvar); 1430 break; 1431 case VT_R8: 1432 return &V_R8(pvar); 1433 break; 1434#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 1435 case VT_I8: 1436 return &V_I8(pvar); 1437 break; 1438 case VT_UI8: 1439 return &V_UI8(pvar); 1440 break; 1441#endif 1442 case VT_INT: 1443 return &V_INT(pvar); 1444 break; 1445 case VT_UINT: 1446 return &V_UINT(pvar); 1447 break; 1448 case VT_CY: 1449 return &V_CY(pvar); 1450 break; 1451 case VT_DATE: 1452 return &V_DATE(pvar); 1453 break; 1454 case VT_BSTR: 1455 return V_BSTR(pvar); 1456 break; 1457 case VT_DISPATCH: 1458 return V_DISPATCH(pvar); 1459 break; 1460 case VT_ERROR: 1461 return &V_ERROR(pvar); 1462 break; 1463 case VT_BOOL: 1464 return &V_BOOL(pvar); 1465 break; 1466 case VT_UNKNOWN: 1467 return V_UNKNOWN(pvar); 1468 break; 1469 case VT_ARRAY: 1470 return &V_ARRAY(pvar); 1471 break; 1472 default: 1473 return NULL; 1474 break; 1475 } 1476} 1477 1478static VALUE 1479is_all_index_under(long *pid, long *pub, long dim) 1480{ 1481 long i = 0; 1482 for (i = 0; i < dim; i++) { 1483 if (pid[i] > pub[i]) { 1484 return Qfalse; 1485 } 1486 } 1487 return Qtrue; 1488} 1489 1490static void 1491ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt) 1492{ 1493 VALUE val1; 1494 HRESULT hr = S_OK; 1495 VARIANT var; 1496 VOID *p = NULL; 1497 long i = n; 1498 while(i >= 0) { 1499 val1 = ole_ary_m_entry(val, pid); 1500 VariantInit(&var); 1501 p = val2variant_ptr(val1, &var, vt); 1502 if (is_all_index_under(pid, pub, dim) == Qtrue) { 1503 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || 1504 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { 1505 rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface"); 1506 } 1507 hr = SafeArrayPutElement(psa, pid, p); 1508 } 1509 if (FAILED(hr)) { 1510 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement"); 1511 } 1512 pid[i] += 1; 1513 if (pid[i] > pub[i]) { 1514 pid[i] = 0; 1515 i -= 1; 1516 } else { 1517 i = dim - 1; 1518 } 1519 } 1520} 1521 1522static long 1523dimension(VALUE val) { 1524 long dim = 0; 1525 long dim1 = 0; 1526 long len = 0; 1527 long i = 0; 1528 if (TYPE(val) == T_ARRAY) { 1529 len = RARRAY_LEN(val); 1530 for (i = 0; i < len; i++) { 1531 dim1 = dimension(rb_ary_entry(val, i)); 1532 if (dim < dim1) { 1533 dim = dim1; 1534 } 1535 } 1536 dim += 1; 1537 } 1538 return dim; 1539} 1540 1541static long 1542ary_len_of_dim(VALUE ary, long dim) { 1543 long ary_len = 0; 1544 long ary_len1 = 0; 1545 long len = 0; 1546 long i = 0; 1547 VALUE val; 1548 if (dim == 0) { 1549 if (TYPE(ary) == T_ARRAY) { 1550 ary_len = RARRAY_LEN(ary); 1551 } 1552 } else { 1553 if (TYPE(ary) == T_ARRAY) { 1554 len = RARRAY_LEN(ary); 1555 for (i = 0; i < len; i++) { 1556 val = rb_ary_entry(ary, i); 1557 ary_len1 = ary_len_of_dim(val, dim-1); 1558 if (ary_len < ary_len1) { 1559 ary_len = ary_len1; 1560 } 1561 } 1562 } 1563 } 1564 return ary_len; 1565} 1566 1567static HRESULT 1568ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt) 1569{ 1570 long dim = 0; 1571 int i = 0; 1572 HRESULT hr = S_OK; 1573 1574 SAFEARRAYBOUND *psab = NULL; 1575 SAFEARRAY *psa = NULL; 1576 long *pub, *pid; 1577 1578 Check_Type(val, T_ARRAY); 1579 1580 dim = dimension(val); 1581 1582 psab = ALLOC_N(SAFEARRAYBOUND, dim); 1583 pub = ALLOC_N(long, dim); 1584 pid = ALLOC_N(long, dim); 1585 1586 if(!psab || !pub || !pid) { 1587 if(pub) free(pub); 1588 if(psab) free(psab); 1589 if(pid) free(pid); 1590 rb_raise(rb_eRuntimeError, "memory allocation error"); 1591 } 1592 1593 for (i = 0; i < dim; i++) { 1594 psab[i].cElements = ary_len_of_dim(val, i); 1595 psab[i].lLbound = 0; 1596 pub[i] = psab[i].cElements - 1; 1597 pid[i] = 0; 1598 } 1599 /* Create and fill VARIANT array */ 1600 if ((vt & ~VT_BYREF) == VT_ARRAY) { 1601 vt = (vt | VT_VARIANT); 1602 } 1603 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); 1604 if (psa == NULL) 1605 hr = E_OUTOFMEMORY; 1606 else 1607 hr = SafeArrayLock(psa); 1608 if (SUCCEEDED(hr)) { 1609 ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK)); 1610 hr = SafeArrayUnlock(psa); 1611 } 1612 1613 if(pub) free(pub); 1614 if(psab) free(psab); 1615 if(pid) free(pid); 1616 1617 if (SUCCEEDED(hr)) { 1618 V_VT(var) = vt; 1619 V_ARRAY(var) = psa; 1620 } 1621 else { 1622 if (psa != NULL) 1623 SafeArrayDestroy(psa); 1624 } 1625 return hr; 1626} 1627 1628static void 1629ole_val2variant(VALUE val, VARIANT *var) 1630{ 1631 struct oledata *pole; 1632 struct olevariantdata *pvar; 1633 if(rb_obj_is_kind_of(val, cWIN32OLE)) { 1634 Data_Get_Struct(val, struct oledata, pole); 1635 OLE_ADDREF(pole->pDispatch); 1636 V_VT(var) = VT_DISPATCH; 1637 V_DISPATCH(var) = pole->pDispatch; 1638 return; 1639 } 1640 if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) { 1641 Data_Get_Struct(val, struct olevariantdata, pvar); 1642 VariantCopy(var, &(pvar->var)); 1643 return; 1644 } 1645 1646 if (rb_obj_is_kind_of(val, rb_cTime)) { 1647 V_VT(var) = VT_DATE; 1648 V_DATE(var) = rbtime2vtdate(val); 1649 return; 1650 } 1651 switch (TYPE(val)) { 1652 case T_ARRAY: 1653 ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY); 1654 break; 1655 case T_STRING: 1656 V_VT(var) = VT_BSTR; 1657 V_BSTR(var) = ole_vstr2wc(val); 1658 break; 1659 case T_FIXNUM: 1660 V_VT(var) = VT_I4; 1661 V_I4(var) = NUM2INT(val); 1662 break; 1663 case T_BIGNUM: 1664 V_VT(var) = VT_R8; 1665 V_R8(var) = rb_big2dbl(val); 1666 break; 1667 case T_FLOAT: 1668 V_VT(var) = VT_R8; 1669 V_R8(var) = NUM2DBL(val); 1670 break; 1671 case T_TRUE: 1672 V_VT(var) = VT_BOOL; 1673 V_BOOL(var) = VARIANT_TRUE; 1674 break; 1675 case T_FALSE: 1676 V_VT(var) = VT_BOOL; 1677 V_BOOL(var) = VARIANT_FALSE; 1678 break; 1679 case T_NIL: 1680 if (g_nil_to == VT_ERROR) { 1681 V_VT(var) = VT_ERROR; 1682 V_ERROR(var) = DISP_E_PARAMNOTFOUND; 1683 }else { 1684 V_VT(var) = VT_EMPTY; 1685 } 1686 break; 1687 default: 1688 V_VT(var) = VT_DISPATCH; 1689 V_DISPATCH(var) = val2dispatch(val); 1690 break; 1691 } 1692} 1693 1694static void 1695ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt) 1696{ 1697 if (val == Qnil) { 1698 if (vt == VT_VARIANT) { 1699 ole_val2variant2(val, var); 1700 } else { 1701 V_VT(var) = (vt & ~VT_BYREF); 1702 if (V_VT(var) == VT_DISPATCH) { 1703 V_DISPATCH(var) = NULL; 1704 } else if (V_VT(var) == VT_UNKNOWN) { 1705 V_UNKNOWN(var) = NULL; 1706 } 1707 } 1708 return; 1709 } 1710#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 1711 switch(vt & ~VT_BYREF) { 1712 case VT_I8: 1713 V_VT(var) = VT_I8; 1714 V_I8(var) = NUM2I8 (val); 1715 break; 1716 case VT_UI8: 1717 V_VT(var) = VT_UI8; 1718 V_UI8(var) = NUM2UI8(val); 1719 break; 1720 default: 1721 ole_val2variant2(val, var); 1722 break; 1723 } 1724#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ 1725 ole_val2variant2(val, var); 1726#endif 1727} 1728 1729static void 1730ole_val2ptr_variant(VALUE val, VARIANT *var) 1731{ 1732 switch (TYPE(val)) { 1733 case T_STRING: 1734 if (V_VT(var) == (VT_BSTR | VT_BYREF)) { 1735 *V_BSTRREF(var) = ole_vstr2wc(val); 1736 } 1737 break; 1738 case T_FIXNUM: 1739 switch(V_VT(var)) { 1740 case (VT_UI1 | VT_BYREF) : 1741 *V_UI1REF(var) = NUM2CHR(val); 1742 break; 1743 case (VT_I2 | VT_BYREF) : 1744 *V_I2REF(var) = (short)NUM2INT(val); 1745 break; 1746 case (VT_I4 | VT_BYREF) : 1747 *V_I4REF(var) = NUM2INT(val); 1748 break; 1749 case (VT_R4 | VT_BYREF) : 1750 *V_R4REF(var) = (float)NUM2INT(val); 1751 break; 1752 case (VT_R8 | VT_BYREF) : 1753 *V_R8REF(var) = NUM2INT(val); 1754 break; 1755 default: 1756 break; 1757 } 1758 break; 1759 case T_FLOAT: 1760 switch(V_VT(var)) { 1761 case (VT_I2 | VT_BYREF) : 1762 *V_I2REF(var) = (short)NUM2INT(val); 1763 break; 1764 case (VT_I4 | VT_BYREF) : 1765 *V_I4REF(var) = NUM2INT(val); 1766 break; 1767 case (VT_R4 | VT_BYREF) : 1768 *V_R4REF(var) = (float)NUM2DBL(val); 1769 break; 1770 case (VT_R8 | VT_BYREF) : 1771 *V_R8REF(var) = NUM2DBL(val); 1772 break; 1773 default: 1774 break; 1775 } 1776 break; 1777 case T_BIGNUM: 1778 if (V_VT(var) == (VT_R8 | VT_BYREF)) { 1779 *V_R8REF(var) = rb_big2dbl(val); 1780 } 1781 break; 1782 case T_TRUE: 1783 if (V_VT(var) == (VT_BOOL | VT_BYREF)) { 1784 *V_BOOLREF(var) = VARIANT_TRUE; 1785 } 1786 break; 1787 case T_FALSE: 1788 if (V_VT(var) == (VT_BOOL | VT_BYREF)) { 1789 *V_BOOLREF(var) = VARIANT_FALSE; 1790 } 1791 break; 1792 default: 1793 break; 1794 } 1795} 1796 1797static void 1798ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt) 1799{ 1800 V_VT(var) = vt; 1801 if (vt == (VT_VARIANT|VT_BYREF)) { 1802 V_VARIANTREF(var) = realvar; 1803 } else { 1804 if (V_VT(realvar) != (vt & ~VT_BYREF)) { 1805 rb_raise(eWIN32OLERuntimeError, "variant type mismatch"); 1806 } 1807 switch(vt & ~VT_BYREF) { 1808 case VT_I1: 1809 V_I1REF(var) = &V_I1(realvar); 1810 break; 1811 case VT_UI1: 1812 V_UI1REF(var) = &V_UI1(realvar); 1813 break; 1814 case VT_I2: 1815 V_I2REF(var) = &V_I2(realvar); 1816 break; 1817 case VT_UI2: 1818 V_UI2REF(var) = &V_UI2(realvar); 1819 break; 1820 case VT_I4: 1821 V_I4REF(var) = &V_I4(realvar); 1822 break; 1823 case VT_UI4: 1824 V_UI4REF(var) = &V_UI4(realvar); 1825 break; 1826 case VT_R4: 1827 V_R4REF(var) = &V_R4(realvar); 1828 break; 1829 case VT_R8: 1830 V_R8REF(var) = &V_R8(realvar); 1831 break; 1832 1833#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 1834#ifdef V_I8REF 1835 case VT_I8: 1836 V_I8REF(var) = &V_I8(realvar); 1837 break; 1838#endif 1839#ifdef V_UI8REF 1840 case VT_UI8: 1841 V_UI8REF(var) = &V_UI8(realvar); 1842 break; 1843#endif 1844#endif 1845 case VT_INT: 1846 V_INTREF(var) = &V_INT(realvar); 1847 break; 1848 1849 case VT_UINT: 1850 V_UINTREF(var) = &V_UINT(realvar); 1851 break; 1852 1853 case VT_CY: 1854 V_CYREF(var) = &V_CY(realvar); 1855 break; 1856 case VT_DATE: 1857 V_DATEREF(var) = &V_DATE(realvar); 1858 break; 1859 case VT_BSTR: 1860 V_BSTRREF(var) = &V_BSTR(realvar); 1861 break; 1862 case VT_DISPATCH: 1863 V_DISPATCHREF(var) = &V_DISPATCH(realvar); 1864 break; 1865 case VT_ERROR: 1866 V_ERRORREF(var) = &V_ERROR(realvar); 1867 break; 1868 case VT_BOOL: 1869 V_BOOLREF(var) = &V_BOOL(realvar); 1870 break; 1871 case VT_UNKNOWN: 1872 V_UNKNOWNREF(var) = &V_UNKNOWN(realvar); 1873 break; 1874 case VT_ARRAY: 1875 V_ARRAYREF(var) = &V_ARRAY(realvar); 1876 break; 1877 default: 1878 rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt); 1879 break; 1880 } 1881 } 1882} 1883 1884static void 1885ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar) 1886{ 1887 HRESULT hr = S_OK; 1888 1889 if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && TYPE(val) == T_STRING) { 1890 long len = RSTRING_LEN(val); 1891 void *pdest = NULL; 1892 SAFEARRAY *p = NULL; 1893 SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len); 1894 if (!psa) { 1895 rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector"); 1896 } 1897 hr = SafeArrayAccessData(psa, &pdest); 1898 if (SUCCEEDED(hr)) { 1899 memcpy(pdest, RSTRING_PTR(val), len); 1900 SafeArrayUnaccessData(psa); 1901 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); 1902 p = V_ARRAY(&(pvar->realvar)); 1903 if (p != NULL) { 1904 SafeArrayDestroy(p); 1905 } 1906 V_ARRAY(&(pvar->realvar)) = psa; 1907 if (vt & VT_BYREF) { 1908 V_VT(&(pvar->var)) = vt; 1909 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 1910 } else { 1911 hr = VariantCopy(&(pvar->var), &(pvar->realvar)); 1912 } 1913 } else { 1914 if (psa) 1915 SafeArrayDestroy(psa); 1916 } 1917 } else if (vt & VT_ARRAY) { 1918 if (val == Qnil) { 1919 V_VT(&(pvar->var)) = vt; 1920 if (vt & VT_BYREF) { 1921 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 1922 } 1923 } else { 1924 hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); 1925 if (SUCCEEDED(hr)) { 1926 if (vt & VT_BYREF) { 1927 V_VT(&(pvar->var)) = vt; 1928 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 1929 } else { 1930 hr = VariantCopy(&(pvar->var), &(pvar->realvar)); 1931 } 1932 } 1933 } 1934#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 1935 } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) { 1936 ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF)); 1937 ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF)); 1938 V_VT(&(pvar->var)) = vt; 1939 if (vt & VT_BYREF) { 1940 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 1941 } 1942#endif 1943 } else { 1944 if (val == Qnil) { 1945 V_VT(&(pvar->var)) = vt; 1946 if (vt == (VT_BYREF | VT_VARIANT)) { 1947 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 1948 } else { 1949 V_VT(&(pvar->realvar)) = vt & ~VT_BYREF; 1950 if (vt & VT_BYREF) { 1951 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 1952 } 1953 } 1954 } else { 1955 ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); 1956 if (vt == (VT_BYREF | VT_VARIANT)) { 1957 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 1958 } else if (vt & VT_BYREF) { 1959 if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) { 1960 hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar), 1961 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); 1962 } 1963 if (SUCCEEDED(hr)) { 1964 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 1965 } 1966 } else { 1967 if (vt == V_VT(&(pvar->realvar))) { 1968 hr = VariantCopy(&(pvar->var), &(pvar->realvar)); 1969 } else { 1970 hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar), 1971 cWIN32OLE_lcid, 0, vt); 1972 } 1973 } 1974 } 1975 } 1976 if (FAILED(hr)) { 1977 ole_raise(hr, eWIN32OLERuntimeError, "failed to change type"); 1978 } 1979} 1980 1981static void 1982ole_val2variant2(VALUE val, VARIANT *var) 1983{ 1984 g_nil_to = VT_EMPTY; 1985 ole_val2variant(val, var); 1986 g_nil_to = VT_ERROR; 1987} 1988 1989static VALUE 1990make_inspect(const char *class_name, VALUE detail) 1991{ 1992 VALUE str; 1993 str = rb_str_new2("#<"); 1994 rb_str_cat2(str, class_name); 1995 rb_str_cat2(str, ":"); 1996 rb_str_concat(str, detail); 1997 rb_str_cat2(str, ">"); 1998 return str; 1999} 2000 2001static VALUE 2002default_inspect(VALUE self, const char *class_name) 2003{ 2004 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0); 2005 return make_inspect(class_name, detail); 2006} 2007 2008static VALUE 2009ole_set_member(VALUE self, IDispatch *dispatch) 2010{ 2011 struct oledata *pole; 2012 Data_Get_Struct(self, struct oledata, pole); 2013 if (pole->pDispatch) { 2014 OLE_RELEASE(pole->pDispatch); 2015 pole->pDispatch = NULL; 2016 } 2017 pole->pDispatch = dispatch; 2018 return self; 2019} 2020 2021 2022static VALUE 2023fole_s_allocate(VALUE klass) 2024{ 2025 struct oledata *pole; 2026 VALUE obj; 2027 ole_initialize(); 2028 obj = Data_Make_Struct(klass,struct oledata,0,ole_free,pole); 2029 pole->pDispatch = NULL; 2030 return obj; 2031} 2032 2033static VALUE 2034create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv) 2035{ 2036 VALUE obj = fole_s_allocate(klass); 2037 ole_set_member(obj, pDispatch); 2038 return obj; 2039} 2040 2041static VALUE 2042ary_new_dim(VALUE myary, long *pid, long *plb, long dim) { 2043 long i; 2044 VALUE obj = Qnil; 2045 VALUE pobj = Qnil; 2046 long *ids = ALLOC_N(long, dim); 2047 if (!ids) { 2048 rb_raise(rb_eRuntimeError, "memory allocation error"); 2049 } 2050 for(i = 0; i < dim; i++) { 2051 ids[i] = pid[i] - plb[i]; 2052 } 2053 obj = myary; 2054 pobj = myary; 2055 for(i = 0; i < dim-1; i++) { 2056 obj = rb_ary_entry(pobj, ids[i]); 2057 if (obj == Qnil) { 2058 rb_ary_store(pobj, ids[i], rb_ary_new()); 2059 } 2060 obj = rb_ary_entry(pobj, ids[i]); 2061 pobj = obj; 2062 } 2063 if (ids) free(ids); 2064 return obj; 2065} 2066 2067static void 2068ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val) { 2069 long id = pid[dim - 1] - plb[dim - 1]; 2070 VALUE obj = ary_new_dim(myary, pid, plb, dim); 2071 rb_ary_store(obj, id, val); 2072} 2073 2074static VALUE 2075ole_variant2val(VARIANT *pvar) 2076{ 2077 VALUE obj = Qnil; 2078 HRESULT hr; 2079 while ( V_VT(pvar) == (VT_BYREF | VT_VARIANT) ) 2080 pvar = V_VARIANTREF(pvar); 2081 2082 if(V_ISARRAY(pvar)) { 2083 SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar); 2084 UINT i = 0; 2085 long *pid, *plb, *pub; 2086 VARIANT variant; 2087 VALUE val; 2088 UINT dim = 0; 2089 if (!psa) { 2090 return obj; 2091 } 2092 dim = SafeArrayGetDim(psa); 2093 VariantInit(&variant); 2094 V_VT(&variant) = (V_VT(pvar) & ~VT_ARRAY) | VT_BYREF; 2095 2096 pid = ALLOC_N(long, dim); 2097 plb = ALLOC_N(long, dim); 2098 pub = ALLOC_N(long, dim); 2099 2100 if(!pid || !plb || !pub) { 2101 if(pid) free(pid); 2102 if(plb) free(plb); 2103 if(pub) free(pub); 2104 rb_raise(rb_eRuntimeError, "memory allocation error"); 2105 } 2106 2107 for(i = 0; i < dim; ++i) { 2108 SafeArrayGetLBound(psa, i+1, &plb[i]); 2109 SafeArrayGetLBound(psa, i+1, &pid[i]); 2110 SafeArrayGetUBound(psa, i+1, &pub[i]); 2111 } 2112 hr = SafeArrayLock(psa); 2113 if (SUCCEEDED(hr)) { 2114 obj = rb_ary_new(); 2115 i = 0; 2116 while (i < dim) { 2117 ary_new_dim(obj, pid, plb, dim); 2118 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); 2119 if (SUCCEEDED(hr)) { 2120 val = ole_variant2val(&variant); 2121 ary_store_dim(obj, pid, plb, dim, val); 2122 } 2123 for (i = 0; i < dim; ++i) { 2124 if (++pid[i] <= pub[i]) 2125 break; 2126 pid[i] = plb[i]; 2127 } 2128 } 2129 SafeArrayUnlock(psa); 2130 } 2131 if(pid) free(pid); 2132 if(plb) free(plb); 2133 if(pub) free(pub); 2134 return obj; 2135 } 2136 switch(V_VT(pvar) & ~VT_BYREF){ 2137 case VT_EMPTY: 2138 break; 2139 case VT_NULL: 2140 break; 2141 case VT_I1: 2142 if(V_ISBYREF(pvar)) 2143 obj = INT2NUM((long)*V_I1REF(pvar)); 2144 else 2145 obj = INT2NUM((long)V_I1(pvar)); 2146 break; 2147 2148 case VT_UI1: 2149 if(V_ISBYREF(pvar)) 2150 obj = INT2NUM((long)*V_UI1REF(pvar)); 2151 else 2152 obj = INT2NUM((long)V_UI1(pvar)); 2153 break; 2154 2155 case VT_I2: 2156 if(V_ISBYREF(pvar)) 2157 obj = INT2NUM((long)*V_I2REF(pvar)); 2158 else 2159 obj = INT2NUM((long)V_I2(pvar)); 2160 break; 2161 2162 case VT_UI2: 2163 if(V_ISBYREF(pvar)) 2164 obj = INT2NUM((long)*V_UI2REF(pvar)); 2165 else 2166 obj = INT2NUM((long)V_UI2(pvar)); 2167 break; 2168 2169 case VT_I4: 2170 if(V_ISBYREF(pvar)) 2171 obj = INT2NUM((long)*V_I4REF(pvar)); 2172 else 2173 obj = INT2NUM((long)V_I4(pvar)); 2174 break; 2175 2176 case VT_UI4: 2177 if(V_ISBYREF(pvar)) 2178 obj = INT2NUM((long)*V_UI4REF(pvar)); 2179 else 2180 obj = INT2NUM((long)V_UI4(pvar)); 2181 break; 2182 2183 case VT_INT: 2184 if(V_ISBYREF(pvar)) 2185 obj = INT2NUM((long)*V_INTREF(pvar)); 2186 else 2187 obj = INT2NUM((long)V_INT(pvar)); 2188 break; 2189 2190 case VT_UINT: 2191 if(V_ISBYREF(pvar)) 2192 obj = INT2NUM((long)*V_UINTREF(pvar)); 2193 else 2194 obj = INT2NUM((long)V_UINT(pvar)); 2195 break; 2196 2197#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 2198 case VT_I8: 2199 if(V_ISBYREF(pvar)) 2200#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 2201#ifdef V_I8REF 2202 obj = I8_2_NUM(*V_I8REF(pvar)); 2203#endif 2204#else 2205 obj = Qnil; 2206#endif 2207 else 2208 obj = I8_2_NUM(V_I8(pvar)); 2209 break; 2210 case VT_UI8: 2211 if(V_ISBYREF(pvar)) 2212#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 2213#ifdef V_UI8REF 2214 obj = UI8_2_NUM(*V_UI8REF(pvar)); 2215#endif 2216#else 2217 obj = Qnil; 2218#endif 2219 else 2220 obj = UI8_2_NUM(V_UI8(pvar)); 2221 break; 2222#endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ 2223 2224 case VT_R4: 2225 if(V_ISBYREF(pvar)) 2226 obj = rb_float_new(*V_R4REF(pvar)); 2227 else 2228 obj = rb_float_new(V_R4(pvar)); 2229 break; 2230 2231 case VT_R8: 2232 if(V_ISBYREF(pvar)) 2233 obj = rb_float_new(*V_R8REF(pvar)); 2234 else 2235 obj = rb_float_new(V_R8(pvar)); 2236 break; 2237 2238 case VT_BSTR: 2239 { 2240 if(V_ISBYREF(pvar)) 2241 obj = ole_wc2vstr(*V_BSTRREF(pvar), FALSE); 2242 else 2243 obj = ole_wc2vstr(V_BSTR(pvar), FALSE); 2244 break; 2245 } 2246 2247 case VT_ERROR: 2248 if(V_ISBYREF(pvar)) 2249 obj = INT2NUM(*V_ERRORREF(pvar)); 2250 else 2251 obj = INT2NUM(V_ERROR(pvar)); 2252 break; 2253 2254 case VT_BOOL: 2255 if (V_ISBYREF(pvar)) 2256 obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse); 2257 else 2258 obj = (V_BOOL(pvar) ? Qtrue : Qfalse); 2259 break; 2260 2261 case VT_DISPATCH: 2262 { 2263 IDispatch *pDispatch; 2264 2265 if (V_ISBYREF(pvar)) 2266 pDispatch = *V_DISPATCHREF(pvar); 2267 else 2268 pDispatch = V_DISPATCH(pvar); 2269 2270 if (pDispatch != NULL ) { 2271 OLE_ADDREF(pDispatch); 2272 obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 2273 } 2274 break; 2275 } 2276 2277 case VT_UNKNOWN: 2278 { 2279 /* get IDispatch interface from IUnknown interface */ 2280 IUnknown *punk; 2281 IDispatch *pDispatch; 2282 void *p; 2283 HRESULT hr; 2284 2285 if (V_ISBYREF(pvar)) 2286 punk = *V_UNKNOWNREF(pvar); 2287 else 2288 punk = V_UNKNOWN(pvar); 2289 2290 if(punk != NULL) { 2291 hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p); 2292 if(SUCCEEDED(hr)) { 2293 pDispatch = p; 2294 obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 2295 } 2296 } 2297 break; 2298 } 2299 2300 case VT_DATE: 2301 { 2302 DATE date; 2303 if(V_ISBYREF(pvar)) 2304 date = *V_DATEREF(pvar); 2305 else 2306 date = V_DATE(pvar); 2307 2308 obj = vtdate2rbtime(date); 2309 break; 2310 } 2311 case VT_CY: 2312 default: 2313 { 2314 HRESULT hr; 2315 VARIANT variant; 2316 VariantInit(&variant); 2317 hr = VariantChangeTypeEx(&variant, pvar, 2318 cWIN32OLE_lcid, 0, VT_BSTR); 2319 if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) { 2320 obj = ole_wc2vstr(V_BSTR(&variant), FALSE); 2321 } 2322 VariantClear(&variant); 2323 break; 2324 } 2325 } 2326 return obj; 2327} 2328 2329static LONG 2330reg_open_key(HKEY hkey, const char *name, HKEY *phkey) 2331{ 2332 return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey); 2333} 2334 2335static LONG 2336reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey) 2337{ 2338 return reg_open_key(hkey, StringValuePtr(key), phkey); 2339} 2340 2341static VALUE 2342reg_enum_key(HKEY hkey, DWORD i) 2343{ 2344 char buf[BUFSIZ + 1]; 2345 DWORD size_buf = sizeof(buf); 2346 FILETIME ft; 2347 LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf, 2348 NULL, NULL, NULL, &ft); 2349 if(err == ERROR_SUCCESS) { 2350 buf[BUFSIZ] = '\0'; 2351 return rb_str_new2(buf); 2352 } 2353 return Qnil; 2354} 2355 2356static VALUE 2357reg_get_val(HKEY hkey, const char *subkey) 2358{ 2359 char *pbuf; 2360 DWORD dwtype = 0; 2361 DWORD size = 0; 2362 VALUE val = Qnil; 2363 LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size); 2364 2365 if (err == ERROR_SUCCESS) { 2366 pbuf = ALLOC_N(char, size + 1); 2367 err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, (BYTE *)pbuf, &size); 2368 if (err == ERROR_SUCCESS) { 2369 pbuf[size] = '\0'; 2370 if (dwtype == REG_EXPAND_SZ) { 2371 char* pbuf2 = (char *)pbuf; 2372 DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0); 2373 pbuf = ALLOC_N(char, len + 1); 2374 ExpandEnvironmentStrings(pbuf2, pbuf, len + 1); 2375 free(pbuf2); 2376 } 2377 val = rb_str_new2((char *)pbuf); 2378 } 2379 free(pbuf); 2380 } 2381 return val; 2382} 2383 2384static VALUE 2385reg_get_val2(HKEY hkey, const char *subkey) 2386{ 2387 HKEY hsubkey; 2388 LONG err; 2389 VALUE val = Qnil; 2390 err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey); 2391 if (err == ERROR_SUCCESS) { 2392 val = reg_get_val(hsubkey, NULL); 2393 RegCloseKey(hsubkey); 2394 } 2395 if (val == Qnil) { 2396 val = reg_get_val(hkey, subkey); 2397 } 2398 return val; 2399} 2400 2401static VALUE 2402reg_get_typelib_file_path(HKEY hkey) 2403{ 2404 VALUE path = Qnil; 2405 path = reg_get_val2(hkey, "win64"); 2406 if (path != Qnil) { 2407 return path; 2408 } 2409 path = reg_get_val2(hkey, "win32"); 2410 if (path != Qnil) { 2411 return path; 2412 } 2413 path = reg_get_val2(hkey, "win16"); 2414 return path; 2415} 2416 2417static VALUE 2418typelib_file_from_clsid(VALUE ole) 2419{ 2420 HKEY hroot, hclsid; 2421 LONG err; 2422 VALUE typelib; 2423 char path[MAX_PATH + 1]; 2424 2425 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot); 2426 if (err != ERROR_SUCCESS) { 2427 return Qnil; 2428 } 2429 err = reg_open_key(hroot, StringValuePtr(ole), &hclsid); 2430 if (err != ERROR_SUCCESS) { 2431 RegCloseKey(hroot); 2432 return Qnil; 2433 } 2434 typelib = reg_get_val2(hclsid, "InprocServer32"); 2435 RegCloseKey(hroot); 2436 RegCloseKey(hclsid); 2437 if (typelib != Qnil) { 2438 ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path)); 2439 path[MAX_PATH] = '\0'; 2440 typelib = rb_str_new2(path); 2441 } 2442 return typelib; 2443} 2444 2445static VALUE 2446typelib_file_from_typelib(VALUE ole) 2447{ 2448 HKEY htypelib, hclsid, hversion, hlang; 2449 double fver; 2450 DWORD i, j, k; 2451 LONG err; 2452 BOOL found = FALSE; 2453 VALUE typelib; 2454 VALUE file = Qnil; 2455 VALUE clsid; 2456 VALUE ver; 2457 VALUE lang; 2458 2459 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 2460 if(err != ERROR_SUCCESS) { 2461 return Qnil; 2462 } 2463 for(i = 0; !found; i++) { 2464 clsid = reg_enum_key(htypelib, i); 2465 if (clsid == Qnil) 2466 break; 2467 err = reg_open_vkey(htypelib, clsid, &hclsid); 2468 if (err != ERROR_SUCCESS) 2469 continue; 2470 fver = 0; 2471 for(j = 0; !found; j++) { 2472 ver = reg_enum_key(hclsid, j); 2473 if (ver == Qnil) 2474 break; 2475 err = reg_open_vkey(hclsid, ver, &hversion); 2476 if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver))) 2477 continue; 2478 fver = atof(StringValuePtr(ver)); 2479 typelib = reg_get_val(hversion, NULL); 2480 if (typelib == Qnil) 2481 continue; 2482 if (rb_str_cmp(typelib, ole) == 0) { 2483 for(k = 0; !found; k++) { 2484 lang = reg_enum_key(hversion, k); 2485 if (lang == Qnil) 2486 break; 2487 err = reg_open_vkey(hversion, lang, &hlang); 2488 if (err == ERROR_SUCCESS) { 2489 if ((file = reg_get_typelib_file_path(hlang)) != Qnil) 2490 found = TRUE; 2491 RegCloseKey(hlang); 2492 } 2493 } 2494 } 2495 RegCloseKey(hversion); 2496 } 2497 RegCloseKey(hclsid); 2498 } 2499 RegCloseKey(htypelib); 2500 return file; 2501} 2502 2503static VALUE 2504typelib_file(VALUE ole) 2505{ 2506 VALUE file = typelib_file_from_clsid(ole); 2507 if (file != Qnil) { 2508 return file; 2509 } 2510 return typelib_file_from_typelib(ole); 2511} 2512 2513static void 2514ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self) 2515{ 2516 unsigned int count; 2517 unsigned int index; 2518 int iVar; 2519 ITypeInfo *pTypeInfo; 2520 TYPEATTR *pTypeAttr; 2521 VARDESC *pVarDesc; 2522 HRESULT hr; 2523 unsigned int len; 2524 BSTR bstr; 2525 char *pName = NULL; 2526 VALUE val; 2527 VALUE constant; 2528 ID id; 2529 constant = rb_hash_new(); 2530 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 2531 for (index = 0; index < count; index++) { 2532 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo); 2533 if (FAILED(hr)) 2534 continue; 2535 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 2536 if(FAILED(hr)) { 2537 OLE_RELEASE(pTypeInfo); 2538 continue; 2539 } 2540 for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) { 2541 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc); 2542 if(FAILED(hr)) 2543 continue; 2544 if(pVarDesc->varkind == VAR_CONST && 2545 !(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | 2546 VARFLAG_FRESTRICTED | 2547 VARFLAG_FNONBROWSABLE))) { 2548 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 2549 1, &len); 2550 if(FAILED(hr) || len == 0 || !bstr) 2551 continue; 2552 pName = ole_wc2mb(bstr); 2553 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); 2554 *pName = toupper((int)*pName); 2555 id = rb_intern(pName); 2556 if (rb_is_const_id(id)) { 2557 rb_define_const(klass, pName, val); 2558 } 2559 else { 2560 rb_hash_aset(constant, rb_str_new2(pName), val); 2561 } 2562 SysFreeString(bstr); 2563 if(pName) { 2564 free(pName); 2565 pName = NULL; 2566 } 2567 } 2568 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 2569 } 2570 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); 2571 OLE_RELEASE(pTypeInfo); 2572 } 2573 rb_define_const(klass, "CONSTANTS", constant); 2574} 2575 2576static HRESULT 2577clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid) 2578{ 2579 HKEY hlm; 2580 HKEY hpid; 2581 VALUE subkey; 2582 LONG err; 2583 char clsid[100]; 2584 OLECHAR *pbuf; 2585 DWORD len; 2586 DWORD dwtype; 2587 HRESULT hr = S_OK; 2588 err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm); 2589 if (err != ERROR_SUCCESS) 2590 return HRESULT_FROM_WIN32(err); 2591 subkey = rb_str_new2("SOFTWARE\\Classes\\"); 2592 rb_str_concat(subkey, com); 2593 rb_str_cat2(subkey, "\\CLSID"); 2594 err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid); 2595 if (err != ERROR_SUCCESS) 2596 hr = HRESULT_FROM_WIN32(err); 2597 else { 2598 len = sizeof(clsid); 2599 err = RegQueryValueEx(hpid, "", NULL, &dwtype, (BYTE *)clsid, &len); 2600 if (err == ERROR_SUCCESS && dwtype == REG_SZ) { 2601 pbuf = ole_mb2wc(clsid, -1); 2602 hr = CLSIDFromString(pbuf, pclsid); 2603 SysFreeString(pbuf); 2604 } 2605 else { 2606 hr = HRESULT_FROM_WIN32(err); 2607 } 2608 RegCloseKey(hpid); 2609 } 2610 RegCloseKey(hlm); 2611 return hr; 2612} 2613 2614static VALUE 2615ole_create_dcom(int argc, VALUE *argv, VALUE self) 2616{ 2617 VALUE ole, host, others; 2618 HRESULT hr; 2619 CLSID clsid; 2620 OLECHAR *pbuf; 2621 2622 COSERVERINFO serverinfo; 2623 MULTI_QI multi_qi; 2624 DWORD clsctx = CLSCTX_REMOTE_SERVER; 2625 2626 if (!gole32) 2627 gole32 = LoadLibrary("OLE32"); 2628 if (!gole32) 2629 rb_raise(rb_eRuntimeError, "failed to load OLE32"); 2630 if (!gCoCreateInstanceEx) 2631 gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*) 2632 GetProcAddress(gole32, "CoCreateInstanceEx"); 2633 if (!gCoCreateInstanceEx) 2634 rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment"); 2635 rb_scan_args(argc, argv, "2*", &ole, &host, &others); 2636 2637 pbuf = ole_vstr2wc(ole); 2638 hr = CLSIDFromProgID(pbuf, &clsid); 2639 if (FAILED(hr)) 2640 hr = clsid_from_remote(host, ole, &clsid); 2641 if (FAILED(hr)) 2642 hr = CLSIDFromString(pbuf, &clsid); 2643 SysFreeString(pbuf); 2644 if (FAILED(hr)) 2645 ole_raise(hr, eWIN32OLERuntimeError, 2646 "unknown OLE server: `%s'", 2647 StringValuePtr(ole)); 2648 memset(&serverinfo, 0, sizeof(COSERVERINFO)); 2649 serverinfo.pwszName = ole_vstr2wc(host); 2650 memset(&multi_qi, 0, sizeof(MULTI_QI)); 2651 multi_qi.pIID = &IID_IDispatch; 2652 hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi); 2653 SysFreeString(serverinfo.pwszName); 2654 if (FAILED(hr)) 2655 ole_raise(hr, eWIN32OLERuntimeError, 2656 "failed to create DCOM server `%s' in `%s'", 2657 StringValuePtr(ole), 2658 StringValuePtr(host)); 2659 2660 ole_set_member(self, (IDispatch*)multi_qi.pItf); 2661 return self; 2662} 2663 2664static VALUE 2665ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self) 2666{ 2667 IBindCtx *pBindCtx; 2668 IMoniker *pMoniker; 2669 IDispatch *pDispatch; 2670 void *p; 2671 HRESULT hr; 2672 OLECHAR *pbuf; 2673 ULONG eaten = 0; 2674 2675 ole_initialize(); 2676 2677 hr = CreateBindCtx(0, &pBindCtx); 2678 if(FAILED(hr)) { 2679 ole_raise(hr, eWIN32OLERuntimeError, 2680 "failed to create bind context"); 2681 } 2682 2683 pbuf = ole_vstr2wc(moniker); 2684 hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker); 2685 SysFreeString(pbuf); 2686 if(FAILED(hr)) { 2687 OLE_RELEASE(pBindCtx); 2688 ole_raise(hr, eWIN32OLERuntimeError, 2689 "failed to parse display name of moniker `%s'", 2690 StringValuePtr(moniker)); 2691 } 2692 hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, 2693 &IID_IDispatch, &p); 2694 pDispatch = p; 2695 OLE_RELEASE(pMoniker); 2696 OLE_RELEASE(pBindCtx); 2697 2698 if(FAILED(hr)) { 2699 ole_raise(hr, eWIN32OLERuntimeError, 2700 "failed to bind moniker `%s'", 2701 StringValuePtr(moniker)); 2702 } 2703 return create_win32ole_object(self, pDispatch, argc, argv); 2704} 2705 2706/* 2707 * call-seq: 2708 * WIN32OLE.connect( ole ) --> aWIN32OLE 2709 * 2710 * Returns running OLE Automation object or WIN32OLE object from moniker. 2711 * 1st argument should be OLE program id or class id or moniker. 2712 * 2713 * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel. 2714 */ 2715static VALUE 2716fole_s_connect(int argc, VALUE *argv, VALUE self) 2717{ 2718 VALUE svr_name; 2719 VALUE others; 2720 HRESULT hr; 2721 CLSID clsid; 2722 OLECHAR *pBuf; 2723 IDispatch *pDispatch; 2724 void *p; 2725 IUnknown *pUnknown; 2726 2727 rb_secure(4); 2728 /* initialize to use OLE */ 2729 ole_initialize(); 2730 2731 rb_scan_args(argc, argv, "1*", &svr_name, &others); 2732 SafeStringValue(svr_name); 2733 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { 2734 rb_raise(rb_eSecurityError, "Insecure Object Connection - %s", 2735 StringValuePtr(svr_name)); 2736 } 2737 2738 /* get CLSID from OLE server name */ 2739 pBuf = ole_vstr2wc(svr_name); 2740 hr = CLSIDFromProgID(pBuf, &clsid); 2741 if(FAILED(hr)) { 2742 hr = CLSIDFromString(pBuf, &clsid); 2743 } 2744 SysFreeString(pBuf); 2745 if(FAILED(hr)) { 2746 return ole_bind_obj(svr_name, argc, argv, self); 2747 } 2748 2749 hr = GetActiveObject(&clsid, 0, &pUnknown); 2750 if (FAILED(hr)) { 2751 ole_raise(hr, eWIN32OLERuntimeError, 2752 "OLE server `%s' not running", StringValuePtr(svr_name)); 2753 } 2754 hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p); 2755 pDispatch = p; 2756 if(FAILED(hr)) { 2757 OLE_RELEASE(pUnknown); 2758 ole_raise(hr, eWIN32OLERuntimeError, 2759 "failed to create WIN32OLE server `%s'", 2760 StringValuePtr(svr_name)); 2761 } 2762 2763 OLE_RELEASE(pUnknown); 2764 2765 return create_win32ole_object(self, pDispatch, argc, argv); 2766} 2767 2768/* 2769 * call-seq: 2770 * WIN32OLE.const_load( ole, mod = WIN32OLE) 2771 * 2772 * Defines the constants of OLE Automation server as mod's constants. 2773 * The first argument is WIN32OLE object or type library name. 2774 * If 2nd argument is omitted, the default is WIN32OLE. 2775 * The first letter of Ruby's constant variable name is upper case, 2776 * so constant variable name of WIN32OLE object is capitalized. 2777 * For example, the 'xlTop' constant of Excel is changed to 'XlTop' 2778 * in WIN32OLE. 2779 * If the first letter of constant variabl is not [A-Z], then 2780 * the constant is defined as CONSTANTS hash element. 2781 * 2782 * module EXCEL_CONST 2783 * end 2784 * excel = WIN32OLE.new('Excel.Application') 2785 * WIN32OLE.const_load(excel, EXCEL_CONST) 2786 * puts EXCEL_CONST::XlTop # => -4160 2787 * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541 2788 * 2789 * WIN32OLE.const_load(excel) 2790 * puts WIN32OLE::XlTop # => -4160 2791 * 2792 * module MSO 2793 * end 2794 * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO) 2795 * puts MSO::MsoLineSingle # => 1 2796 */ 2797static VALUE 2798fole_s_const_load(int argc, VALUE *argv, VALUE self) 2799{ 2800 VALUE ole; 2801 VALUE klass; 2802 struct oledata *pole; 2803 ITypeInfo *pTypeInfo; 2804 ITypeLib *pTypeLib; 2805 unsigned int index; 2806 HRESULT hr; 2807 OLECHAR *pBuf; 2808 VALUE file; 2809 LCID lcid = cWIN32OLE_lcid; 2810 2811 rb_secure(4); 2812 rb_scan_args(argc, argv, "11", &ole, &klass); 2813 if (TYPE(klass) != T_CLASS && 2814 TYPE(klass) != T_MODULE && 2815 TYPE(klass) != T_NIL) { 2816 rb_raise(rb_eTypeError, "2nd parameter must be Class or Module"); 2817 } 2818 if (rb_obj_is_kind_of(ole, cWIN32OLE)) { 2819 OLEData_Get_Struct(ole, pole); 2820 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 2821 0, lcid, &pTypeInfo); 2822 if(FAILED(hr)) { 2823 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 2824 } 2825 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); 2826 if(FAILED(hr)) { 2827 OLE_RELEASE(pTypeInfo); 2828 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); 2829 } 2830 OLE_RELEASE(pTypeInfo); 2831 if(TYPE(klass) != T_NIL) { 2832 ole_const_load(pTypeLib, klass, self); 2833 } 2834 else { 2835 ole_const_load(pTypeLib, cWIN32OLE, self); 2836 } 2837 OLE_RELEASE(pTypeLib); 2838 } 2839 else if(TYPE(ole) == T_STRING) { 2840 file = typelib_file(ole); 2841 if (file == Qnil) { 2842 file = ole; 2843 } 2844 pBuf = ole_vstr2wc(file); 2845 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib); 2846 SysFreeString(pBuf); 2847 if (FAILED(hr)) 2848 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); 2849 if(TYPE(klass) != T_NIL) { 2850 ole_const_load(pTypeLib, klass, self); 2851 } 2852 else { 2853 ole_const_load(pTypeLib, cWIN32OLE, self); 2854 } 2855 OLE_RELEASE(pTypeLib); 2856 } 2857 else { 2858 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance"); 2859 } 2860 return Qnil; 2861} 2862 2863static VALUE 2864ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes) 2865{ 2866 2867 long count; 2868 int i; 2869 HRESULT hr; 2870 BSTR bstr; 2871 ITypeInfo *pTypeInfo; 2872 VALUE type; 2873 2874 rb_secure(4); 2875 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 2876 for (i = 0; i < count; i++) { 2877 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 2878 &bstr, NULL, NULL, NULL); 2879 if (FAILED(hr)) 2880 continue; 2881 2882 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 2883 if (FAILED(hr)) 2884 continue; 2885 2886 type = foletype_s_allocate(cWIN32OLE_TYPE); 2887 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr)); 2888 2889 rb_ary_push(classes, type); 2890 OLE_RELEASE(pTypeInfo); 2891 } 2892 return classes; 2893} 2894 2895static ULONG 2896reference_count(struct oledata * pole) 2897{ 2898 ULONG n = 0; 2899 if(pole->pDispatch) { 2900 OLE_ADDREF(pole->pDispatch); 2901 n = OLE_RELEASE(pole->pDispatch); 2902 } 2903 return n; 2904} 2905 2906/* 2907 * call-seq: 2908 * WIN32OLE.ole_reference_count(aWIN32OLE) --> number 2909 * 2910 * Returns reference counter of Dispatch interface of WIN32OLE object. 2911 * You should not use this method because this method 2912 * exists only for debugging WIN32OLE. 2913 */ 2914static VALUE 2915fole_s_reference_count(VALUE self, VALUE obj) 2916{ 2917 struct oledata * pole; 2918 OLEData_Get_Struct(obj, pole); 2919 return INT2NUM(reference_count(pole)); 2920} 2921 2922/* 2923 * call-seq: 2924 * WIN32OLE.ole_free(aWIN32OLE) --> number 2925 * 2926 * Invokes Release method of Dispatch interface of WIN32OLE object. 2927 * You should not use this method because this method 2928 * exists only for debugging WIN32OLE. 2929 * The return value is reference counter of OLE object. 2930 */ 2931static VALUE 2932fole_s_free(VALUE self, VALUE obj) 2933{ 2934 ULONG n = 0; 2935 struct oledata * pole; 2936 OLEData_Get_Struct(obj, pole); 2937 if(pole->pDispatch) { 2938 if (reference_count(pole) > 0) { 2939 n = OLE_RELEASE(pole->pDispatch); 2940 } 2941 } 2942 return INT2NUM(n); 2943} 2944 2945static HWND 2946ole_show_help(VALUE helpfile, VALUE helpcontext) 2947{ 2948 FNHTMLHELP *pfnHtmlHelp; 2949 HWND hwnd = 0; 2950 2951 if(!ghhctrl) 2952 ghhctrl = LoadLibrary("HHCTRL.OCX"); 2953 if (!ghhctrl) 2954 return hwnd; 2955 pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA"); 2956 if (!pfnHtmlHelp) 2957 return hwnd; 2958 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), 2959 0x0f, NUM2INT(helpcontext)); 2960 if (hwnd == 0) 2961 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), 2962 0, NUM2INT(helpcontext)); 2963 return hwnd; 2964} 2965 2966/* 2967 * call-seq: 2968 * WIN32OLE.ole_show_help(obj [,helpcontext]) 2969 * 2970 * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE 2971 * object or WIN32OLE_METHOD object or helpfile. 2972 * 2973 * excel = WIN32OLE.new('Excel.Application') 2974 * typeobj = excel.ole_type 2975 * WIN32OLE.ole_show_help(typeobj) 2976 */ 2977static VALUE 2978fole_s_show_help(int argc, VALUE *argv, VALUE self) 2979{ 2980 VALUE target; 2981 VALUE helpcontext; 2982 VALUE helpfile; 2983 VALUE name; 2984 HWND hwnd; 2985 rb_scan_args(argc, argv, "11", &target, &helpcontext); 2986 if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) || 2987 rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) { 2988 helpfile = rb_funcall(target, rb_intern("helpfile"), 0); 2989 if(strlen(StringValuePtr(helpfile)) == 0) { 2990 name = rb_ivar_get(target, rb_intern("name")); 2991 rb_raise(rb_eRuntimeError, "no helpfile of `%s'", 2992 StringValuePtr(name)); 2993 } 2994 helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0); 2995 } else { 2996 helpfile = target; 2997 } 2998 if (TYPE(helpfile) != T_STRING) { 2999 rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)"); 3000 } 3001 hwnd = ole_show_help(helpfile, helpcontext); 3002 if(hwnd == 0) { 3003 rb_raise(rb_eRuntimeError, "failed to open help file `%s'", 3004 StringValuePtr(helpfile)); 3005 } 3006 return Qnil; 3007} 3008 3009/* 3010 * call-seq: 3011 * WIN32OLE.codepage 3012 * 3013 * Returns current codepage. 3014 * WIN32OLE.codepage # => WIN32OLE::CP_ACP 3015 */ 3016static VALUE 3017fole_s_get_code_page(VALUE self) 3018{ 3019 return INT2FIX(cWIN32OLE_cp); 3020} 3021 3022static BOOL CALLBACK 3023installed_code_page_proc(LPTSTR str) { 3024 if (strtoul(str, NULL, 10) == g_cp_to_check) { 3025 g_cp_installed = TRUE; 3026 return FALSE; 3027 } 3028 return TRUE; 3029} 3030 3031static BOOL 3032code_page_installed(UINT cp) 3033{ 3034 g_cp_installed = FALSE; 3035 g_cp_to_check = cp; 3036 EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED); 3037 return g_cp_installed; 3038} 3039 3040/* 3041 * call-seq: 3042 * WIN32OLE.codepage = CP 3043 * 3044 * Sets current codepage. 3045 * The WIN32OLE.codepage is initialized according to 3046 * Encoding.default_internal. 3047 * If Encoding.default_internal is nil then WIN32OLE.codepage 3048 * is initialized according to Encoding.default_external. 3049 * 3050 * WIN32OLE.codepage = WIN32OLE::CP_UTF8 3051 * WIN32OLE.codepage = 65001 3052 */ 3053static VALUE 3054fole_s_set_code_page(VALUE self, VALUE vcp) 3055{ 3056 UINT cp = FIX2INT(vcp); 3057 set_ole_codepage(cp); 3058 /* 3059 * Should this method return old codepage? 3060 */ 3061 return Qnil; 3062} 3063 3064/* 3065 * call-seq: 3066 * WIN32OLE.locale -> locale id. 3067 * 3068 * Returns current locale id (lcid). The default locale is 3069 * LOCALE_SYSTEM_DEFAULT. 3070 * 3071 * lcid = WIN32OLE.locale 3072 */ 3073static VALUE 3074fole_s_get_locale(VALUE self) 3075{ 3076 return INT2FIX(cWIN32OLE_lcid); 3077} 3078 3079static BOOL 3080CALLBACK installed_lcid_proc(LPTSTR str) 3081{ 3082 if (strcmp(str, g_lcid_to_check) == 0) { 3083 g_lcid_installed = TRUE; 3084 return FALSE; 3085 } 3086 return TRUE; 3087} 3088 3089static BOOL 3090lcid_installed(LCID lcid) 3091{ 3092 g_lcid_installed = FALSE; 3093 snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", lcid); 3094 EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED); 3095 return g_lcid_installed; 3096} 3097 3098/* 3099 * call-seq: 3100 * WIN32OLE.locale = lcid 3101 * 3102 * Sets current locale id (lcid). 3103 * 3104 * WIN32OLE.locale = 1033 # set locale English(U.S) 3105 * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY) 3106 * 3107 */ 3108static VALUE 3109fole_s_set_locale(VALUE self, VALUE vlcid) 3110{ 3111 LCID lcid = FIX2INT(vlcid); 3112 if (lcid_installed(lcid)) { 3113 cWIN32OLE_lcid = lcid; 3114 } else { 3115 switch (lcid) { 3116 case LOCALE_SYSTEM_DEFAULT: 3117 case LOCALE_USER_DEFAULT: 3118 cWIN32OLE_lcid = lcid; 3119 break; 3120 default: 3121 rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid); 3122 } 3123 } 3124 return Qnil; 3125} 3126 3127/* 3128 * call-seq: 3129 * WIN32OLE.create_guid 3130 * 3131 * Creates GUID. 3132 * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8} 3133 */ 3134static VALUE 3135fole_s_create_guid(VALUE self) 3136{ 3137 GUID guid; 3138 HRESULT hr; 3139 OLECHAR bstr[80]; 3140 int len = 0; 3141 hr = CoCreateGuid(&guid); 3142 if (FAILED(hr)) { 3143 ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID"); 3144 } 3145 len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 3146 if (len == 0) { 3147 rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)"); 3148 } 3149 return ole_wc2vstr(bstr, FALSE); 3150} 3151 3152/* 3153 * WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize 3154 * are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634). 3155 * You must not use thease method. 3156 */ 3157 3158/* :nodoc */ 3159static VALUE 3160fole_s_ole_initialize(VALUE self) 3161{ 3162 ole_initialize(); 3163 return Qnil; 3164} 3165 3166/* :nodoc */ 3167static VALUE 3168fole_s_ole_uninitialize(VALUE self) 3169{ 3170 ole_uninitialize(); 3171 return Qnil; 3172} 3173 3174/* 3175 * Document-class: WIN32OLE 3176 * 3177 * <code>WIN32OLE</code> objects represent OLE Automation object in Ruby. 3178 * 3179 * By using WIN32OLE, you can access OLE server like VBScript. 3180 * 3181 * Here is sample script. 3182 * 3183 * require 'win32ole' 3184 * 3185 * excel = WIN32OLE.new('Excel.Application') 3186 * excel.visible = true 3187 * workbook = excel.Workbooks.Add(); 3188 * worksheet = workbook.Worksheets(1); 3189 * worksheet.Range("A1:D1").value = ["North","South","East","West"]; 3190 * worksheet.Range("A2:B2").value = [5.2, 10]; 3191 * worksheet.Range("C2").value = 8; 3192 * worksheet.Range("D2").value = 20; 3193 * 3194 * range = worksheet.Range("A1:D2"); 3195 * range.select 3196 * chart = workbook.Charts.Add; 3197 * 3198 * workbook.saved = true; 3199 * 3200 * excel.ActiveWorkbook.Close(0); 3201 * excel.Quit(); 3202 * 3203 * Unfortunately, Win32OLE doesn't support the argument passed by 3204 * reference directly. 3205 * Instead, Win32OLE provides WIN32OLE::ARGV. 3206 * If you want to get the result value of argument passed by reference, 3207 * you can use WIN32OLE::ARGV. 3208 * 3209 * oleobj.method(arg1, arg2, refargv3) 3210 * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method 3211 * 3212 */ 3213 3214/* 3215 * call-seq: 3216 * WIN32OLE.new(server, [host]) -> WIN32OLE object 3217 * 3218 * Returns a new WIN32OLE object(OLE Automation object). 3219 * The first argument server specifies OLE Automation server. 3220 * The first argument should be CLSID or PROGID. 3221 * If second argument host specified, then returns OLE Automation 3222 * object on host. 3223 * 3224 * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object. 3225 * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object. 3226 */ 3227static VALUE 3228fole_initialize(int argc, VALUE *argv, VALUE self) 3229{ 3230 VALUE svr_name; 3231 VALUE host; 3232 VALUE others; 3233 HRESULT hr; 3234 CLSID clsid; 3235 OLECHAR *pBuf; 3236 IDispatch *pDispatch; 3237 void *p; 3238 rb_secure(4); 3239 rb_call_super(0, 0); 3240 rb_scan_args(argc, argv, "11*", &svr_name, &host, &others); 3241 3242 SafeStringValue(svr_name); 3243 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { 3244 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s", 3245 StringValuePtr(svr_name)); 3246 } 3247 if (!NIL_P(host)) { 3248 SafeStringValue(host); 3249 if (rb_safe_level() > 0 && OBJ_TAINTED(host)) { 3250 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s", 3251 StringValuePtr(svr_name)); 3252 } 3253 return ole_create_dcom(argc, argv, self); 3254 } 3255 3256 /* get CLSID from OLE server name */ 3257 pBuf = ole_vstr2wc(svr_name); 3258 hr = CLSIDFromProgID(pBuf, &clsid); 3259 if(FAILED(hr)) { 3260 hr = CLSIDFromString(pBuf, &clsid); 3261 } 3262 SysFreeString(pBuf); 3263 if(FAILED(hr)) { 3264 ole_raise(hr, eWIN32OLERuntimeError, 3265 "unknown OLE server: `%s'", 3266 StringValuePtr(svr_name)); 3267 } 3268 3269 /* get IDispatch interface */ 3270 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 3271 &IID_IDispatch, &p); 3272 pDispatch = p; 3273 if(FAILED(hr)) { 3274 ole_raise(hr, eWIN32OLERuntimeError, 3275 "failed to create WIN32OLE object from `%s'", 3276 StringValuePtr(svr_name)); 3277 } 3278 3279 ole_set_member(self, pDispatch); 3280 return self; 3281} 3282 3283static VALUE 3284hash2named_arg(VALUE pair, struct oleparam* pOp) 3285{ 3286 unsigned int index, i; 3287 VALUE key, value; 3288 index = pOp->dp.cNamedArgs; 3289 3290 /*--------------------------------------------- 3291 the data-type of key must be String or Symbol 3292 -----------------------------------------------*/ 3293 key = rb_ary_entry(pair, 0); 3294 if(TYPE(key) != T_STRING && TYPE(key) != T_SYMBOL) { 3295 /* clear name of dispatch parameters */ 3296 for(i = 1; i < index + 1; i++) { 3297 SysFreeString(pOp->pNamedArgs[i]); 3298 } 3299 /* clear dispatch parameters */ 3300 for(i = 0; i < index; i++ ) { 3301 VariantClear(&(pOp->dp.rgvarg[i])); 3302 } 3303 /* raise an exception */ 3304 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 3305 } 3306 if (TYPE(key) == T_SYMBOL) { 3307 key = rb_sym_to_s(key); 3308 } 3309 3310 /* pNamedArgs[0] is <method name>, so "index + 1" */ 3311 pOp->pNamedArgs[index + 1] = ole_vstr2wc(key); 3312 3313 value = rb_ary_entry(pair, 1); 3314 VariantInit(&(pOp->dp.rgvarg[index])); 3315 ole_val2variant(value, &(pOp->dp.rgvarg[index])); 3316 3317 pOp->dp.cNamedArgs += 1; 3318 return Qnil; 3319} 3320 3321static VALUE 3322set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end) 3323{ 3324 VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV")); 3325 3326 Check_Type(argv, T_ARRAY); 3327 rb_ary_clear(argv); 3328 while (end-- > beg) { 3329 rb_ary_push(argv, ole_variant2val(&realargs[end])); 3330 VariantClear(&realargs[end]); 3331 } 3332 return argv; 3333} 3334 3335static VALUE 3336ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket) 3337{ 3338 LCID lcid = cWIN32OLE_lcid; 3339 struct oledata *pole; 3340 HRESULT hr; 3341 VALUE cmd; 3342 VALUE paramS; 3343 VALUE param; 3344 VALUE obj; 3345 VALUE v; 3346 3347 BSTR wcmdname; 3348 3349 DISPID DispID; 3350 DISPID* pDispID; 3351 EXCEPINFO excepinfo; 3352 VARIANT result; 3353 VARIANTARG* realargs = NULL; 3354 unsigned int argErr = 0; 3355 unsigned int i; 3356 unsigned int cNamedArgs; 3357 int n; 3358 struct oleparam op; 3359 struct olevariantdata *pvar; 3360 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 3361 3362 VariantInit(&result); 3363 3364 op.dp.rgvarg = NULL; 3365 op.dp.rgdispidNamedArgs = NULL; 3366 op.dp.cNamedArgs = 0; 3367 op.dp.cArgs = 0; 3368 3369 rb_scan_args(argc, argv, "1*", &cmd, ¶mS); 3370 if(TYPE(cmd) != T_STRING && TYPE(cmd) != T_SYMBOL && !is_bracket) { 3371 rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)"); 3372 } 3373 if (TYPE(cmd) == T_SYMBOL) { 3374 cmd = rb_sym_to_s(cmd); 3375 } 3376 OLEData_Get_Struct(self, pole); 3377 if(!pole->pDispatch) { 3378 rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); 3379 } 3380 if (is_bracket) { 3381 DispID = DISPID_VALUE; 3382 argc += 1; 3383 rb_ary_unshift(paramS, cmd); 3384 } else { 3385 wcmdname = ole_vstr2wc(cmd); 3386 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, 3387 &wcmdname, 1, lcid, &DispID); 3388 SysFreeString(wcmdname); 3389 if(FAILED(hr)) { 3390 ole_raise(hr, rb_eNoMethodError, 3391 "unknown property or method: `%s'", 3392 StringValuePtr(cmd)); 3393 } 3394 } 3395 3396 /* pick up last argument of method */ 3397 param = rb_ary_entry(paramS, argc-2); 3398 3399 op.dp.cNamedArgs = 0; 3400 3401 /* if last arg is hash object */ 3402 if(TYPE(param) == T_HASH) { 3403 /*------------------------------------------ 3404 hash object ==> named dispatch parameters 3405 --------------------------------------------*/ 3406 cNamedArgs = NUM2INT(rb_funcall(param, rb_intern("length"), 0)); 3407 op.dp.cArgs = cNamedArgs + argc - 2; 3408 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); 3409 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); 3410 rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op); 3411 3412 pDispID = ALLOCA_N(DISPID, cNamedArgs + 1); 3413 op.pNamedArgs[0] = ole_vstr2wc(cmd); 3414 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, 3415 &IID_NULL, 3416 op.pNamedArgs, 3417 op.dp.cNamedArgs + 1, 3418 lcid, pDispID); 3419 for(i = 0; i < op.dp.cNamedArgs + 1; i++) { 3420 SysFreeString(op.pNamedArgs[i]); 3421 op.pNamedArgs[i] = NULL; 3422 } 3423 if(FAILED(hr)) { 3424 /* clear dispatch parameters */ 3425 for(i = 0; i < op.dp.cArgs; i++ ) { 3426 VariantClear(&op.dp.rgvarg[i]); 3427 } 3428 ole_raise(hr, eWIN32OLERuntimeError, 3429 "failed to get named argument info: `%s'", 3430 StringValuePtr(cmd)); 3431 } 3432 op.dp.rgdispidNamedArgs = &(pDispID[1]); 3433 } 3434 else { 3435 cNamedArgs = 0; 3436 op.dp.cArgs = argc - 1; 3437 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); 3438 if (op.dp.cArgs > 0) { 3439 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); 3440 } 3441 } 3442 /*-------------------------------------- 3443 non hash args ==> dispatch parameters 3444 ----------------------------------------*/ 3445 if(op.dp.cArgs > cNamedArgs) { 3446 realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1); 3447 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 3448 n = op.dp.cArgs - i + cNamedArgs - 1; 3449 VariantInit(&realargs[n]); 3450 VariantInit(&op.dp.rgvarg[n]); 3451 param = rb_ary_entry(paramS, i-cNamedArgs); 3452 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { 3453 Data_Get_Struct(param, struct olevariantdata, pvar); 3454 VariantCopy(&op.dp.rgvarg[n], &(pvar->var)); 3455 } else { 3456 ole_val2variant(param, &realargs[n]); 3457 V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF; 3458 V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n]; 3459 } 3460 } 3461 } 3462 /* apparent you need to call propput, you need this */ 3463 if (wFlags & DISPATCH_PROPERTYPUT) { 3464 if (op.dp.cArgs == 0) 3465 ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error"); 3466 3467 op.dp.cNamedArgs = 1; 3468 op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); 3469 op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; 3470 } 3471 3472 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 3473 &IID_NULL, lcid, wFlags, &op.dp, 3474 &result, &excepinfo, &argErr); 3475 3476 if (FAILED(hr)) { 3477 /* retry to call args by value */ 3478 if(op.dp.cArgs >= cNamedArgs) { 3479 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 3480 n = op.dp.cArgs - i + cNamedArgs - 1; 3481 param = rb_ary_entry(paramS, i-cNamedArgs); 3482 ole_val2variant(param, &op.dp.rgvarg[n]); 3483 } 3484 if (hr == DISP_E_EXCEPTION) { 3485 ole_freeexceptinfo(&excepinfo); 3486 } 3487 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 3488 VariantInit(&result); 3489 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 3490 &IID_NULL, lcid, wFlags, 3491 &op.dp, &result, 3492 &excepinfo, &argErr); 3493 3494 /* mega kludge. if a method in WORD is called and we ask 3495 * for a result when one is not returned then 3496 * hResult == DISP_E_EXCEPTION. this only happens on 3497 * functions whose DISPID > 0x8000 */ 3498 if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) { 3499 if (hr == DISP_E_EXCEPTION) { 3500 ole_freeexceptinfo(&excepinfo); 3501 } 3502 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 3503 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 3504 &IID_NULL, lcid, wFlags, 3505 &op.dp, NULL, 3506 &excepinfo, &argErr); 3507 3508 } 3509 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 3510 n = op.dp.cArgs - i + cNamedArgs - 1; 3511 VariantClear(&op.dp.rgvarg[n]); 3512 } 3513 } 3514 3515 if (FAILED(hr)) { 3516 /* retry after converting nil to VT_EMPTY */ 3517 if (op.dp.cArgs > cNamedArgs) { 3518 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 3519 n = op.dp.cArgs - i + cNamedArgs - 1; 3520 param = rb_ary_entry(paramS, i-cNamedArgs); 3521 ole_val2variant2(param, &op.dp.rgvarg[n]); 3522 } 3523 if (hr == DISP_E_EXCEPTION) { 3524 ole_freeexceptinfo(&excepinfo); 3525 } 3526 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 3527 VariantInit(&result); 3528 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 3529 &IID_NULL, lcid, wFlags, 3530 &op.dp, &result, 3531 &excepinfo, &argErr); 3532 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 3533 n = op.dp.cArgs - i + cNamedArgs - 1; 3534 VariantClear(&op.dp.rgvarg[n]); 3535 } 3536 } 3537 } 3538 3539 } 3540 /* clear dispatch parameter */ 3541 if(op.dp.cArgs > cNamedArgs) { 3542 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 3543 n = op.dp.cArgs - i + cNamedArgs - 1; 3544 param = rb_ary_entry(paramS, i-cNamedArgs); 3545 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { 3546 ole_val2variant(param, &realargs[n]); 3547 } 3548 } 3549 set_argv(realargs, cNamedArgs, op.dp.cArgs); 3550 } 3551 else { 3552 for(i = 0; i < op.dp.cArgs; i++) { 3553 VariantClear(&op.dp.rgvarg[i]); 3554 } 3555 } 3556 3557 if (FAILED(hr)) { 3558 v = ole_excepinfo2msg(&excepinfo); 3559 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s", 3560 StringValuePtr(cmd), 3561 StringValuePtr(v)); 3562 } 3563 obj = ole_variant2val(&result); 3564 VariantClear(&result); 3565 return obj; 3566} 3567 3568/* 3569 * call-seq: 3570 * WIN32OLE#invoke(method, [arg1,...]) => return value of method. 3571 * 3572 * Runs OLE method. 3573 * The first argument specifies the method name of OLE Automation object. 3574 * The others specify argument of the <i>method</i>. 3575 * If you can not execute <i>method</i> directly, then use this method instead. 3576 * 3577 * excel = WIN32OLE.new('Excel.Application') 3578 * excel.invoke('Quit') # => same as excel.Quit 3579 * 3580 */ 3581static VALUE 3582fole_invoke(int argc, VALUE *argv, VALUE self) 3583{ 3584 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); 3585} 3586 3587static VALUE 3588ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind) 3589{ 3590 HRESULT hr; 3591 struct oledata *pole; 3592 unsigned int argErr = 0; 3593 EXCEPINFO excepinfo; 3594 VARIANT result; 3595 DISPPARAMS dispParams; 3596 VARIANTARG* realargs = NULL; 3597 int i, j; 3598 VALUE obj = Qnil; 3599 VALUE tp, param; 3600 VALUE v; 3601 VARTYPE vt; 3602 3603 Check_Type(args, T_ARRAY); 3604 Check_Type(types, T_ARRAY); 3605 3606 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 3607 memset(&dispParams, 0, sizeof(DISPPARAMS)); 3608 VariantInit(&result); 3609 OLEData_Get_Struct(self, pole); 3610 3611 dispParams.cArgs = RARRAY_LEN(args); 3612 dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs); 3613 realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs); 3614 for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--) 3615 { 3616 VariantInit(&realargs[i]); 3617 VariantInit(&dispParams.rgvarg[i]); 3618 tp = rb_ary_entry(types, j); 3619 vt = (VARTYPE)FIX2INT(tp); 3620 V_VT(&dispParams.rgvarg[i]) = vt; 3621 param = rb_ary_entry(args, j); 3622 if (param == Qnil) 3623 { 3624 3625 V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR; 3626 V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND; 3627 } 3628 else 3629 { 3630 if (vt & VT_ARRAY) 3631 { 3632 int ent; 3633 LPBYTE pb; 3634 short* ps; 3635 LPLONG pl; 3636 VARIANT* pv; 3637 CY *py; 3638 VARTYPE v; 3639 SAFEARRAYBOUND rgsabound[1]; 3640 Check_Type(param, T_ARRAY); 3641 rgsabound[0].lLbound = 0; 3642 rgsabound[0].cElements = RARRAY_LEN(param); 3643 v = vt & ~(VT_ARRAY | VT_BYREF); 3644 V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound); 3645 V_VT(&realargs[i]) = VT_ARRAY | v; 3646 SafeArrayLock(V_ARRAY(&realargs[i])); 3647 pb = V_ARRAY(&realargs[i])->pvData; 3648 ps = V_ARRAY(&realargs[i])->pvData; 3649 pl = V_ARRAY(&realargs[i])->pvData; 3650 py = V_ARRAY(&realargs[i])->pvData; 3651 pv = V_ARRAY(&realargs[i])->pvData; 3652 for (ent = 0; ent < (int)rgsabound[0].cElements; ent++) 3653 { 3654 VARIANT velem; 3655 VALUE elem = rb_ary_entry(param, ent); 3656 ole_val2variant(elem, &velem); 3657 if (v != VT_VARIANT) 3658 { 3659 VariantChangeTypeEx(&velem, &velem, 3660 cWIN32OLE_lcid, 0, v); 3661 } 3662 switch (v) 3663 { 3664 /* 128 bits */ 3665 case VT_VARIANT: 3666 *pv++ = velem; 3667 break; 3668 /* 64 bits */ 3669 case VT_R8: 3670 case VT_CY: 3671 case VT_DATE: 3672 *py++ = V_CY(&velem); 3673 break; 3674 /* 16 bits */ 3675 case VT_BOOL: 3676 case VT_I2: 3677 case VT_UI2: 3678 *ps++ = V_I2(&velem); 3679 break; 3680 /* 8 bites */ 3681 case VT_UI1: 3682 case VT_I1: 3683 *pb++ = V_UI1(&velem); 3684 break; 3685 /* 32 bits */ 3686 default: 3687 *pl++ = V_I4(&velem); 3688 break; 3689 } 3690 } 3691 SafeArrayUnlock(V_ARRAY(&realargs[i])); 3692 } 3693 else 3694 { 3695 ole_val2variant(param, &realargs[i]); 3696 if ((vt & (~VT_BYREF)) != VT_VARIANT) 3697 { 3698 hr = VariantChangeTypeEx(&realargs[i], &realargs[i], 3699 cWIN32OLE_lcid, 0, 3700 (VARTYPE)(vt & (~VT_BYREF))); 3701 if (hr != S_OK) 3702 { 3703 rb_raise(rb_eTypeError, "not valid value"); 3704 } 3705 } 3706 } 3707 if ((vt & VT_BYREF) || vt == VT_VARIANT) 3708 { 3709 if (vt == VT_VARIANT) 3710 V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF; 3711 switch (vt & (~VT_BYREF)) 3712 { 3713 /* 128 bits */ 3714 case VT_VARIANT: 3715 V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i]; 3716 break; 3717 /* 64 bits */ 3718 case VT_R8: 3719 case VT_CY: 3720 case VT_DATE: 3721 V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]); 3722 break; 3723 /* 16 bits */ 3724 case VT_BOOL: 3725 case VT_I2: 3726 case VT_UI2: 3727 V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]); 3728 break; 3729 /* 8 bites */ 3730 case VT_UI1: 3731 case VT_I1: 3732 V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]); 3733 break; 3734 /* 32 bits */ 3735 default: 3736 V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]); 3737 break; 3738 } 3739 } 3740 else 3741 { 3742 /* copy 64 bits of data */ 3743 V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]); 3744 } 3745 } 3746 } 3747 3748 if (dispkind & DISPATCH_PROPERTYPUT) { 3749 dispParams.cNamedArgs = 1; 3750 dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); 3751 dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; 3752 } 3753 3754 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid), 3755 &IID_NULL, cWIN32OLE_lcid, 3756 dispkind, 3757 &dispParams, &result, 3758 &excepinfo, &argErr); 3759 3760 if (FAILED(hr)) { 3761 v = ole_excepinfo2msg(&excepinfo); 3762 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s", 3763 NUM2INT(dispid), 3764 StringValuePtr(v)); 3765 } 3766 3767 /* clear dispatch parameter */ 3768 if(dispParams.cArgs > 0) { 3769 set_argv(realargs, 0, dispParams.cArgs); 3770 } 3771 3772 obj = ole_variant2val(&result); 3773 VariantClear(&result); 3774 return obj; 3775} 3776 3777/* 3778 * call-seq: 3779 * WIN32OLE#_invoke(dispid, args, types) 3780 * 3781 * Runs the early binding method. 3782 * The 1st argument specifies dispatch ID, 3783 * the 2nd argument specifies the array of arguments, 3784 * the 3rd argument specifies the array of the type of arguments. 3785 * 3786 * excel = WIN32OLE.new('Excel.Application') 3787 * excel._invoke(302, [], []) # same effect as excel.Quit 3788 */ 3789static VALUE 3790fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types) 3791{ 3792 return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD); 3793} 3794 3795/* 3796 * call-seq: 3797 * WIN32OLE#_getproperty(dispid, args, types) 3798 * 3799 * Runs the early binding method to get property. 3800 * The 1st argument specifies dispatch ID, 3801 * the 2nd argument specifies the array of arguments, 3802 * the 3rd argument specifies the array of the type of arguments. 3803 * 3804 * excel = WIN32OLE.new('Excel.Application') 3805 * puts excel._getproperty(558, [], []) # same effect as puts excel.visible 3806 */ 3807static VALUE 3808fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) 3809{ 3810 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET); 3811} 3812 3813/* 3814 * call-seq: 3815 * WIN32OLE#_setproperty(dispid, args, types) 3816 * 3817 * Runs the early binding method to set property. 3818 * The 1st argument specifies dispatch ID, 3819 * the 2nd argument specifies the array of arguments, 3820 * the 3rd argument specifies the array of the type of arguments. 3821 * 3822 * excel = WIN32OLE.new('Excel.Application') 3823 * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true 3824 */ 3825static VALUE 3826fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) 3827{ 3828 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT); 3829} 3830 3831/* 3832 * call-seq: 3833 * WIN32OLE[a1, a2, ...]=val 3834 * 3835 * Sets the value to WIN32OLE object specified by a1, a2, ... 3836 * 3837 * dict = WIN32OLE.new('Scripting.Dictionary') 3838 * dict.add('ruby', 'RUBY') 3839 * dict['ruby'] = 'Ruby' 3840 * puts dict['ruby'] # => 'Ruby' 3841 * 3842 * Remark: You can not use this method to set the property value. 3843 * 3844 * excel = WIN32OLE.new('Excel.Application') 3845 * # excel['Visible'] = true # This is error !!! 3846 * excel.Visible = true # You should to use this style to set the property. 3847 * 3848 */ 3849static VALUE 3850fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self) 3851{ 3852 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE); 3853} 3854 3855/* 3856 * call-seq: 3857 * WIN32OLE.setproperty('property', [arg1, arg2,...] val) 3858 * 3859 * Sets property of OLE object. 3860 * When you want to set property with argument, you can use this method. 3861 * 3862 * excel = WIN32OLE.new('Excel.Application') 3863 * excel.Visible = true 3864 * book = excel.workbooks.add 3865 * sheet = book.worksheets(1) 3866 * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10. 3867 */ 3868static VALUE 3869fole_setproperty(int argc, VALUE *argv, VALUE self) 3870{ 3871 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE); 3872} 3873 3874/* 3875 * call-seq: 3876 * WIN32OLE[a1,a2,...] 3877 * 3878 * Returns the value of Collection specified by a1, a2,.... 3879 * 3880 * dict = WIN32OLE.new('Scripting.Dictionary') 3881 * dict.add('ruby', 'Ruby') 3882 * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')') 3883 * 3884 * Remark: You can not use this method to get the property. 3885 * excel = WIN32OLE.new('Excel.Application') 3886 * # puts excel['Visible'] This is error !!! 3887 * puts excel.Visible # You should to use this style to get the property. 3888 * 3889 */ 3890static VALUE 3891fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self) 3892{ 3893 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE); 3894} 3895 3896static VALUE 3897ole_propertyput(VALUE self, VALUE property, VALUE value) 3898{ 3899 struct oledata *pole; 3900 unsigned argErr; 3901 unsigned int index; 3902 HRESULT hr; 3903 EXCEPINFO excepinfo; 3904 DISPID dispID = DISPID_VALUE; 3905 DISPID dispIDParam = DISPID_PROPERTYPUT; 3906 USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF; 3907 DISPPARAMS dispParams; 3908 VARIANTARG propertyValue[2]; 3909 OLECHAR* pBuf[1]; 3910 VALUE v; 3911 LCID lcid = cWIN32OLE_lcid; 3912 dispParams.rgdispidNamedArgs = &dispIDParam; 3913 dispParams.rgvarg = propertyValue; 3914 dispParams.cNamedArgs = 1; 3915 dispParams.cArgs = 1; 3916 3917 VariantInit(&propertyValue[0]); 3918 VariantInit(&propertyValue[1]); 3919 memset(&excepinfo, 0, sizeof(excepinfo)); 3920 3921 OLEData_Get_Struct(self, pole); 3922 3923 /* get ID from property name */ 3924 pBuf[0] = ole_vstr2wc(property); 3925 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL, 3926 pBuf, 1, lcid, &dispID); 3927 SysFreeString(pBuf[0]); 3928 pBuf[0] = NULL; 3929 3930 if(FAILED(hr)) { 3931 ole_raise(hr, eWIN32OLERuntimeError, 3932 "unknown property or method: `%s'", 3933 StringValuePtr(property)); 3934 } 3935 /* set property value */ 3936 ole_val2variant(value, &propertyValue[0]); 3937 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL, 3938 lcid, wFlags, &dispParams, 3939 NULL, &excepinfo, &argErr); 3940 3941 for(index = 0; index < dispParams.cArgs; ++index) { 3942 VariantClear(&propertyValue[index]); 3943 } 3944 if (FAILED(hr)) { 3945 v = ole_excepinfo2msg(&excepinfo); 3946 ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s", 3947 StringValuePtr(property), 3948 StringValuePtr(v)); 3949 } 3950 return Qnil; 3951} 3952 3953/* 3954 * call-seq: 3955 * WIN32OLE#ole_free 3956 * 3957 * invokes Release method of Dispatch interface of WIN32OLE object. 3958 * Usually, you do not need to call this method because Release method 3959 * called automatically when WIN32OLE object garbaged. 3960 * 3961 */ 3962static VALUE 3963fole_free(VALUE self) 3964{ 3965 struct oledata *pole; 3966 rb_secure(4); 3967 OLEData_Get_Struct(self, pole); 3968 OLE_FREE(pole->pDispatch); 3969 pole->pDispatch = NULL; 3970 return Qnil; 3971} 3972 3973static VALUE 3974ole_each_sub(VALUE pEnumV) 3975{ 3976 VARIANT variant; 3977 VALUE obj = Qnil; 3978 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; 3979 VariantInit(&variant); 3980 while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) { 3981 obj = ole_variant2val(&variant); 3982 VariantClear(&variant); 3983 VariantInit(&variant); 3984 rb_yield(obj); 3985 } 3986 return Qnil; 3987} 3988 3989static VALUE 3990ole_ienum_free(VALUE pEnumV) 3991{ 3992 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; 3993 OLE_RELEASE(pEnum); 3994 return Qnil; 3995} 3996 3997/* 3998 * call-seq: 3999 * WIN32OLE#each {|i|...} 4000 * 4001 * Iterates over each item of OLE collection which has IEnumVARIANT interface. 4002 * 4003 * excel = WIN32OLE.new('Excel.Application') 4004 * book = excel.workbooks.add 4005 * sheets = book.worksheets(1) 4006 * cells = sheets.cells("A1:A5") 4007 * cells.each do |cell| 4008 * cell.value = 10 4009 * end 4010 */ 4011static VALUE 4012fole_each(VALUE self) 4013{ 4014 LCID lcid = cWIN32OLE_lcid; 4015 4016 struct oledata *pole; 4017 4018 unsigned int argErr; 4019 EXCEPINFO excepinfo; 4020 DISPPARAMS dispParams; 4021 VARIANT result; 4022 HRESULT hr; 4023 IEnumVARIANT *pEnum = NULL; 4024 void *p; 4025 4026 RETURN_ENUMERATOR(self, 0, 0); 4027 4028 VariantInit(&result); 4029 dispParams.rgvarg = NULL; 4030 dispParams.rgdispidNamedArgs = NULL; 4031 dispParams.cNamedArgs = 0; 4032 dispParams.cArgs = 0; 4033 memset(&excepinfo, 0, sizeof(excepinfo)); 4034 4035 OLEData_Get_Struct(self, pole); 4036 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM, 4037 &IID_NULL, lcid, 4038 DISPATCH_METHOD | DISPATCH_PROPERTYGET, 4039 &dispParams, &result, 4040 &excepinfo, &argErr); 4041 4042 if (FAILED(hr)) { 4043 VariantClear(&result); 4044 ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface"); 4045 } 4046 4047 if (V_VT(&result) == VT_UNKNOWN) { 4048 hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result), 4049 &IID_IEnumVARIANT, 4050 &p); 4051 pEnum = p; 4052 } else if (V_VT(&result) == VT_DISPATCH) { 4053 hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result), 4054 &IID_IEnumVARIANT, 4055 &p); 4056 pEnum = p; 4057 } 4058 if (FAILED(hr) || !pEnum) { 4059 VariantClear(&result); 4060 ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface"); 4061 } 4062 4063 VariantClear(&result); 4064 rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum); 4065 return Qnil; 4066} 4067 4068/* 4069 * call-seq: 4070 * WIN32OLE#method_missing(id [,arg1, arg2, ...]) 4071 * 4072 * Calls WIN32OLE#invoke method. 4073 */ 4074static VALUE 4075fole_missing(int argc, VALUE *argv, VALUE self) 4076{ 4077 ID id; 4078 const char* mname; 4079 int n; 4080 id = rb_to_id(argv[0]); 4081 mname = rb_id2name(id); 4082 if(!mname) { 4083 rb_raise(rb_eRuntimeError, "fail: unknown method or property"); 4084 } 4085 n = strlen(mname); 4086 if(mname[n-1] == '=') { 4087 argv[0] = rb_enc_str_new(mname, n-1, cWIN32OLE_enc); 4088 4089 return ole_propertyput(self, argv[0], argv[1]); 4090 } 4091 else { 4092 argv[0] = rb_enc_str_new(mname, n, cWIN32OLE_enc); 4093 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); 4094 } 4095} 4096 4097static VALUE 4098ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name) 4099{ 4100 HRESULT hr; 4101 TYPEATTR *pTypeAttr; 4102 BSTR bstr; 4103 FUNCDESC *pFuncDesc; 4104 WORD i; 4105 VALUE fname; 4106 VALUE method = Qnil; 4107 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 4108 if (FAILED(hr)) { 4109 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 4110 } 4111 for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) { 4112 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); 4113 if (FAILED(hr)) 4114 continue; 4115 4116 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 4117 &bstr, NULL, NULL, NULL); 4118 if (FAILED(hr)) { 4119 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 4120 continue; 4121 } 4122 fname = WC2VSTR(bstr); 4123 if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) { 4124 olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname); 4125 method = self; 4126 } 4127 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 4128 pFuncDesc=NULL; 4129 } 4130 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 4131 return method; 4132} 4133 4134static VALUE 4135olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name) 4136{ 4137 HRESULT hr; 4138 TYPEATTR *pTypeAttr; 4139 WORD i; 4140 HREFTYPE href; 4141 ITypeInfo *pRefTypeInfo; 4142 VALUE method = Qnil; 4143 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 4144 if (FAILED(hr)) { 4145 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 4146 } 4147 method = ole_method_sub(self, 0, pTypeInfo, name); 4148 if (method != Qnil) { 4149 return method; 4150 } 4151 for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){ 4152 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 4153 if(FAILED(hr)) 4154 continue; 4155 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 4156 if (FAILED(hr)) 4157 continue; 4158 method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name); 4159 OLE_RELEASE(pRefTypeInfo); 4160 } 4161 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 4162 return method; 4163} 4164 4165static VALUE 4166ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask) 4167{ 4168 HRESULT hr; 4169 TYPEATTR *pTypeAttr; 4170 BSTR bstr; 4171 FUNCDESC *pFuncDesc; 4172 VALUE method; 4173 WORD i; 4174 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 4175 if (FAILED(hr)) { 4176 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 4177 } 4178 for(i = 0; i < pTypeAttr->cFuncs; i++) { 4179 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); 4180 if (FAILED(hr)) 4181 continue; 4182 4183 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 4184 &bstr, NULL, NULL, NULL); 4185 if (FAILED(hr)) { 4186 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 4187 continue; 4188 } 4189 if(pFuncDesc->invkind & mask) { 4190 method = folemethod_s_allocate(cWIN32OLE_METHOD); 4191 olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo, 4192 i, WC2VSTR(bstr)); 4193 rb_ary_push(methods, method); 4194 } 4195 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 4196 pFuncDesc=NULL; 4197 } 4198 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 4199 4200 return methods; 4201} 4202 4203static VALUE 4204ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) 4205{ 4206 HRESULT hr; 4207 TYPEATTR *pTypeAttr; 4208 WORD i; 4209 HREFTYPE href; 4210 ITypeInfo *pRefTypeInfo; 4211 VALUE methods = rb_ary_new(); 4212 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 4213 if (FAILED(hr)) { 4214 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 4215 } 4216 4217 ole_methods_sub(0, pTypeInfo, methods, mask); 4218 for(i=0; i < pTypeAttr->cImplTypes; i++){ 4219 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 4220 if(FAILED(hr)) 4221 continue; 4222 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 4223 if (FAILED(hr)) 4224 continue; 4225 ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask); 4226 OLE_RELEASE(pRefTypeInfo); 4227 } 4228 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 4229 return methods; 4230} 4231 4232static HRESULT 4233typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti) 4234{ 4235 ITypeInfo *pTypeInfo; 4236 ITypeLib *pTypeLib; 4237 BSTR bstr; 4238 VALUE type; 4239 UINT i; 4240 UINT count; 4241 LCID lcid = cWIN32OLE_lcid; 4242 HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 4243 0, lcid, &pTypeInfo); 4244 if(FAILED(hr)) { 4245 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 4246 } 4247 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, 4248 -1, 4249 &bstr, 4250 NULL, NULL, NULL); 4251 type = WC2VSTR(bstr); 4252 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); 4253 OLE_RELEASE(pTypeInfo); 4254 if (FAILED(hr)) { 4255 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); 4256 } 4257 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 4258 for (i = 0; i < count; i++) { 4259 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 4260 &bstr, NULL, NULL, NULL); 4261 if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) { 4262 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 4263 if (SUCCEEDED(hr)) { 4264 *ppti = pTypeInfo; 4265 break; 4266 } 4267 } 4268 } 4269 OLE_RELEASE(pTypeLib); 4270 return hr; 4271} 4272 4273static VALUE 4274ole_methods(VALUE self, int mask) 4275{ 4276 ITypeInfo *pTypeInfo; 4277 HRESULT hr; 4278 VALUE methods; 4279 struct oledata *pole; 4280 4281 OLEData_Get_Struct(self, pole); 4282 methods = rb_ary_new(); 4283 4284 hr = typeinfo_from_ole(pole, &pTypeInfo); 4285 if(FAILED(hr)) 4286 return methods; 4287 rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask)); 4288 OLE_RELEASE(pTypeInfo); 4289 return methods; 4290} 4291 4292/* 4293 * call-seq: 4294 * WIN32OLE#ole_methods 4295 * 4296 * Returns the array of WIN32OLE_METHOD object. 4297 * The element is OLE method of WIN32OLE object. 4298 * 4299 * excel = WIN32OLE.new('Excel.Application') 4300 * methods = excel.ole_methods 4301 * 4302 */ 4303static VALUE 4304fole_methods(VALUE self) 4305{ 4306 return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); 4307} 4308 4309/* 4310 * call-seq: 4311 * WIN32OLE#ole_get_methods 4312 * 4313 * Returns the array of WIN32OLE_METHOD object . 4314 * The element of the array is property (gettable) of WIN32OLE object. 4315 * 4316 * excel = WIN32OLE.new('Excel.Application') 4317 * properties = excel.ole_get_methods 4318 */ 4319static VALUE 4320fole_get_methods(VALUE self) 4321{ 4322 return ole_methods( self, INVOKE_PROPERTYGET); 4323} 4324 4325/* 4326 * call-seq: 4327 * WIN32OLE#ole_put_methods 4328 * 4329 * Returns the array of WIN32OLE_METHOD object . 4330 * The element of the array is property (settable) of WIN32OLE object. 4331 * 4332 * excel = WIN32OLE.new('Excel.Application') 4333 * properties = excel.ole_put_methods 4334 */ 4335static VALUE 4336fole_put_methods(VALUE self) 4337{ 4338 return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF); 4339} 4340 4341/* 4342 * call-seq: 4343 * WIN32OLE#ole_func_methods 4344 * 4345 * Returns the array of WIN32OLE_METHOD object . 4346 * The element of the array is property (settable) of WIN32OLE object. 4347 * 4348 * excel = WIN32OLE.new('Excel.Application') 4349 * properties = excel.ole_func_methods 4350 * 4351 */ 4352static VALUE 4353fole_func_methods(VALUE self) 4354{ 4355 return ole_methods( self, INVOKE_FUNC); 4356} 4357 4358static VALUE 4359ole_type_from_itypeinfo(ITypeInfo *pTypeInfo) 4360{ 4361 ITypeLib *pTypeLib; 4362 VALUE type = Qnil; 4363 HRESULT hr; 4364 unsigned int index; 4365 BSTR bstr; 4366 4367 hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index ); 4368 if(FAILED(hr)) { 4369 return Qnil; 4370 } 4371 hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index, 4372 &bstr, NULL, NULL, NULL); 4373 OLE_RELEASE(pTypeLib); 4374 if (FAILED(hr)) { 4375 return Qnil; 4376 } 4377 type = foletype_s_allocate(cWIN32OLE_TYPE); 4378 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr)); 4379 return type; 4380} 4381 4382/* 4383 * call-seq: 4384 * WIN32OLE#ole_type 4385 * 4386 * Returns WIN32OLE_TYPE object. 4387 * 4388 * excel = WIN32OLE.new('Excel.Application') 4389 * tobj = excel.ole_type 4390 */ 4391static VALUE 4392fole_type(VALUE self) 4393{ 4394 ITypeInfo *pTypeInfo; 4395 HRESULT hr; 4396 struct oledata *pole; 4397 LCID lcid = cWIN32OLE_lcid; 4398 VALUE type = Qnil; 4399 4400 OLEData_Get_Struct(self, pole); 4401 4402 hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo ); 4403 if(FAILED(hr)) { 4404 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 4405 } 4406 type = ole_type_from_itypeinfo(pTypeInfo); 4407 OLE_RELEASE(pTypeInfo); 4408 if (type == Qnil) { 4409 rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo"); 4410 } 4411 return type; 4412} 4413 4414static VALUE 4415ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo) 4416{ 4417 HRESULT hr; 4418 ITypeLib *pTypeLib; 4419 unsigned int index; 4420 VALUE retval = Qnil; 4421 4422 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); 4423 if(FAILED(hr)) { 4424 return Qnil; 4425 } 4426 retval = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0); 4427 oletypelib_set_member(retval, pTypeLib); 4428 return retval; 4429} 4430 4431/* 4432 * call-seq: 4433 * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object 4434 * 4435 * Returns the WIN32OLE_TYPELIB object. The object represents the 4436 * type library which contains the WIN32OLE object. 4437 * 4438 * excel = WIN32OLE.new('Excel.Application') 4439 * tlib = excel.ole_typelib 4440 * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library' 4441 */ 4442static VALUE 4443fole_typelib(VALUE self) 4444{ 4445 struct oledata *pole; 4446 HRESULT hr; 4447 ITypeInfo *pTypeInfo; 4448 LCID lcid = cWIN32OLE_lcid; 4449 VALUE vtlib = Qnil; 4450 4451 OLEData_Get_Struct(self, pole); 4452 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 4453 0, lcid, &pTypeInfo); 4454 if(FAILED(hr)) { 4455 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 4456 } 4457 vtlib = ole_typelib_from_itypeinfo(pTypeInfo); 4458 OLE_RELEASE(pTypeInfo); 4459 if (vtlib == Qnil) { 4460 rb_raise(rb_eRuntimeError, "failed to get type library info."); 4461 } 4462 return vtlib; 4463} 4464 4465/* 4466 * call-seq: 4467 * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object 4468 * 4469 * Returns WIN32OLE object for a specific dispatch or dual 4470 * interface specified by iid. 4471 * 4472 * ie = WIN32OLE.new('InternetExplorer.Application') 4473 * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp 4474 */ 4475static VALUE 4476fole_query_interface(VALUE self, VALUE str_iid) 4477{ 4478 HRESULT hr; 4479 OLECHAR *pBuf; 4480 IID iid; 4481 struct oledata *pole; 4482 IDispatch *pDispatch; 4483 void *p; 4484 4485 pBuf = ole_vstr2wc(str_iid); 4486 hr = CLSIDFromString(pBuf, &iid); 4487 SysFreeString(pBuf); 4488 if(FAILED(hr)) { 4489 ole_raise(hr, eWIN32OLERuntimeError, 4490 "invalid iid: `%s'", 4491 StringValuePtr(str_iid)); 4492 } 4493 4494 OLEData_Get_Struct(self, pole); 4495 if(!pole->pDispatch) { 4496 rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); 4497 } 4498 4499 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid, 4500 &p); 4501 if(FAILED(hr)) { 4502 ole_raise(hr, eWIN32OLERuntimeError, 4503 "failed to get interface `%s'", 4504 StringValuePtr(str_iid)); 4505 } 4506 4507 pDispatch = p; 4508 return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 4509} 4510 4511/* 4512 * call-seq: 4513 * WIN32OLE#ole_respond_to?(method) -> true or false 4514 * 4515 * Returns true when OLE object has OLE method, otherwise returns false. 4516 * 4517 * ie = WIN32OLE.new('InternetExplorer.Application') 4518 * ie.ole_respond_to?("gohome") => true 4519 */ 4520static VALUE 4521fole_respond_to(VALUE self, VALUE method) 4522{ 4523 struct oledata *pole; 4524 BSTR wcmdname; 4525 DISPID DispID; 4526 HRESULT hr; 4527 rb_secure(4); 4528 if(TYPE(method) != T_STRING && TYPE(method) != T_SYMBOL) { 4529 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 4530 } 4531 if (TYPE(method) == T_SYMBOL) { 4532 method = rb_sym_to_s(method); 4533 } 4534 OLEData_Get_Struct(self, pole); 4535 wcmdname = ole_vstr2wc(method); 4536 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, 4537 &wcmdname, 1, cWIN32OLE_lcid, &DispID); 4538 SysFreeString(wcmdname); 4539 return SUCCEEDED(hr) ? Qtrue : Qfalse; 4540} 4541 4542static HRESULT 4543ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile) 4544{ 4545 HRESULT hr; 4546 ITypeLib *pTypeLib; 4547 UINT i; 4548 4549 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); 4550 if (FAILED(hr)) { 4551 return hr; 4552 } 4553 4554 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 4555 name, helpstr, 4556 helpcontext, helpfile); 4557 if (FAILED(hr)) { 4558 OLE_RELEASE(pTypeLib); 4559 return hr; 4560 } 4561 OLE_RELEASE(pTypeLib); 4562 return hr; 4563} 4564 4565static VALUE 4566ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 4567{ 4568 HRESULT hr; 4569 BSTR bstr; 4570 ITypeInfo *pRefTypeInfo; 4571 VALUE type = Qnil; 4572 4573 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 4574 V_UNION1(pTypeDesc, hreftype), 4575 &pRefTypeInfo); 4576 if(FAILED(hr)) 4577 return Qnil; 4578 hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL); 4579 if(FAILED(hr)) { 4580 OLE_RELEASE(pRefTypeInfo); 4581 return Qnil; 4582 } 4583 OLE_RELEASE(pRefTypeInfo); 4584 type = WC2VSTR(bstr); 4585 if(typedetails != Qnil) 4586 rb_ary_push(typedetails, type); 4587 return type; 4588} 4589 4590static VALUE 4591ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 4592{ 4593 TYPEDESC *p = pTypeDesc; 4594 VALUE type = rb_str_new2(""); 4595 4596 if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) { 4597 p = V_UNION1(p, lptdesc); 4598 type = ole_typedesc2val(pTypeInfo, p, typedetails); 4599 } 4600 return type; 4601} 4602 4603static VALUE 4604ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 4605{ 4606 VALUE str; 4607 VALUE typestr = Qnil; 4608 switch(pTypeDesc->vt) { 4609 case VT_I2: 4610 typestr = rb_str_new2("I2"); 4611 break; 4612 case VT_I4: 4613 typestr = rb_str_new2("I4"); 4614 break; 4615 case VT_R4: 4616 typestr = rb_str_new2("R4"); 4617 break; 4618 case VT_R8: 4619 typestr = rb_str_new2("R8"); 4620 break; 4621 case VT_CY: 4622 typestr = rb_str_new2("CY"); 4623 break; 4624 case VT_DATE: 4625 typestr = rb_str_new2("DATE"); 4626 break; 4627 case VT_BSTR: 4628 typestr = rb_str_new2("BSTR"); 4629 break; 4630 case VT_BOOL: 4631 typestr = rb_str_new2("BOOL"); 4632 break; 4633 case VT_VARIANT: 4634 typestr = rb_str_new2("VARIANT"); 4635 break; 4636 case VT_DECIMAL: 4637 typestr = rb_str_new2("DECIMAL"); 4638 break; 4639 case VT_I1: 4640 typestr = rb_str_new2("I1"); 4641 break; 4642 case VT_UI1: 4643 typestr = rb_str_new2("UI1"); 4644 break; 4645 case VT_UI2: 4646 typestr = rb_str_new2("UI2"); 4647 break; 4648 case VT_UI4: 4649 typestr = rb_str_new2("UI4"); 4650 break; 4651#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 4652 case VT_I8: 4653 typestr = rb_str_new2("I8"); 4654 break; 4655 case VT_UI8: 4656 typestr = rb_str_new2("UI8"); 4657 break; 4658#endif 4659 case VT_INT: 4660 typestr = rb_str_new2("INT"); 4661 break; 4662 case VT_UINT: 4663 typestr = rb_str_new2("UINT"); 4664 break; 4665 case VT_VOID: 4666 typestr = rb_str_new2("VOID"); 4667 break; 4668 case VT_HRESULT: 4669 typestr = rb_str_new2("HRESULT"); 4670 break; 4671 case VT_PTR: 4672 typestr = rb_str_new2("PTR"); 4673 if(typedetails != Qnil) 4674 rb_ary_push(typedetails, typestr); 4675 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); 4676 case VT_SAFEARRAY: 4677 typestr = rb_str_new2("SAFEARRAY"); 4678 if(typedetails != Qnil) 4679 rb_ary_push(typedetails, typestr); 4680 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); 4681 case VT_CARRAY: 4682 typestr = rb_str_new2("CARRAY"); 4683 break; 4684 case VT_USERDEFINED: 4685 typestr = rb_str_new2("USERDEFINED"); 4686 if (typedetails != Qnil) 4687 rb_ary_push(typedetails, typestr); 4688 str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails); 4689 if (str != Qnil) { 4690 return str; 4691 } 4692 return typestr; 4693 case VT_UNKNOWN: 4694 typestr = rb_str_new2("UNKNOWN"); 4695 break; 4696 case VT_DISPATCH: 4697 typestr = rb_str_new2("DISPATCH"); 4698 break; 4699 case VT_ERROR: 4700 typestr = rb_str_new2("ERROR"); 4701 break; 4702 case VT_LPWSTR: 4703 typestr = rb_str_new2("LPWSTR"); 4704 break; 4705 case VT_LPSTR: 4706 typestr = rb_str_new2("LPSTR"); 4707 break; 4708 default: 4709 typestr = rb_str_new2("Unknown Type "); 4710 rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10)); 4711 break; 4712 } 4713 if (typedetails != Qnil) 4714 rb_ary_push(typedetails, typestr); 4715 return typestr; 4716} 4717 4718/* 4719 * call-seq: 4720 * WIN32OLE#ole_method_help(method) 4721 * 4722 * Returns WIN32OLE_METHOD object corresponding with method 4723 * specified by 1st argument. 4724 * 4725 * excel = WIN32OLE.new('Excel.Application') 4726 * method = excel.ole_method_help('Quit') 4727 * 4728 */ 4729static VALUE 4730fole_method_help(VALUE self, VALUE cmdname) 4731{ 4732 ITypeInfo *pTypeInfo; 4733 HRESULT hr; 4734 struct oledata *pole; 4735 VALUE method, obj; 4736 4737 SafeStringValue(cmdname); 4738 OLEData_Get_Struct(self, pole); 4739 hr = typeinfo_from_ole(pole, &pTypeInfo); 4740 if(FAILED(hr)) 4741 ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo"); 4742 method = folemethod_s_allocate(cWIN32OLE_METHOD); 4743 obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname); 4744 OLE_RELEASE(pTypeInfo); 4745 if (obj == Qnil) 4746 rb_raise(eWIN32OLERuntimeError, "not found %s", 4747 StringValuePtr(cmdname)); 4748 return obj; 4749} 4750 4751/* 4752 * call-seq: 4753 * WIN32OLE#ole_activex_initialize() -> Qnil 4754 * 4755 * Initialize WIN32OLE object(ActiveX Control) by calling 4756 * IPersistMemory::InitNew. 4757 * 4758 * Before calling OLE method, some kind of the ActiveX controls 4759 * created with MFC should be initialized by calling 4760 * IPersistXXX::InitNew. 4761 * 4762 * If and only if you received the exception "HRESULT error code: 4763 * 0x8000ffff catastrophic failure", try this method before 4764 * invoking any ole_method. 4765 * 4766 * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control") 4767 * obj.ole_activex_initialize 4768 * obj.method(...) 4769 * 4770 */ 4771static VALUE 4772fole_activex_initialize(VALUE self) 4773{ 4774 struct oledata *pole; 4775 IPersistMemory *pPersistMemory; 4776 void *p; 4777 4778 HRESULT hr = S_OK; 4779 4780 OLEData_Get_Struct(self, pole); 4781 4782 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p); 4783 pPersistMemory = p; 4784 if (SUCCEEDED(hr)) { 4785 hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory); 4786 OLE_RELEASE(pPersistMemory); 4787 if (SUCCEEDED(hr)) { 4788 return Qnil; 4789 } 4790 } 4791 4792 if (FAILED(hr)) { 4793 ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control"); 4794 } 4795 4796 return Qnil; 4797} 4798 4799/* 4800 * call-seq: 4801 * WIN32OLE_TYPE.ole_classes(typelib) 4802 * 4803 * Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library. 4804 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead. 4805 */ 4806static VALUE 4807foletype_s_ole_classes(VALUE self, VALUE typelib) 4808{ 4809 VALUE obj; 4810 4811 /* 4812 rb_warn("%s is obsolete; use %s instead.", 4813 "WIN32OLE_TYPE.ole_classes", 4814 "WIN32OLE_TYPELIB.new(typelib).ole_types"); 4815 */ 4816 obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib); 4817 return rb_funcall(obj, rb_intern("ole_types"), 0); 4818} 4819 4820/* 4821 * call-seq: 4822 * WIN32OLE_TYPE.typelibs 4823 * 4824 * Returns array of type libraries. 4825 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead. 4826 * 4827 */ 4828static VALUE 4829foletype_s_typelibs(VALUE self) 4830{ 4831 /* 4832 rb_warn("%s is obsolete. use %s instead.", 4833 "WIN32OLE_TYPE.typelibs", 4834 "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}"); 4835 */ 4836 return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}"); 4837} 4838 4839/* 4840 * call-seq: 4841 * WIN32OLE_TYPE.progids 4842 * 4843 * Returns array of ProgID. 4844 */ 4845static VALUE 4846foletype_s_progids(VALUE self) 4847{ 4848 HKEY hclsids, hclsid; 4849 DWORD i; 4850 LONG err; 4851 VALUE clsid; 4852 VALUE v = rb_str_new2(""); 4853 VALUE progids = rb_ary_new(); 4854 4855 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids); 4856 if(err != ERROR_SUCCESS) { 4857 return progids; 4858 } 4859 for(i = 0; ; i++) { 4860 clsid = reg_enum_key(hclsids, i); 4861 if (clsid == Qnil) 4862 break; 4863 err = reg_open_vkey(hclsids, clsid, &hclsid); 4864 if (err != ERROR_SUCCESS) 4865 continue; 4866 if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil) 4867 rb_ary_push(progids, v); 4868 if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil) 4869 rb_ary_push(progids, v); 4870 RegCloseKey(hclsid); 4871 } 4872 RegCloseKey(hclsids); 4873 return progids; 4874} 4875 4876static VALUE 4877foletype_s_allocate(VALUE klass) 4878{ 4879 struct oletypedata *poletype; 4880 VALUE obj; 4881 ole_initialize(); 4882 obj = Data_Make_Struct(klass,struct oletypedata,0,oletype_free,poletype); 4883 poletype->pTypeInfo = NULL; 4884 return obj; 4885} 4886 4887static VALUE 4888oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name) 4889{ 4890 struct oletypedata *ptype; 4891 Data_Get_Struct(self, struct oletypedata, ptype); 4892 rb_ivar_set(self, rb_intern("name"), name); 4893 ptype->pTypeInfo = pTypeInfo; 4894 if(pTypeInfo) OLE_ADDREF(pTypeInfo); 4895 return self; 4896} 4897 4898static VALUE 4899oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) 4900{ 4901 4902 long count; 4903 int i; 4904 HRESULT hr; 4905 BSTR bstr; 4906 VALUE typelib; 4907 ITypeInfo *pTypeInfo; 4908 4909 VALUE found = Qfalse; 4910 4911 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 4912 for (i = 0; i < count && found == Qfalse; i++) { 4913 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 4914 if (FAILED(hr)) 4915 continue; 4916 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 4917 &bstr, NULL, NULL, NULL); 4918 if (FAILED(hr)) 4919 continue; 4920 typelib = WC2VSTR(bstr); 4921 if (rb_str_cmp(oleclass, typelib) == 0) { 4922 oletype_set_member(self, pTypeInfo, typelib); 4923 found = Qtrue; 4924 } 4925 OLE_RELEASE(pTypeInfo); 4926 } 4927 return found; 4928} 4929 4930/* 4931 * Document-class: WIN32OLE_TYPELIB 4932 * 4933 * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information. 4934 */ 4935 4936static VALUE 4937oletypelib_set_member(VALUE self, ITypeLib *pTypeLib) 4938{ 4939 struct oletypelibdata *ptlib; 4940 Data_Get_Struct(self, struct oletypelibdata, ptlib); 4941 ptlib->pTypeLib = pTypeLib; 4942 return self; 4943} 4944 4945static ITypeLib * 4946oletypelib_get_typelib(VALUE self) 4947{ 4948 struct oletypelibdata *ptlib; 4949 Data_Get_Struct(self, struct oletypelibdata, ptlib); 4950 return ptlib->pTypeLib; 4951} 4952 4953static void 4954oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr) 4955{ 4956 HRESULT hr; 4957 hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr); 4958 if (FAILED(hr)) { 4959 ole_raise(hr, eWIN32OLERuntimeError, 4960 "failed to get library attribute(TLIBATTR) from ITypeLib"); 4961 } 4962} 4963 4964/* 4965 * call-seq: 4966 * 4967 * WIN32OLE_TYPELIB.typelibs 4968 * 4969 * Returns the array of WIN32OLE_TYPELIB object. 4970 * 4971 * tlibs = WIN32OLE_TYPELIB.typelibs 4972 * 4973 */ 4974static VALUE 4975foletypelib_s_typelibs(VALUE self) 4976{ 4977 HKEY htypelib, hguid; 4978 DWORD i, j; 4979 LONG err; 4980 VALUE guid; 4981 VALUE version; 4982 VALUE name = Qnil; 4983 VALUE typelibs = rb_ary_new(); 4984 VALUE typelib = Qnil; 4985 HRESULT hr; 4986 ITypeLib *pTypeLib; 4987 4988 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 4989 if(err != ERROR_SUCCESS) { 4990 return typelibs; 4991 } 4992 for(i = 0; ; i++) { 4993 guid = reg_enum_key(htypelib, i); 4994 if (guid == Qnil) 4995 break; 4996 err = reg_open_vkey(htypelib, guid, &hguid); 4997 if (err != ERROR_SUCCESS) 4998 continue; 4999 for(j = 0; ; j++) { 5000 version = reg_enum_key(hguid, j); 5001 if (version == Qnil) 5002 break; 5003 if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) { 5004 hr = oletypelib_from_guid(guid, version, &pTypeLib); 5005 if (SUCCEEDED(hr)) { 5006 typelib = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0); 5007 oletypelib_set_member(typelib, pTypeLib); 5008 rb_ary_push(typelibs, typelib); 5009 } 5010 } 5011 } 5012 RegCloseKey(hguid); 5013 } 5014 RegCloseKey(htypelib); 5015 return typelibs; 5016} 5017 5018static VALUE 5019make_version_str(VALUE major, VALUE minor) 5020{ 5021 VALUE version_str = Qnil; 5022 VALUE minor_str = Qnil; 5023 if (major == Qnil) { 5024 return Qnil; 5025 } 5026 version_str = rb_String(major); 5027 if (minor != Qnil) { 5028 minor_str = rb_String(minor); 5029 rb_str_cat2(version_str, "."); 5030 rb_str_append(version_str, minor_str); 5031 } 5032 return version_str; 5033} 5034 5035static VALUE 5036oletypelib_search_registry2(VALUE self, VALUE args) 5037{ 5038 HKEY htypelib, hguid, hversion; 5039 double fver; 5040 DWORD j; 5041 LONG err; 5042 VALUE found = Qfalse; 5043 VALUE tlib; 5044 VALUE ver; 5045 VALUE version_str; 5046 VALUE version = Qnil; 5047 VALUE typelib = Qnil; 5048 HRESULT hr; 5049 ITypeLib *pTypeLib; 5050 5051 VALUE guid = rb_ary_entry(args, 0); 5052 version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2)); 5053 5054 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 5055 if(err != ERROR_SUCCESS) { 5056 return Qfalse; 5057 } 5058 err = reg_open_vkey(htypelib, guid, &hguid); 5059 if (err != ERROR_SUCCESS) { 5060 RegCloseKey(htypelib); 5061 return Qfalse; 5062 } 5063 if (version_str != Qnil) { 5064 err = reg_open_vkey(hguid, version_str, &hversion); 5065 if (err == ERROR_SUCCESS) { 5066 tlib = reg_get_val(hversion, NULL); 5067 if (tlib != Qnil) { 5068 typelib = tlib; 5069 version = version_str; 5070 } 5071 } 5072 RegCloseKey(hversion); 5073 } else { 5074 fver = 0.0; 5075 for(j = 0; ;j++) { 5076 ver = reg_enum_key(hguid, j); 5077 if (ver == Qnil) 5078 break; 5079 err = reg_open_vkey(hguid, ver, &hversion); 5080 if (err != ERROR_SUCCESS) 5081 continue; 5082 tlib = reg_get_val(hversion, NULL); 5083 if (tlib == Qnil) { 5084 RegCloseKey(hversion); 5085 continue; 5086 } 5087 if (fver < atof(StringValuePtr(ver))) { 5088 fver = atof(StringValuePtr(ver)); 5089 version = ver; 5090 typelib = tlib; 5091 } 5092 RegCloseKey(hversion); 5093 } 5094 } 5095 RegCloseKey(hguid); 5096 RegCloseKey(htypelib); 5097 if (typelib != Qnil) { 5098 hr = oletypelib_from_guid(guid, version, &pTypeLib); 5099 if (SUCCEEDED(hr)) { 5100 found = Qtrue; 5101 oletypelib_set_member(self, pTypeLib); 5102 } 5103 } 5104 return found; 5105} 5106 5107static VALUE 5108oletypelib_search_registry(VALUE self, VALUE typelib) 5109{ 5110 HKEY htypelib, hguid, hversion; 5111 DWORD i, j; 5112 LONG err; 5113 VALUE found = Qfalse; 5114 VALUE tlib; 5115 VALUE guid; 5116 VALUE ver; 5117 HRESULT hr; 5118 ITypeLib *pTypeLib; 5119 5120 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 5121 if(err != ERROR_SUCCESS) { 5122 return Qfalse; 5123 } 5124 for(i = 0; !found; i++) { 5125 guid = reg_enum_key(htypelib, i); 5126 if (guid == Qnil) 5127 break; 5128 err = reg_open_vkey(htypelib, guid, &hguid); 5129 if (err != ERROR_SUCCESS) 5130 continue; 5131 for(j = 0; found == Qfalse; j++) { 5132 ver = reg_enum_key(hguid, j); 5133 if (ver == Qnil) 5134 break; 5135 err = reg_open_vkey(hguid, ver, &hversion); 5136 if (err != ERROR_SUCCESS) 5137 continue; 5138 tlib = reg_get_val(hversion, NULL); 5139 if (tlib == Qnil) { 5140 RegCloseKey(hversion); 5141 continue; 5142 } 5143 if (rb_str_cmp(typelib, tlib) == 0) { 5144 hr = oletypelib_from_guid(guid, ver, &pTypeLib); 5145 if (SUCCEEDED(hr)) { 5146 oletypelib_set_member(self, pTypeLib); 5147 found = Qtrue; 5148 } 5149 } 5150 RegCloseKey(hversion); 5151 } 5152 RegCloseKey(hguid); 5153 } 5154 RegCloseKey(htypelib); 5155 return found; 5156} 5157 5158static VALUE 5159foletypelib_s_allocate(VALUE klass) 5160{ 5161 struct oletypelibdata *poletypelib; 5162 VALUE obj; 5163 ole_initialize(); 5164 obj = Data_Make_Struct(klass, struct oletypelibdata, 0, oletypelib_free, poletypelib); 5165 poletypelib->pTypeLib = NULL; 5166 return obj; 5167} 5168 5169/* 5170 * call-seq: 5171 * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object 5172 * 5173 * Returns a new WIN32OLE_TYPELIB object. 5174 * 5175 * The first argument <i>typelib</i> specifies OLE type library name or GUID or 5176 * OLE library file. 5177 * The second argument is major version or version of the type library. 5178 * The third argument is minor version. 5179 * The second argument and third argument are optional. 5180 * If the first argument is type library name, then the second and third argument 5181 * are ignored. 5182 * 5183 * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5184 * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}') 5185 * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3) 5186 * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3) 5187 * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL") 5188 * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library' 5189 * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library' 5190 * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library' 5191 * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library' 5192 * puts tlib5.name # -> 'Microsoft Shell Controls And Automation' 5193 * 5194 */ 5195static VALUE 5196foletypelib_initialize(VALUE self, VALUE args) 5197{ 5198 VALUE found = Qfalse; 5199 VALUE typelib = Qnil; 5200 int len = 0; 5201 OLECHAR * pbuf; 5202 ITypeLib *pTypeLib; 5203 HRESULT hr = S_OK; 5204 5205 len = RARRAY_LEN(args); 5206 if (len < 1 || len > 3) { 5207 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); 5208 } 5209 5210 typelib = rb_ary_entry(args, 0); 5211 5212 SafeStringValue(typelib); 5213 5214 found = oletypelib_search_registry(self, typelib); 5215 if (found == Qfalse) { 5216 found = oletypelib_search_registry2(self, args); 5217 } 5218 if (found == Qfalse) { 5219 pbuf = ole_vstr2wc(typelib); 5220 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); 5221 SysFreeString(pbuf); 5222 if (SUCCEEDED(hr)) { 5223 found = Qtrue; 5224 oletypelib_set_member(self, pTypeLib); 5225 } 5226 } 5227 5228 if (found == Qfalse) { 5229 rb_raise(eWIN32OLERuntimeError, "not found type library `%s`", 5230 StringValuePtr(typelib)); 5231 } 5232 return self; 5233} 5234 5235/* 5236 * call-seq: 5237 * WIN32OLE_TYPELIB#guid -> The guid string. 5238 * 5239 * Returns guid string which specifies type library. 5240 * 5241 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5242 * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}' 5243 */ 5244static VALUE 5245foletypelib_guid(VALUE self) 5246{ 5247 ITypeLib *pTypeLib; 5248 OLECHAR bstr[80]; 5249 VALUE guid = Qnil; 5250 int len; 5251 TLIBATTR *pTLibAttr; 5252 5253 pTypeLib = oletypelib_get_typelib(self); 5254 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 5255 len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 5256 if (len > 3) { 5257 guid = ole_wc2vstr(bstr, FALSE); 5258 } 5259 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5260 return guid; 5261} 5262 5263/* 5264 * call-seq: 5265 * WIN32OLE_TYPELIB#name -> The type library name 5266 * 5267 * Returns the type library name. 5268 * 5269 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5270 * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library' 5271 */ 5272static VALUE 5273foletypelib_name(VALUE self) 5274{ 5275 ITypeLib *pTypeLib; 5276 HRESULT hr; 5277 BSTR bstr; 5278 VALUE name; 5279 pTypeLib = oletypelib_get_typelib(self); 5280 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, 5281 NULL, &bstr, NULL, NULL); 5282 5283 if (FAILED(hr)) { 5284 ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib"); 5285 } 5286 name = WC2VSTR(bstr); 5287 return rb_enc_str_new(StringValuePtr(name), strlen(StringValuePtr(name)), cWIN32OLE_enc); 5288} 5289 5290/* 5291 * call-seq: 5292 * WIN32OLE_TYPELIB#version -> The type library version. 5293 * 5294 * Returns the type library version. 5295 * 5296 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5297 * puts tlib.version #-> 1.3 5298 */ 5299static VALUE 5300foletypelib_version(VALUE self) 5301{ 5302 TLIBATTR *pTLibAttr; 5303 VALUE major; 5304 VALUE minor; 5305 ITypeLib *pTypeLib; 5306 5307 pTypeLib = oletypelib_get_typelib(self); 5308 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 5309 major = INT2NUM(pTLibAttr->wMajorVerNum); 5310 minor = INT2NUM(pTLibAttr->wMinorVerNum); 5311 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5312 return rb_Float(make_version_str(major, minor)); 5313} 5314 5315/* 5316 * call-seq: 5317 * WIN32OLE_TYPELIB#major_version -> The type library major version. 5318 * 5319 * Returns the type library major version. 5320 * 5321 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5322 * puts tlib.major_version # -> 1 5323 */ 5324static VALUE 5325foletypelib_major_version(VALUE self) 5326{ 5327 TLIBATTR *pTLibAttr; 5328 VALUE major; 5329 ITypeLib *pTypeLib; 5330 pTypeLib = oletypelib_get_typelib(self); 5331 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 5332 5333 major = INT2NUM(pTLibAttr->wMajorVerNum); 5334 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5335 return major; 5336} 5337 5338/* 5339 * call-seq: 5340 * WIN32OLE_TYPELIB#minor_version -> The type library minor version. 5341 * 5342 * Returns the type library minor version. 5343 * 5344 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5345 * puts tlib.minor_version # -> 3 5346 */ 5347static VALUE 5348foletypelib_minor_version(VALUE self) 5349{ 5350 TLIBATTR *pTLibAttr; 5351 VALUE minor; 5352 ITypeLib *pTypeLib; 5353 pTypeLib = oletypelib_get_typelib(self); 5354 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 5355 minor = INT2NUM(pTLibAttr->wMinorVerNum); 5356 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5357 return minor; 5358} 5359 5360static VALUE 5361oletypelib_path(VALUE guid, VALUE version) 5362{ 5363 int k; 5364 LONG err; 5365 HKEY hkey; 5366 HKEY hlang; 5367 VALUE lang; 5368 VALUE path = Qnil; 5369 5370 VALUE key = rb_str_new2("TypeLib\\"); 5371 rb_str_concat(key, guid); 5372 rb_str_cat2(key, "\\"); 5373 rb_str_concat(key, version); 5374 5375 err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey); 5376 if (err != ERROR_SUCCESS) { 5377 return Qnil; 5378 } 5379 for(k = 0; path == Qnil; k++) { 5380 lang = reg_enum_key(hkey, k); 5381 if (lang == Qnil) 5382 break; 5383 err = reg_open_vkey(hkey, lang, &hlang); 5384 if (err == ERROR_SUCCESS) { 5385 path = reg_get_typelib_file_path(hlang); 5386 RegCloseKey(hlang); 5387 } 5388 } 5389 RegCloseKey(hkey); 5390 return path; 5391} 5392 5393static HRESULT 5394oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib) 5395{ 5396 VALUE path; 5397 OLECHAR *pBuf; 5398 HRESULT hr; 5399 path = oletypelib_path(guid, version); 5400 if (path == Qnil) { 5401 return E_UNEXPECTED; 5402 } 5403 pBuf = ole_vstr2wc(path); 5404 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib); 5405 SysFreeString(pBuf); 5406 return hr; 5407} 5408 5409/* 5410 * call-seq: 5411 * WIN32OLE_TYPELIB#path -> The type library file path. 5412 * 5413 * Returns the type library file path. 5414 * 5415 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5416 * puts tlib.path #-> 'C:\...\EXCEL9.OLB' 5417 */ 5418static VALUE 5419foletypelib_path(VALUE self) 5420{ 5421 TLIBATTR *pTLibAttr; 5422 HRESULT hr = S_OK; 5423 BSTR bstr; 5424 LCID lcid = cWIN32OLE_lcid; 5425 VALUE path; 5426 ITypeLib *pTypeLib; 5427 5428 pTypeLib = oletypelib_get_typelib(self); 5429 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 5430 hr = QueryPathOfRegTypeLib(&pTLibAttr->guid, 5431 pTLibAttr->wMajorVerNum, 5432 pTLibAttr->wMinorVerNum, 5433 lcid, 5434 &bstr); 5435 if (FAILED(hr)) { 5436 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5437 ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib"); 5438 } 5439 5440 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5441 path = WC2VSTR(bstr); 5442 return rb_enc_str_new(StringValuePtr(path), strlen(StringValuePtr(path)), cWIN32OLE_enc); 5443} 5444 5445/* 5446 * call-seq: 5447 * WIN32OLE_TYPELIB#visible? 5448 * 5449 * Returns true if the type library information is not hidden. 5450 * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN, 5451 * the method returns false, otherwise, returns true. 5452 * If the method fails to access the TLIBATTR information, then 5453 * WIN32OLERuntimeError is raised. 5454 * 5455 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5456 * tlib.visible? # => true 5457 */ 5458static VALUE 5459foletypelib_visible(VALUE self) 5460{ 5461 ITypeLib *pTypeLib = NULL; 5462 VALUE visible = Qtrue; 5463 TLIBATTR *pTLibAttr; 5464 5465 pTypeLib = oletypelib_get_typelib(self); 5466 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 5467 5468 if ((pTLibAttr->wLibFlags == 0) || 5469 (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) || 5470 (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) { 5471 visible = Qfalse; 5472 } 5473 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 5474 return visible; 5475} 5476 5477/* 5478 * call-seq: 5479 * WIN32OLE_TYPELIB#library_name 5480 * 5481 * Returns library name. 5482 * If the method fails to access library name, WIN32OLERuntimeError is raised. 5483 * 5484 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5485 * tlib.library_name # => Excel 5486 */ 5487static VALUE 5488foletypelib_library_name(VALUE self) 5489{ 5490 HRESULT hr; 5491 ITypeLib *pTypeLib = NULL; 5492 VALUE libname = Qnil; 5493 BSTR bstr; 5494 5495 pTypeLib = oletypelib_get_typelib(self); 5496 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, 5497 &bstr, NULL, NULL, NULL); 5498 if (FAILED(hr)) { 5499 ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name"); 5500 } 5501 libname = WC2VSTR(bstr); 5502 return libname; 5503} 5504 5505 5506/* 5507 * call-seq: 5508 * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library. 5509 * 5510 * Returns the type library file path. 5511 * 5512 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5513 * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...] 5514 */ 5515static VALUE 5516foletypelib_ole_types(VALUE self) 5517{ 5518 ITypeLib *pTypeLib = NULL; 5519 VALUE classes = rb_ary_new(); 5520 pTypeLib = oletypelib_get_typelib(self); 5521 ole_types_from_typelib(pTypeLib, classes); 5522 return classes; 5523} 5524 5525/* 5526 * call-seq: 5527 * WIN32OLE_TYPELIB#inspect -> String 5528 * 5529 * Returns the type library name with class name. 5530 * 5531 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 5532 * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>" 5533 */ 5534static VALUE 5535foletypelib_inspect(VALUE self) 5536{ 5537 return default_inspect(self, "WIN32OLE_TYPELIB"); 5538} 5539 5540/* 5541 * Document-class: WIN32OLE_TYPE 5542 * 5543 * <code>WIN32OLE_TYPE</code> objects represent OLE type libarary information. 5544 */ 5545 5546/* 5547 * call-seq: 5548 * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object 5549 * 5550 * Returns a new WIN32OLE_TYPE object. 5551 * The first argument <i>typelib</i> specifies OLE type library name. 5552 * The second argument specifies OLE class name. 5553 * 5554 * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 5555 * # => WIN32OLE_TYPE object of Application class of Excel. 5556 */ 5557static VALUE 5558foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) 5559{ 5560 VALUE file; 5561 OLECHAR * pbuf; 5562 ITypeLib *pTypeLib; 5563 HRESULT hr; 5564 5565 SafeStringValue(oleclass); 5566 SafeStringValue(typelib); 5567 file = typelib_file(typelib); 5568 if (file == Qnil) { 5569 file = typelib; 5570 } 5571 pbuf = ole_vstr2wc(file); 5572 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); 5573 if (FAILED(hr)) 5574 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); 5575 SysFreeString(pbuf); 5576 if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) { 5577 OLE_RELEASE(pTypeLib); 5578 rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`", 5579 StringValuePtr(oleclass), StringValuePtr(typelib)); 5580 } 5581 OLE_RELEASE(pTypeLib); 5582 return self; 5583} 5584 5585/* 5586 * call-seq: 5587 * WIN32OLE_TYPE#name #=> OLE type name 5588 * 5589 * Returns OLE type name. 5590 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 5591 * puts tobj.name # => Application 5592 */ 5593static VALUE 5594foletype_name(VALUE self) 5595{ 5596 return rb_ivar_get(self, rb_intern("name")); 5597} 5598 5599static VALUE 5600ole_ole_type(ITypeInfo *pTypeInfo) 5601{ 5602 HRESULT hr; 5603 TYPEATTR *pTypeAttr; 5604 VALUE type = Qnil; 5605 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5606 if(FAILED(hr)){ 5607 return type; 5608 } 5609 switch(pTypeAttr->typekind) { 5610 case TKIND_ENUM: 5611 type = rb_str_new2("Enum"); 5612 break; 5613 case TKIND_RECORD: 5614 type = rb_str_new2("Record"); 5615 break; 5616 case TKIND_MODULE: 5617 type = rb_str_new2("Module"); 5618 break; 5619 case TKIND_INTERFACE: 5620 type = rb_str_new2("Interface"); 5621 break; 5622 case TKIND_DISPATCH: 5623 type = rb_str_new2("Dispatch"); 5624 break; 5625 case TKIND_COCLASS: 5626 type = rb_str_new2("Class"); 5627 break; 5628 case TKIND_ALIAS: 5629 type = rb_str_new2("Alias"); 5630 break; 5631 case TKIND_UNION: 5632 type = rb_str_new2("Union"); 5633 break; 5634 case TKIND_MAX: 5635 type = rb_str_new2("Max"); 5636 break; 5637 default: 5638 type = Qnil; 5639 break; 5640 } 5641 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5642 return type; 5643} 5644 5645/* 5646 * call-seq: 5647 * WIN32OLE_TYPE#ole_type #=> OLE type string. 5648 * 5649 * returns type of OLE class. 5650 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 5651 * puts tobj.ole_type # => Class 5652 */ 5653static VALUE 5654foletype_ole_type(VALUE self) 5655{ 5656 struct oletypedata *ptype; 5657 Data_Get_Struct(self, struct oletypedata, ptype); 5658 return ole_ole_type(ptype->pTypeInfo); 5659} 5660 5661static VALUE 5662ole_type_guid(ITypeInfo *pTypeInfo) 5663{ 5664 HRESULT hr; 5665 TYPEATTR *pTypeAttr; 5666 int len; 5667 OLECHAR bstr[80]; 5668 VALUE guid = Qnil; 5669 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5670 if (FAILED(hr)) 5671 return guid; 5672 len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 5673 if (len > 3) { 5674 guid = ole_wc2vstr(bstr, FALSE); 5675 } 5676 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5677 return guid; 5678} 5679 5680/* 5681 * call-seq: 5682 * WIN32OLE_TYPE#guid #=> GUID 5683 * 5684 * Returns GUID. 5685 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 5686 * puts tobj.guid # => {00024500-0000-0000-C000-000000000046} 5687 */ 5688static VALUE 5689foletype_guid(VALUE self) 5690{ 5691 struct oletypedata *ptype; 5692 Data_Get_Struct(self, struct oletypedata, ptype); 5693 return ole_type_guid(ptype->pTypeInfo); 5694} 5695 5696static VALUE 5697ole_type_progid(ITypeInfo *pTypeInfo) 5698{ 5699 HRESULT hr; 5700 TYPEATTR *pTypeAttr; 5701 OLECHAR *pbuf; 5702 VALUE progid = Qnil; 5703 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5704 if (FAILED(hr)) 5705 return progid; 5706 hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf); 5707 if (SUCCEEDED(hr)) { 5708 progid = ole_wc2vstr(pbuf, FALSE); 5709 CoTaskMemFree(pbuf); 5710 } 5711 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5712 return progid; 5713} 5714 5715/* 5716 * call-seq: 5717 * WIN32OLE_TYPE#progid #=> ProgID 5718 * 5719 * Returns ProgID if it exists. If not found, then returns nil. 5720 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 5721 * puts tobj.progid # => Excel.Application.9 5722 */ 5723static VALUE 5724foletype_progid(VALUE self) 5725{ 5726 struct oletypedata *ptype; 5727 Data_Get_Struct(self, struct oletypedata, ptype); 5728 return ole_type_progid(ptype->pTypeInfo); 5729} 5730 5731 5732static VALUE 5733ole_type_visible(ITypeInfo *pTypeInfo) 5734{ 5735 HRESULT hr; 5736 TYPEATTR *pTypeAttr; 5737 VALUE visible; 5738 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5739 if (FAILED(hr)) 5740 return Qtrue; 5741 if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) { 5742 visible = Qfalse; 5743 } else { 5744 visible = Qtrue; 5745 } 5746 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5747 return visible; 5748} 5749 5750/* 5751 * call-seq: 5752 * WIN32OLE_TYPE#visible #=> true or false 5753 * 5754 * Returns true if the OLE class is public. 5755 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 5756 * puts tobj.visible # => true 5757 */ 5758static VALUE 5759foletype_visible(VALUE self) 5760{ 5761 struct oletypedata *ptype; 5762 Data_Get_Struct(self, struct oletypedata, ptype); 5763 return ole_type_visible(ptype->pTypeInfo); 5764} 5765 5766static VALUE 5767ole_type_major_version(ITypeInfo *pTypeInfo) 5768{ 5769 VALUE ver; 5770 TYPEATTR *pTypeAttr; 5771 HRESULT hr; 5772 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5773 if (FAILED(hr)) 5774 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 5775 ver = INT2FIX(pTypeAttr->wMajorVerNum); 5776 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5777 return ver; 5778} 5779 5780/* 5781 * call-seq: 5782 * WIN32OLE_TYPE#major_version 5783 * 5784 * Returns major version. 5785 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 5786 * puts tobj.major_version # => 8 5787 */ 5788static VALUE 5789foletype_major_version(VALUE self) 5790{ 5791 struct oletypedata *ptype; 5792 Data_Get_Struct(self, struct oletypedata, ptype); 5793 return ole_type_major_version(ptype->pTypeInfo); 5794} 5795 5796static VALUE 5797ole_type_minor_version(ITypeInfo *pTypeInfo) 5798{ 5799 VALUE ver; 5800 TYPEATTR *pTypeAttr; 5801 HRESULT hr; 5802 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5803 if (FAILED(hr)) 5804 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 5805 ver = INT2FIX(pTypeAttr->wMinorVerNum); 5806 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5807 return ver; 5808} 5809 5810/* 5811 * call-seq: 5812 * WIN32OLE_TYPE#minor_version #=> OLE minor version 5813 * 5814 * Returns minor version. 5815 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 5816 * puts tobj.minor_version # => 2 5817 */ 5818static VALUE 5819foletype_minor_version(VALUE self) 5820{ 5821 struct oletypedata *ptype; 5822 Data_Get_Struct(self, struct oletypedata, ptype); 5823 return ole_type_minor_version(ptype->pTypeInfo); 5824} 5825 5826static VALUE 5827ole_type_typekind(ITypeInfo *pTypeInfo) 5828{ 5829 VALUE typekind; 5830 TYPEATTR *pTypeAttr; 5831 HRESULT hr; 5832 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5833 if (FAILED(hr)) 5834 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 5835 typekind = INT2FIX(pTypeAttr->typekind); 5836 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5837 return typekind; 5838} 5839 5840/* 5841 * call-seq: 5842 * WIN32OLE_TYPE#typekind #=> number of type. 5843 * 5844 * Returns number which represents type. 5845 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 5846 * puts tobj.typekind # => 4 5847 * 5848 */ 5849static VALUE 5850foletype_typekind(VALUE self) 5851{ 5852 struct oletypedata *ptype; 5853 Data_Get_Struct(self, struct oletypedata, ptype); 5854 return ole_type_typekind(ptype->pTypeInfo); 5855} 5856 5857static VALUE 5858ole_type_helpstring(ITypeInfo *pTypeInfo) 5859{ 5860 HRESULT hr; 5861 BSTR bhelpstr; 5862 hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL); 5863 if(FAILED(hr)) { 5864 return Qnil; 5865 } 5866 return WC2VSTR(bhelpstr); 5867} 5868 5869/* 5870 * call-seq: 5871 * WIN32OLE_TYPE#helpstring #=> help string. 5872 * 5873 * Returns help string. 5874 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') 5875 * puts tobj.helpstring # => Web Browser interface 5876 */ 5877static VALUE 5878foletype_helpstring(VALUE self) 5879{ 5880 struct oletypedata *ptype; 5881 Data_Get_Struct(self, struct oletypedata, ptype); 5882 return ole_type_helpstring(ptype->pTypeInfo); 5883} 5884 5885static VALUE 5886ole_type_src_type(ITypeInfo *pTypeInfo) 5887{ 5888 HRESULT hr; 5889 TYPEATTR *pTypeAttr; 5890 VALUE alias = Qnil; 5891 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 5892 if (FAILED(hr)) 5893 return alias; 5894 if(pTypeAttr->typekind != TKIND_ALIAS) { 5895 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5896 return alias; 5897 } 5898 alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil); 5899 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 5900 return alias; 5901} 5902 5903/* 5904 * call-seq: 5905 * WIN32OLE_TYPE#src_type #=> OLE source class 5906 * 5907 * Returns source class when the OLE class is 'Alias'. 5908 * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType') 5909 * puts tobj.src_type # => I4 5910 * 5911 */ 5912static VALUE 5913foletype_src_type(VALUE self) 5914{ 5915 struct oletypedata *ptype; 5916 Data_Get_Struct(self, struct oletypedata, ptype); 5917 return ole_type_src_type(ptype->pTypeInfo); 5918} 5919 5920static VALUE 5921ole_type_helpfile(ITypeInfo *pTypeInfo) 5922{ 5923 HRESULT hr; 5924 BSTR bhelpfile; 5925 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile); 5926 if(FAILED(hr)) { 5927 return Qnil; 5928 } 5929 return WC2VSTR(bhelpfile); 5930} 5931 5932/* 5933 * call-seq: 5934 * WIN32OLE_TYPE#helpfile 5935 * 5936 * Returns helpfile path. If helpfile is not found, then returns nil. 5937 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 5938 * puts tobj.helpfile # => C:\...\VBAXL9.CHM 5939 * 5940 */ 5941static VALUE 5942foletype_helpfile(VALUE self) 5943{ 5944 struct oletypedata *ptype; 5945 Data_Get_Struct(self, struct oletypedata, ptype); 5946 return ole_type_helpfile(ptype->pTypeInfo); 5947} 5948 5949static VALUE 5950ole_type_helpcontext(ITypeInfo *pTypeInfo) 5951{ 5952 HRESULT hr; 5953 DWORD helpcontext; 5954 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, 5955 &helpcontext, NULL); 5956 if(FAILED(hr)) 5957 return Qnil; 5958 return INT2FIX(helpcontext); 5959} 5960 5961/* 5962 * call-seq: 5963 * WIN32OLE_TYPE#helpcontext 5964 * 5965 * Returns helpcontext. If helpcontext is not found, then returns nil. 5966 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 5967 * puts tobj.helpfile # => 131185 5968 */ 5969static VALUE 5970foletype_helpcontext(VALUE self) 5971{ 5972 struct oletypedata *ptype; 5973 Data_Get_Struct(self, struct oletypedata, ptype); 5974 return ole_type_helpcontext(ptype->pTypeInfo); 5975} 5976 5977/* 5978 * call-seq: 5979 * WIN32OLE_TYPE#ole_typelib 5980 * 5981 * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE 5982 * object. If it is not found, then returns nil. 5983 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 5984 * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library' 5985 */ 5986static VALUE 5987foletype_ole_typelib(VALUE self) 5988{ 5989 struct oletypedata *ptype; 5990 Data_Get_Struct(self, struct oletypedata, ptype); 5991 return ole_typelib_from_itypeinfo(ptype->pTypeInfo); 5992} 5993 5994static VALUE 5995ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) 5996{ 5997 HRESULT hr; 5998 ITypeInfo *pRefTypeInfo; 5999 HREFTYPE href; 6000 WORD i; 6001 VALUE type; 6002 TYPEATTR *pTypeAttr; 6003 int flags; 6004 6005 VALUE types = rb_ary_new(); 6006 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 6007 if (FAILED(hr)) { 6008 return types; 6009 } 6010 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 6011 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 6012 if (FAILED(hr)) 6013 continue; 6014 6015 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 6016 if (FAILED(hr)) 6017 continue; 6018 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 6019 if (FAILED(hr)) 6020 continue; 6021 6022 if ((flags & implflags) == implflags) { 6023 type = ole_type_from_itypeinfo(pRefTypeInfo); 6024 if (type != Qnil) { 6025 rb_ary_push(types, type); 6026 } 6027 } 6028 6029 OLE_RELEASE(pRefTypeInfo); 6030 } 6031 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 6032 return types; 6033} 6034 6035/* 6036 * call-seq: 6037 * WIN32OLE_TYPE#implemented_ole_types 6038 * 6039 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 6040 * object. 6041 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 6042 * p tobj.implemented_ole_types # => [_Worksheet, DocEvents] 6043 */ 6044static VALUE 6045foletype_impl_ole_types(VALUE self) 6046{ 6047 struct oletypedata *ptype; 6048 Data_Get_Struct(self, struct oletypedata, ptype); 6049 return ole_type_impl_ole_types(ptype->pTypeInfo, 0); 6050} 6051 6052/* 6053 * call-seq: 6054 * WIN32OLE_TYPE#source_ole_types 6055 * 6056 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 6057 * object and having IMPLTYPEFLAG_FSOURCE. 6058 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 6059 * p tobj.source_ole_types 6060 * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>] 6061 */ 6062static VALUE 6063foletype_source_ole_types(VALUE self) 6064{ 6065 struct oletypedata *ptype; 6066 Data_Get_Struct(self, struct oletypedata, ptype); 6067 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE); 6068} 6069 6070/* 6071 * call-seq: 6072 * WIN32OLE_TYPE#default_event_sources 6073 * 6074 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 6075 * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. 6076 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 6077 * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>] 6078 */ 6079static VALUE 6080foletype_default_event_sources(VALUE self) 6081{ 6082 struct oletypedata *ptype; 6083 Data_Get_Struct(self, struct oletypedata, ptype); 6084 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT); 6085} 6086 6087/* 6088 * call-seq: 6089 * WIN32OLE_TYPE#default_ole_types 6090 * 6091 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 6092 * object and having IMPLTYPEFLAG_FDEFAULT. 6093 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 6094 * p tobj.default_ole_types 6095 * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>] 6096 */ 6097static VALUE 6098foletype_default_ole_types(VALUE self) 6099{ 6100 struct oletypedata *ptype; 6101 Data_Get_Struct(self, struct oletypedata, ptype); 6102 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT); 6103} 6104 6105/* 6106 * call-seq: 6107 * WIN32OLE_TYPE#inspect -> String 6108 * 6109 * Returns the type name with class name. 6110 * 6111 * ie = WIN32OLE.new('InternetExplorer.Application') 6112 * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2> 6113 */ 6114static VALUE 6115foletype_inspect(VALUE self) 6116{ 6117 return default_inspect(self, "WIN32OLE_TYPE"); 6118} 6119 6120static VALUE 6121ole_variables(ITypeInfo *pTypeInfo) 6122{ 6123 HRESULT hr; 6124 TYPEATTR *pTypeAttr; 6125 WORD i; 6126 UINT len; 6127 BSTR bstr; 6128 VARDESC *pVarDesc; 6129 struct olevariabledata *pvar; 6130 VALUE var; 6131 VALUE variables = rb_ary_new(); 6132 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 6133 if (FAILED(hr)) { 6134 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 6135 } 6136 6137 for(i = 0; i < pTypeAttr->cVars; i++) { 6138 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc); 6139 if(FAILED(hr)) 6140 continue; 6141 len = 0; 6142 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 6143 1, &len); 6144 if(FAILED(hr) || len == 0 || !bstr) 6145 continue; 6146 6147 var = Data_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata, 6148 0,olevariable_free,pvar); 6149 pvar->pTypeInfo = pTypeInfo; 6150 OLE_ADDREF(pTypeInfo); 6151 pvar->index = i; 6152 rb_ivar_set(var, rb_intern("name"), WC2VSTR(bstr)); 6153 rb_ary_push(variables, var); 6154 6155 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6156 pVarDesc = NULL; 6157 } 6158 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 6159 return variables; 6160} 6161 6162/* 6163 * call-seq: 6164 * WIN32OLE_TYPE#variables 6165 * 6166 * Returns array of WIN32OLE_VARIABLE objects which represent variables 6167 * defined in OLE class. 6168 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6169 * vars = tobj.variables 6170 * vars.each do |v| 6171 * puts "#{v.name} = #{v.value}" 6172 * end 6173 * 6174 * The result of above sample script is follows: 6175 * xlChart = -4109 6176 * xlDialogSheet = -4116 6177 * xlExcel4IntlMacroSheet = 4 6178 * xlExcel4MacroSheet = 3 6179 * xlWorksheet = -4167 6180 * 6181 */ 6182static VALUE 6183foletype_variables(VALUE self) 6184{ 6185 struct oletypedata *ptype; 6186 Data_Get_Struct(self, struct oletypedata, ptype); 6187 return ole_variables(ptype->pTypeInfo); 6188} 6189 6190/* 6191 * call-seq: 6192 * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects. 6193 * 6194 * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in 6195 * OLE type library. 6196 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 6197 * methods = tobj.ole_methods.collect{|m| 6198 * m.name 6199 * } 6200 * # => ['Activate', 'Copy', 'Delete',....] 6201 */ 6202static VALUE 6203foletype_methods(VALUE self) 6204{ 6205 struct oletypedata *ptype; 6206 Data_Get_Struct(self, struct oletypedata, ptype); 6207 return ole_methods_from_typeinfo(ptype->pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); 6208} 6209 6210/* 6211 * Document-class: WIN32OLE_VARIABLE 6212 * 6213 * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information. 6214 */ 6215 6216/* 6217 * call-seq: 6218 * WIN32OLE_VARIABLE#name 6219 * 6220 * Returns the name of variable. 6221 * 6222 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6223 * variables = tobj.variables 6224 * variables.each do |variable| 6225 * puts "#{variable.name}" 6226 * end 6227 * 6228 * The result of above script is following: 6229 * xlChart 6230 * xlDialogSheet 6231 * xlExcel4IntlMacroSheet 6232 * xlExcel4MacroSheet 6233 * xlWorksheet 6234 * 6235 */ 6236static VALUE 6237folevariable_name(VALUE self) 6238{ 6239 return rb_ivar_get(self, rb_intern("name")); 6240} 6241 6242static VALUE 6243ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index) 6244{ 6245 VARDESC *pVarDesc; 6246 HRESULT hr; 6247 VALUE type; 6248 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 6249 if (FAILED(hr)) 6250 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); 6251 type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil); 6252 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6253 return type; 6254} 6255 6256/* 6257 * call-seq: 6258 * WIN32OLE_VARIABLE#ole_type 6259 * 6260 * Returns OLE type string. 6261 * 6262 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6263 * variables = tobj.variables 6264 * variables.each do |variable| 6265 * puts "#{variable.ole_type} #{variable.name}" 6266 * end 6267 * 6268 * The result of above script is following: 6269 * INT xlChart 6270 * INT xlDialogSheet 6271 * INT xlExcel4IntlMacroSheet 6272 * INT xlExcel4MacroSheet 6273 * INT xlWorksheet 6274 * 6275 */ 6276static VALUE 6277folevariable_ole_type(VALUE self) 6278{ 6279 struct olevariabledata *pvar; 6280 Data_Get_Struct(self, struct olevariabledata, pvar); 6281 return ole_variable_ole_type(pvar->pTypeInfo, pvar->index); 6282} 6283 6284static VALUE 6285ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index) 6286{ 6287 VARDESC *pVarDesc; 6288 HRESULT hr; 6289 VALUE type = rb_ary_new(); 6290 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 6291 if (FAILED(hr)) 6292 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); 6293 ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type); 6294 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6295 return type; 6296} 6297 6298/* 6299 * call-seq: 6300 * WIN32OLE_VARIABLE#ole_type_detail 6301 * 6302 * Returns detail information of type. The information is array of type. 6303 * 6304 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS') 6305 * variable = tobj.variables.find {|variable| variable.name == 'lFlags'} 6306 * tdetail = variable.ole_type_detail 6307 * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"] 6308 * 6309 */ 6310static VALUE 6311folevariable_ole_type_detail(VALUE self) 6312{ 6313 struct olevariabledata *pvar; 6314 Data_Get_Struct(self, struct olevariabledata, pvar); 6315 return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index); 6316} 6317 6318static VALUE 6319ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index) 6320{ 6321 VARDESC *pVarDesc; 6322 HRESULT hr; 6323 VALUE val = Qnil; 6324 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 6325 if (FAILED(hr)) 6326 return Qnil; 6327 if(pVarDesc->varkind == VAR_CONST) 6328 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); 6329 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6330 return val; 6331} 6332 6333/* 6334 * call-seq: 6335 * WIN32OLE_VARIABLE#value 6336 * 6337 * Returns value if value is exists. If the value does not exist, 6338 * this method returns nil. 6339 * 6340 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6341 * variables = tobj.variables 6342 * variables.each do |variable| 6343 * puts "#{variable.name} #{variable.value}" 6344 * end 6345 * 6346 * The result of above script is following: 6347 * xlChart = -4109 6348 * xlDialogSheet = -4116 6349 * xlExcel4IntlMacroSheet = 4 6350 * xlExcel4MacroSheet = 3 6351 * xlWorksheet = -4167 6352 * 6353 */ 6354static VALUE 6355folevariable_value(VALUE self) 6356{ 6357 struct olevariabledata *pvar; 6358 Data_Get_Struct(self, struct olevariabledata, pvar); 6359 return ole_variable_value(pvar->pTypeInfo, pvar->index); 6360} 6361 6362static VALUE 6363ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index) 6364{ 6365 VARDESC *pVarDesc; 6366 HRESULT hr; 6367 VALUE visible = Qfalse; 6368 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 6369 if (FAILED(hr)) 6370 return visible; 6371 if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | 6372 VARFLAG_FRESTRICTED | 6373 VARFLAG_FNONBROWSABLE))) { 6374 visible = Qtrue; 6375 } 6376 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6377 return visible; 6378} 6379 6380/* 6381 * call-seq: 6382 * WIN32OLE_VARIABLE#visible? 6383 * 6384 * Returns true if the variable is public. 6385 * 6386 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6387 * variables = tobj.variables 6388 * variables.each do |variable| 6389 * puts "#{variable.name} #{variable.visible?}" 6390 * end 6391 * 6392 * The result of above script is following: 6393 * xlChart true 6394 * xlDialogSheet true 6395 * xlExcel4IntlMacroSheet true 6396 * xlExcel4MacroSheet true 6397 * xlWorksheet true 6398 * 6399 */ 6400static VALUE 6401folevariable_visible(VALUE self) 6402{ 6403 struct olevariabledata *pvar; 6404 Data_Get_Struct(self, struct olevariabledata, pvar); 6405 return ole_variable_visible(pvar->pTypeInfo, pvar->index); 6406} 6407 6408static VALUE 6409ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index) 6410{ 6411 VARDESC *pVarDesc; 6412 HRESULT hr; 6413 VALUE kind = rb_str_new2("UNKNOWN"); 6414 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 6415 if (FAILED(hr)) 6416 return kind; 6417 switch(pVarDesc->varkind) { 6418 case VAR_PERINSTANCE: 6419 kind = rb_str_new2("PERINSTANCE"); 6420 break; 6421 case VAR_STATIC: 6422 kind = rb_str_new2("STATIC"); 6423 break; 6424 case VAR_CONST: 6425 kind = rb_str_new2("CONSTANT"); 6426 break; 6427 case VAR_DISPATCH: 6428 kind = rb_str_new2("DISPATCH"); 6429 break; 6430 default: 6431 break; 6432 } 6433 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6434 return kind; 6435} 6436 6437/* 6438 * call-seq: 6439 * WIN32OLE_VARIABLE#variable_kind 6440 * 6441 * Returns variable kind string. 6442 * 6443 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6444 * variables = tobj.variables 6445 * variables.each do |variable| 6446 * puts "#{variable.name} #{variable.variable_kind}" 6447 * end 6448 * 6449 * The result of above script is following: 6450 * xlChart CONSTANT 6451 * xlDialogSheet CONSTANT 6452 * xlExcel4IntlMacroSheet CONSTANT 6453 * xlExcel4MacroSheet CONSTANT 6454 * xlWorksheet CONSTANT 6455 */ 6456static VALUE 6457folevariable_variable_kind(VALUE self) 6458{ 6459 struct olevariabledata *pvar; 6460 Data_Get_Struct(self, struct olevariabledata, pvar); 6461 return ole_variable_kind(pvar->pTypeInfo, pvar->index); 6462} 6463 6464static VALUE 6465ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index) 6466{ 6467 VARDESC *pVarDesc; 6468 HRESULT hr; 6469 VALUE kind = Qnil; 6470 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 6471 if (FAILED(hr)) 6472 return kind; 6473 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 6474 kind = INT2FIX(pVarDesc->varkind); 6475 return kind; 6476} 6477 6478/* 6479 * call-seq: 6480 * WIN32OLE_VARIABLE#varkind 6481 * 6482 * Returns the number which represents variable kind. 6483 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 6484 * variables = tobj.variables 6485 * variables.each do |variable| 6486 * puts "#{variable.name} #{variable.varkind}" 6487 * end 6488 * 6489 * The result of above script is following: 6490 * xlChart 2 6491 * xlDialogSheet 2 6492 * xlExcel4IntlMacroSheet 2 6493 * xlExcel4MacroSheet 2 6494 * xlWorksheet 2 6495 */ 6496static VALUE 6497folevariable_varkind(VALUE self) 6498{ 6499 struct olevariabledata *pvar; 6500 Data_Get_Struct(self, struct olevariabledata, pvar); 6501 return ole_variable_varkind(pvar->pTypeInfo, pvar->index); 6502} 6503 6504/* 6505 * call-seq: 6506 * WIN32OLE_VARIABLE#inspect -> String 6507 * 6508 * Returns the OLE variable name and the value with class name. 6509 * 6510 */ 6511static VALUE 6512folevariable_inspect(VALUE self) 6513{ 6514 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0); 6515 rb_str_cat2(detail, "="); 6516 rb_str_concat(detail, rb_funcall(rb_funcall(self, rb_intern("value"), 0), rb_intern("inspect"), 0)); 6517 return make_inspect("WIN32OLE_VARIABLE", detail); 6518} 6519 6520/* 6521 * Document-class: WIN32OLE_METHOD 6522 * 6523 * <code>WIN32OLE_METHOD</code> objects represent OLE method information. 6524 */ 6525 6526static VALUE 6527olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name) 6528{ 6529 struct olemethoddata *pmethod; 6530 Data_Get_Struct(self, struct olemethoddata, pmethod); 6531 pmethod->pTypeInfo = pTypeInfo; 6532 OLE_ADDREF(pTypeInfo); 6533 pmethod->pOwnerTypeInfo = pOwnerTypeInfo; 6534 if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo); 6535 pmethod->index = index; 6536 rb_ivar_set(self, rb_intern("name"), name); 6537 return self; 6538} 6539 6540static VALUE 6541folemethod_s_allocate(VALUE klass) 6542{ 6543 struct olemethoddata *pmethod; 6544 VALUE obj; 6545 obj = Data_Make_Struct(klass, 6546 struct olemethoddata, 6547 0, olemethod_free, pmethod); 6548 pmethod->pTypeInfo = NULL; 6549 pmethod->pOwnerTypeInfo = NULL; 6550 pmethod->index = 0; 6551 return obj; 6552} 6553 6554/* 6555 * call-seq: 6556 * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object 6557 * 6558 * Returns a new WIN32OLE_METHOD object which represents the information 6559 * about OLE method. 6560 * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object. 6561 * The second argument <i>method</i> specifies OLE method name defined OLE class 6562 * which represents WIN32OLE_TYPE object. 6563 * 6564 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 6565 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 6566 */ 6567static VALUE 6568folemethod_initialize(VALUE self, VALUE oletype, VALUE method) 6569{ 6570 struct oletypedata *ptype; 6571 VALUE obj = Qnil; 6572 if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) { 6573 SafeStringValue(method); 6574 Data_Get_Struct(oletype, struct oletypedata, ptype); 6575 obj = olemethod_from_typeinfo(self, ptype->pTypeInfo, method); 6576 if (obj == Qnil) { 6577 rb_raise(eWIN32OLERuntimeError, "not found %s", 6578 StringValuePtr(method)); 6579 } 6580 } 6581 else { 6582 rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); 6583 } 6584 return obj; 6585} 6586 6587/* 6588 * call-seq 6589 * WIN32OLE_METHOD#name 6590 * 6591 * Returns the name of the method. 6592 * 6593 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 6594 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 6595 * puts method.name # => SaveAs 6596 * 6597 */ 6598static VALUE 6599folemethod_name(VALUE self) 6600{ 6601 return rb_ivar_get(self, rb_intern("name")); 6602} 6603 6604static VALUE 6605ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) 6606{ 6607 FUNCDESC *pFuncDesc; 6608 HRESULT hr; 6609 VALUE type; 6610 6611 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 6612 if (FAILED(hr)) 6613 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 6614 6615 type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil); 6616 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 6617 return type; 6618} 6619 6620/* 6621 * call-seq: 6622 * WIN32OLE_METHOD#return_type 6623 * 6624 * Returns string of return value type of method. 6625 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6626 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6627 * puts method.return_type # => Workbook 6628 * 6629 */ 6630static VALUE 6631folemethod_return_type(VALUE self) 6632{ 6633 struct olemethoddata *pmethod; 6634 Data_Get_Struct(self, struct olemethoddata, pmethod); 6635 return ole_method_return_type(pmethod->pTypeInfo, pmethod->index); 6636} 6637 6638static VALUE 6639ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) 6640{ 6641 FUNCDESC *pFuncDesc; 6642 HRESULT hr; 6643 VALUE vvt; 6644 6645 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 6646 if (FAILED(hr)) 6647 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 6648 6649 vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt); 6650 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 6651 return vvt; 6652} 6653 6654/* 6655 * call-seq: 6656 * WIN32OLE_METHOD#return_vtype 6657 * 6658 * Returns number of return value type of method. 6659 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6660 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6661 * puts method.return_vtype # => 26 6662 * 6663 */ 6664static VALUE 6665folemethod_return_vtype(VALUE self) 6666{ 6667 struct olemethoddata *pmethod; 6668 Data_Get_Struct(self, struct olemethoddata, pmethod); 6669 return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index); 6670} 6671 6672static VALUE 6673ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) 6674{ 6675 FUNCDESC *pFuncDesc; 6676 HRESULT hr; 6677 VALUE type = rb_ary_new(); 6678 6679 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 6680 if (FAILED(hr)) 6681 return type; 6682 6683 ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type); 6684 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 6685 return type; 6686} 6687 6688/* 6689 * call-seq: 6690 * WIN32OLE_METHOD#return_type_detail 6691 * 6692 * Returns detail information of return value type of method. 6693 * The information is array. 6694 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6695 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6696 * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] 6697 */ 6698static VALUE 6699folemethod_return_type_detail(VALUE self) 6700{ 6701 struct olemethoddata *pmethod; 6702 Data_Get_Struct(self, struct olemethoddata, pmethod); 6703 return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index); 6704} 6705 6706static VALUE 6707ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index) 6708{ 6709 FUNCDESC *pFuncDesc; 6710 HRESULT hr; 6711 VALUE invkind; 6712 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 6713 if(FAILED(hr)) 6714 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 6715 invkind = INT2FIX(pFuncDesc->invkind); 6716 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 6717 return invkind; 6718} 6719 6720static VALUE 6721ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) 6722{ 6723 VALUE type = rb_str_new2("UNKNOWN"); 6724 VALUE invkind = ole_method_invkind(pTypeInfo, method_index); 6725 if((FIX2INT(invkind) & INVOKE_PROPERTYGET) && 6726 (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) { 6727 type = rb_str_new2("PROPERTY"); 6728 } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) { 6729 type = rb_str_new2("PROPERTYGET"); 6730 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) { 6731 type = rb_str_new2("PROPERTYPUT"); 6732 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) { 6733 type = rb_str_new2("PROPERTYPUTREF"); 6734 } else if(FIX2INT(invkind) & INVOKE_FUNC) { 6735 type = rb_str_new2("FUNC"); 6736 } 6737 return type; 6738} 6739 6740/* 6741 * call-seq: 6742 * WIN32OLE_MTHOD#invkind 6743 * 6744 * Returns the method invoke kind. 6745 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6746 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6747 * puts method.invkind # => 1 6748 * 6749 */ 6750static VALUE 6751folemethod_invkind(VALUE self) 6752{ 6753 struct olemethoddata *pmethod; 6754 Data_Get_Struct(self, struct olemethoddata, pmethod); 6755 return ole_method_invkind(pmethod->pTypeInfo, pmethod->index); 6756} 6757 6758/* 6759 * call-seq: 6760 * WIN32OLE_METHOD#invoke_kind 6761 * 6762 * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" 6763 * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" 6764 * or "FUNC". 6765 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6766 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6767 * puts method.invoke_kind # => "FUNC" 6768 */ 6769static VALUE 6770folemethod_invoke_kind(VALUE self) 6771{ 6772 struct olemethoddata *pmethod; 6773 Data_Get_Struct(self, struct olemethoddata, pmethod); 6774 return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index); 6775} 6776 6777static VALUE 6778ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) 6779{ 6780 FUNCDESC *pFuncDesc; 6781 HRESULT hr; 6782 VALUE visible; 6783 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 6784 if(FAILED(hr)) 6785 return Qfalse; 6786 if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED | 6787 FUNCFLAG_FHIDDEN | 6788 FUNCFLAG_FNONBROWSABLE)) { 6789 visible = Qfalse; 6790 } else { 6791 visible = Qtrue; 6792 } 6793 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 6794 return visible; 6795} 6796 6797/* 6798 * call-seq: 6799 * WIN32OLE_METHOD#visible? 6800 * 6801 * Returns true if the method is public. 6802 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6803 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6804 * puts method.visible? # => true 6805 */ 6806static VALUE 6807folemethod_visible(VALUE self) 6808{ 6809 struct olemethoddata *pmethod; 6810 Data_Get_Struct(self, struct olemethoddata, pmethod); 6811 return ole_method_visible(pmethod->pTypeInfo, pmethod->index); 6812} 6813 6814static VALUE 6815ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) 6816{ 6817 TYPEATTR *pTypeAttr; 6818 HRESULT hr; 6819 WORD i; 6820 int flags; 6821 HREFTYPE href; 6822 ITypeInfo *pRefTypeInfo; 6823 FUNCDESC *pFuncDesc; 6824 BSTR bstr; 6825 VALUE name; 6826 VALUE event = Qfalse; 6827 6828 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 6829 if (FAILED(hr)) 6830 return event; 6831 if(pTypeAttr->typekind != TKIND_COCLASS) { 6832 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); 6833 return event; 6834 } 6835 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 6836 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 6837 if (FAILED(hr)) 6838 continue; 6839 6840 if (flags & IMPLTYPEFLAG_FSOURCE) { 6841 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 6842 i, &href); 6843 if (FAILED(hr)) 6844 continue; 6845 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 6846 href, &pRefTypeInfo); 6847 if (FAILED(hr)) 6848 continue; 6849 hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index, 6850 &pFuncDesc); 6851 if (FAILED(hr)) { 6852 OLE_RELEASE(pRefTypeInfo); 6853 continue; 6854 } 6855 6856 hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo, 6857 pFuncDesc->memid, 6858 &bstr, NULL, NULL, NULL); 6859 if (FAILED(hr)) { 6860 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); 6861 OLE_RELEASE(pRefTypeInfo); 6862 continue; 6863 } 6864 6865 name = WC2VSTR(bstr); 6866 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); 6867 OLE_RELEASE(pRefTypeInfo); 6868 if (rb_str_cmp(method_name, name) == 0) { 6869 event = Qtrue; 6870 break; 6871 } 6872 } 6873 } 6874 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 6875 return event; 6876} 6877 6878/* 6879 * call-seq: 6880 * WIN32OLE_METHOD#event? 6881 * 6882 * Returns true if the method is event. 6883 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 6884 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') 6885 * puts method.event? # => true 6886 * 6887 */ 6888static VALUE 6889folemethod_event(VALUE self) 6890{ 6891 struct olemethoddata *pmethod; 6892 Data_Get_Struct(self, struct olemethoddata, pmethod); 6893 if (!pmethod->pOwnerTypeInfo) 6894 return Qfalse; 6895 return ole_method_event(pmethod->pOwnerTypeInfo, 6896 pmethod->index, 6897 rb_ivar_get(self, rb_intern("name"))); 6898} 6899 6900/* 6901 * call-seq: 6902 * WIN32OLE_METHOD#event_interface 6903 * 6904 * Returns event interface name if the method is event. 6905 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 6906 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') 6907 * puts method.event_interface # => WorkbookEvents 6908 */ 6909static VALUE 6910folemethod_event_interface(VALUE self) 6911{ 6912 BSTR name; 6913 struct olemethoddata *pmethod; 6914 HRESULT hr; 6915 Data_Get_Struct(self, struct olemethoddata, pmethod); 6916 if(folemethod_event(self) == Qtrue) { 6917 hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL); 6918 if(SUCCEEDED(hr)) 6919 return WC2VSTR(name); 6920 } 6921 return Qnil; 6922} 6923 6924static VALUE 6925ole_method_docinfo_from_type( 6926 ITypeInfo *pTypeInfo, 6927 UINT method_index, 6928 BSTR *name, 6929 BSTR *helpstr, 6930 DWORD *helpcontext, 6931 BSTR *helpfile 6932 ) 6933{ 6934 FUNCDESC *pFuncDesc; 6935 HRESULT hr; 6936 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 6937 if (FAILED(hr)) 6938 return hr; 6939 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 6940 name, helpstr, 6941 helpcontext, helpfile); 6942 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 6943 return hr; 6944} 6945 6946static VALUE 6947ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) 6948{ 6949 HRESULT hr; 6950 BSTR bhelpstring; 6951 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring, 6952 NULL, NULL); 6953 if (FAILED(hr)) 6954 return Qnil; 6955 return WC2VSTR(bhelpstring); 6956} 6957 6958/* 6959 * call-seq: 6960 * WIN32OLE_METHOD#helpstring 6961 * 6962 * Returns help string of OLE method. If the help string is not found, 6963 * then the method returns nil. 6964 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') 6965 * method = WIN32OLE_METHOD.new(tobj, 'Navigate') 6966 * puts method.helpstring # => Navigates to a URL or file. 6967 * 6968 */ 6969static VALUE 6970folemethod_helpstring(VALUE self) 6971{ 6972 struct olemethoddata *pmethod; 6973 Data_Get_Struct(self, struct olemethoddata, pmethod); 6974 return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index); 6975} 6976 6977static VALUE 6978ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index) 6979{ 6980 HRESULT hr; 6981 BSTR bhelpfile; 6982 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, 6983 NULL, &bhelpfile); 6984 if (FAILED(hr)) 6985 return Qnil; 6986 return WC2VSTR(bhelpfile); 6987} 6988 6989/* 6990 * call-seq: 6991 * WIN32OLE_METHOD#helpfile 6992 * 6993 * Returns help file. If help file is not found, then 6994 * the method returns nil. 6995 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 6996 * method = WIN32OLE_METHOD.new(tobj, 'Add') 6997 * puts method.helpfile # => C:\...\VBAXL9.CHM 6998 */ 6999static VALUE 7000folemethod_helpfile(VALUE self) 7001{ 7002 struct olemethoddata *pmethod; 7003 Data_Get_Struct(self, struct olemethoddata, pmethod); 7004 7005 return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index); 7006} 7007 7008static VALUE 7009ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) 7010{ 7011 HRESULT hr; 7012 DWORD helpcontext = 0; 7013 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, 7014 &helpcontext, NULL); 7015 if (FAILED(hr)) 7016 return Qnil; 7017 return INT2FIX(helpcontext); 7018} 7019 7020/* 7021 * call-seq: 7022 * WIN32OLE_METHOD#helpcontext 7023 * 7024 * Returns help context. 7025 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 7026 * method = WIN32OLE_METHOD.new(tobj, 'Add') 7027 * puts method.helpcontext # => 65717 7028 */ 7029static VALUE 7030folemethod_helpcontext(VALUE self) 7031{ 7032 struct olemethoddata *pmethod; 7033 Data_Get_Struct(self, struct olemethoddata, pmethod); 7034 return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index); 7035} 7036 7037static VALUE 7038ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) 7039{ 7040 FUNCDESC *pFuncDesc; 7041 HRESULT hr; 7042 VALUE dispid = Qnil; 7043 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7044 if (FAILED(hr)) 7045 return dispid; 7046 dispid = INT2NUM(pFuncDesc->memid); 7047 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7048 return dispid; 7049} 7050 7051/* 7052 * call-seq: 7053 * WIN32OLE_METHOD#dispid 7054 * 7055 * Returns dispatch ID. 7056 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 7057 * method = WIN32OLE_METHOD.new(tobj, 'Add') 7058 * puts method.dispid # => 181 7059 */ 7060static VALUE 7061folemethod_dispid(VALUE self) 7062{ 7063 struct olemethoddata *pmethod; 7064 Data_Get_Struct(self, struct olemethoddata, pmethod); 7065 return ole_method_dispid(pmethod->pTypeInfo, pmethod->index); 7066} 7067 7068static VALUE 7069ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) 7070{ 7071 FUNCDESC *pFuncDesc; 7072 HRESULT hr; 7073 VALUE offset_vtbl = Qnil; 7074 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7075 if (FAILED(hr)) 7076 return offset_vtbl; 7077 offset_vtbl = INT2FIX(pFuncDesc->oVft); 7078 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7079 return offset_vtbl; 7080} 7081 7082/* 7083 * call-seq: 7084 * WIN32OLE_METHOD#offset_vtbl 7085 * 7086 * Returns the offset ov VTBL. 7087 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 7088 * method = WIN32OLE_METHOD.new(tobj, 'Add') 7089 * puts method.offset_vtbl # => 40 7090 */ 7091static VALUE 7092folemethod_offset_vtbl(VALUE self) 7093{ 7094 struct olemethoddata *pmethod; 7095 Data_Get_Struct(self, struct olemethoddata, pmethod); 7096 return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index); 7097} 7098 7099static VALUE 7100ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) 7101{ 7102 FUNCDESC *pFuncDesc; 7103 HRESULT hr; 7104 VALUE size_params = Qnil; 7105 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7106 if (FAILED(hr)) 7107 return size_params; 7108 size_params = INT2FIX(pFuncDesc->cParams); 7109 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7110 return size_params; 7111} 7112 7113/* 7114 * call-seq: 7115 * WIN32OLE_METHOD#size_params 7116 * 7117 * Returns the size of arguments of the method. 7118 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7119 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7120 * puts method.size_params # => 11 7121 * 7122 */ 7123static VALUE 7124folemethod_size_params(VALUE self) 7125{ 7126 struct olemethoddata *pmethod; 7127 Data_Get_Struct(self, struct olemethoddata, pmethod); 7128 return ole_method_size_params(pmethod->pTypeInfo, pmethod->index); 7129} 7130 7131static VALUE 7132ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) 7133{ 7134 FUNCDESC *pFuncDesc; 7135 HRESULT hr; 7136 VALUE size_opt_params = Qnil; 7137 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7138 if (FAILED(hr)) 7139 return size_opt_params; 7140 size_opt_params = INT2FIX(pFuncDesc->cParamsOpt); 7141 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7142 return size_opt_params; 7143} 7144 7145/* 7146 * call-seq: 7147 * WIN32OLE_METHOD#size_opt_params 7148 * 7149 * Returns the size of optional parameters. 7150 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7151 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7152 * puts method.size_opt_params # => 4 7153 */ 7154static VALUE 7155folemethod_size_opt_params(VALUE self) 7156{ 7157 struct olemethoddata *pmethod; 7158 Data_Get_Struct(self, struct olemethoddata, pmethod); 7159 return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index); 7160} 7161 7162static VALUE 7163ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) 7164{ 7165 FUNCDESC *pFuncDesc; 7166 HRESULT hr; 7167 BSTR *bstrs; 7168 UINT len, i; 7169 struct oleparamdata *pparam; 7170 VALUE param; 7171 VALUE params = rb_ary_new(); 7172 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7173 if (FAILED(hr)) 7174 return params; 7175 7176 len = 0; 7177 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); 7178 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, 7179 bstrs, pFuncDesc->cParams + 1, 7180 &len); 7181 if (FAILED(hr)) { 7182 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7183 return params; 7184 } 7185 SysFreeString(bstrs[0]); 7186 if (pFuncDesc->cParams > 0) { 7187 for(i = 1; i < len; i++) { 7188 param = Data_Make_Struct(cWIN32OLE_PARAM, struct oleparamdata, 0, 7189 oleparam_free, pparam); 7190 pparam->pTypeInfo = pTypeInfo; 7191 OLE_ADDREF(pTypeInfo); 7192 pparam->method_index = method_index; 7193 pparam->index = i - 1; 7194 rb_ivar_set(param, rb_intern("name"), WC2VSTR(bstrs[i])); 7195 rb_ary_push(params, param); 7196 } 7197 } 7198 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7199 return params; 7200} 7201 7202 7203/* 7204 * call-seq: 7205 * WIN32OLE_METHOD#params 7206 * 7207 * returns array of WIN32OLE_PARAM object corresponding with method parameters. 7208 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7209 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7210 * p method.params # => [Filename, FileFormat, Password, WriteResPassword, 7211 * ReadOnlyRecommended, CreateBackup, AccessMode, 7212 * ConflictResolution, AddToMru, TextCodepage, 7213 * TextVisualLayout] 7214 */ 7215static VALUE 7216folemethod_params(VALUE self) 7217{ 7218 struct olemethoddata *pmethod; 7219 Data_Get_Struct(self, struct olemethoddata, pmethod); 7220 return ole_method_params(pmethod->pTypeInfo, pmethod->index); 7221} 7222 7223/* 7224 * call-seq: 7225 * WIN32OLE_METHOD#inspect -> String 7226 * 7227 * Returns the method name with class name. 7228 * 7229 */ 7230static VALUE 7231folemethod_inspect(VALUE self) 7232{ 7233 return default_inspect(self, "WIN32OLE_METHOD"); 7234} 7235 7236/* 7237 * Document-class: WIN32OLE_PARAM 7238 * 7239 * <code>WIN32OLE_PARAM</code> objects represent param information of 7240 * the OLE method. 7241 */ 7242static VALUE foleparam_s_allocate(VALUE klass) 7243{ 7244 struct oleparamdata *pparam; 7245 VALUE obj; 7246 obj = Data_Make_Struct(klass, 7247 struct oleparamdata, 7248 0, oleparam_free, pparam); 7249 pparam->pTypeInfo = NULL; 7250 pparam->method_index = 0; 7251 pparam->index = 0; 7252 return obj; 7253} 7254 7255static VALUE 7256oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index) 7257{ 7258 FUNCDESC *pFuncDesc; 7259 HRESULT hr; 7260 BSTR *bstrs; 7261 UINT len; 7262 struct oleparamdata *pparam; 7263 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7264 if (FAILED(hr)) 7265 ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc"); 7266 7267 len = 0; 7268 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); 7269 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, 7270 bstrs, pFuncDesc->cParams + 1, 7271 &len); 7272 if (FAILED(hr)) { 7273 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7274 ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames"); 7275 } 7276 SysFreeString(bstrs[0]); 7277 if (param_index < 1 || len <= (UINT)param_index) 7278 { 7279 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7280 rb_raise(rb_eIndexError, "index of param must be in 1..%d", len); 7281 } 7282 7283 Data_Get_Struct(self, struct oleparamdata, pparam); 7284 pparam->pTypeInfo = pTypeInfo; 7285 OLE_ADDREF(pTypeInfo); 7286 pparam->method_index = method_index; 7287 pparam->index = param_index - 1; 7288 rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index])); 7289 7290 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7291 return self; 7292} 7293 7294static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n) 7295{ 7296 struct olemethoddata *pmethod; 7297 Data_Get_Struct(olemethod, struct olemethoddata, pmethod); 7298 return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n); 7299} 7300 7301static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n) 7302{ 7303 int idx; 7304 if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) { 7305 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object"); 7306 } 7307 idx = FIX2INT(n); 7308 return oleparam_ole_param(self, olemethod, idx); 7309} 7310 7311/* 7312 * call-seq: 7313 * WIN32OLE_PARAM#name 7314 * 7315 * Returns name. 7316 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7317 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7318 * param1 = method.params[0] 7319 * puts param1.name # => Filename 7320 */ 7321static VALUE 7322foleparam_name(VALUE self) 7323{ 7324 return rb_ivar_get(self, rb_intern("name")); 7325} 7326 7327static VALUE 7328ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 7329{ 7330 FUNCDESC *pFuncDesc; 7331 HRESULT hr; 7332 VALUE type = rb_str_new2("unknown type"); 7333 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7334 if (FAILED(hr)) 7335 return type; 7336 type = ole_typedesc2val(pTypeInfo, 7337 &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil); 7338 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7339 return type; 7340} 7341 7342/* 7343 * call-seq: 7344 * WIN32OLE_PARAM#ole_type 7345 * 7346 * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method). 7347 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7348 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7349 * param1 = method.params[0] 7350 * puts param1.ole_type # => VARIANT 7351 */ 7352static VALUE 7353foleparam_ole_type(VALUE self) 7354{ 7355 struct oleparamdata *pparam; 7356 Data_Get_Struct(self, struct oleparamdata, pparam); 7357 return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index, 7358 pparam->index); 7359} 7360 7361static VALUE 7362ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 7363{ 7364 FUNCDESC *pFuncDesc; 7365 HRESULT hr; 7366 VALUE typedetail = rb_ary_new(); 7367 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7368 if (FAILED(hr)) 7369 return typedetail; 7370 ole_typedesc2val(pTypeInfo, 7371 &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail); 7372 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7373 return typedetail; 7374} 7375 7376/* 7377 * call-seq: 7378 * WIN32OLE_PARAM#ole_type_detail 7379 * 7380 * Returns detail information of type of argument. 7381 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction') 7382 * method = WIN32OLE_METHOD.new(tobj, 'SumIf') 7383 * param1 = method.params[0] 7384 * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"] 7385 */ 7386static VALUE 7387foleparam_ole_type_detail(VALUE self) 7388{ 7389 struct oleparamdata *pparam; 7390 Data_Get_Struct(self, struct oleparamdata, pparam); 7391 return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index, 7392 pparam->index); 7393} 7394 7395static VALUE 7396ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask) 7397{ 7398 FUNCDESC *pFuncDesc; 7399 HRESULT hr; 7400 VALUE ret = Qfalse; 7401 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7402 if(FAILED(hr)) 7403 return ret; 7404 if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask) 7405 ret = Qtrue; 7406 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7407 return ret; 7408} 7409 7410/* 7411 * call-seq: 7412 * WIN32OLE_PARAM#input? 7413 * 7414 * Returns true if the parameter is input. 7415 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7416 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7417 * param1 = method.params[0] 7418 * puts param1.input? # => true 7419 */ 7420static VALUE foleparam_input(VALUE self) 7421{ 7422 struct oleparamdata *pparam; 7423 Data_Get_Struct(self, struct oleparamdata, pparam); 7424 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 7425 pparam->index, PARAMFLAG_FIN); 7426} 7427 7428/* 7429 * call-seq: 7430 * WIN32OLE#output? 7431 * 7432 * Returns true if argument is output. 7433 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents') 7434 * method = WIN32OLE_METHOD.new(tobj, 'NewWindow') 7435 * method.params.each do |param| 7436 * puts "#{param.name} #{param.output?}" 7437 * end 7438 * 7439 * The result of above script is following: 7440 * URL false 7441 * Flags false 7442 * TargetFrameName false 7443 * PostData false 7444 * Headers false 7445 * Processed true 7446 */ 7447static VALUE foleparam_output(VALUE self) 7448{ 7449 struct oleparamdata *pparam; 7450 Data_Get_Struct(self, struct oleparamdata, pparam); 7451 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 7452 pparam->index, PARAMFLAG_FOUT); 7453} 7454 7455/* 7456 * call-seq: 7457 * WIN32OLE_PARAM#optional? 7458 * 7459 * Returns true if argument is optional. 7460 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7461 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7462 * param1 = method.params[0] 7463 * puts "#{param1.name} #{param1.optional?}" # => Filename true 7464 */ 7465static VALUE foleparam_optional(VALUE self) 7466{ 7467 struct oleparamdata *pparam; 7468 Data_Get_Struct(self, struct oleparamdata, pparam); 7469 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 7470 pparam->index, PARAMFLAG_FOPT); 7471} 7472 7473/* 7474 * call-seq: 7475 * WIN32OLE_PARAM#retval? 7476 * 7477 * Returns true if argument is return value. 7478 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 7479 * 'DirectPlayLobbyConnection') 7480 * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName') 7481 * param = method.params[0] 7482 * puts "#{param.name} #{param.retval?}" # => name true 7483 */ 7484static VALUE foleparam_retval(VALUE self) 7485{ 7486 struct oleparamdata *pparam; 7487 Data_Get_Struct(self, struct oleparamdata, pparam); 7488 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 7489 pparam->index, PARAMFLAG_FRETVAL); 7490} 7491 7492static VALUE 7493ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 7494{ 7495 FUNCDESC *pFuncDesc; 7496 ELEMDESC *pElemDesc; 7497 PARAMDESCEX * pParamDescEx; 7498 HRESULT hr; 7499 USHORT wParamFlags; 7500 USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT; 7501 VALUE defval = Qnil; 7502 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 7503 if (FAILED(hr)) 7504 return defval; 7505 pElemDesc = &pFuncDesc->lprgelemdescParam[index]; 7506 wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags; 7507 if ((wParamFlags & mask) == mask) { 7508 pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex; 7509 defval = ole_variant2val(&pParamDescEx->varDefaultValue); 7510 } 7511 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 7512 return defval; 7513} 7514 7515/* 7516 * call-seq: 7517 * WIN32OLE_PARAM#default 7518 * 7519 * Returns default value. If the default value does not exist, 7520 * this method returns nil. 7521 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 7522 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 7523 * method.params.each do |param| 7524 * if param.default 7525 * puts "#{param.name} (= #{param.default})" 7526 * else 7527 * puts "#{param}" 7528 * end 7529 * end 7530 * 7531 * The above script result is following: 7532 * Filename 7533 * FileFormat 7534 * Password 7535 * WriteResPassword 7536 * ReadOnlyRecommended 7537 * CreateBackup 7538 * AccessMode (= 1) 7539 * ConflictResolution 7540 * AddToMru 7541 * TextCodepage 7542 * TextVisualLayout 7543 */ 7544static VALUE foleparam_default(VALUE self) 7545{ 7546 struct oleparamdata *pparam; 7547 Data_Get_Struct(self, struct oleparamdata, pparam); 7548 return ole_param_default(pparam->pTypeInfo, pparam->method_index, 7549 pparam->index); 7550} 7551 7552/* 7553 * call-seq: 7554 * WIN32OLE_PARAM#inspect -> String 7555 * 7556 * Returns the parameter name with class name. If the parameter has default value, 7557 * then returns name=value string with class name. 7558 * 7559 */ 7560static VALUE 7561foleparam_inspect(VALUE self) 7562{ 7563 VALUE detail = foleparam_name(self); 7564 VALUE defval = foleparam_default(self); 7565 if (defval != Qnil) { 7566 rb_str_cat2(detail, "="); 7567 rb_str_concat(detail, rb_funcall(defval, rb_intern("inspect"), 0)); 7568 } 7569 return make_inspect("WIN32OLE_PARAM", detail); 7570} 7571 7572/* 7573 * Document-class: WIN32OLE_EVENT 7574 * 7575 * <code>WIN32OLE_EVENT</code> objects controls OLE event. 7576 */ 7577 7578static IEventSinkVtbl vtEventSink; 7579static BOOL g_IsEventSinkVtblInitialized = FALSE; 7580 7581void EVENTSINK_Destructor(PIEVENTSINKOBJ); 7582 7583STDMETHODIMP 7584EVENTSINK_QueryInterface( 7585 PEVENTSINK pEV, 7586 REFIID iid, 7587 LPVOID* ppv 7588 ) { 7589 if (IsEqualIID(iid, &IID_IUnknown) || 7590 IsEqualIID(iid, &IID_IDispatch) || 7591 IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) { 7592 *ppv = pEV; 7593 } 7594 else { 7595 *ppv = NULL; 7596 return E_NOINTERFACE; 7597 } 7598 ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv); 7599 return NOERROR; 7600} 7601 7602STDMETHODIMP_(ULONG) 7603EVENTSINK_AddRef( 7604 PEVENTSINK pEV 7605 ){ 7606 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; 7607 return ++pEVObj->m_cRef; 7608} 7609 7610STDMETHODIMP_(ULONG) EVENTSINK_Release( 7611 PEVENTSINK pEV 7612 ) { 7613 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; 7614 --pEVObj->m_cRef; 7615 if(pEVObj->m_cRef != 0) 7616 return pEVObj->m_cRef; 7617 EVENTSINK_Destructor(pEVObj); 7618 return 0; 7619} 7620 7621STDMETHODIMP EVENTSINK_GetTypeInfoCount( 7622 PEVENTSINK pEV, 7623 UINT *pct 7624 ) { 7625 *pct = 0; 7626 return NOERROR; 7627} 7628 7629STDMETHODIMP EVENTSINK_GetTypeInfo( 7630 PEVENTSINK pEV, 7631 UINT info, 7632 LCID lcid, 7633 ITypeInfo **pInfo 7634 ) { 7635 *pInfo = NULL; 7636 return DISP_E_BADINDEX; 7637} 7638 7639STDMETHODIMP EVENTSINK_GetIDsOfNames( 7640 PEVENTSINK pEventSink, 7641 REFIID riid, 7642 OLECHAR **szNames, 7643 UINT cNames, 7644 LCID lcid, 7645 DISPID *pDispID 7646 ) { 7647 ITypeInfo *pTypeInfo; 7648 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; 7649 pTypeInfo = pEV->pTypeInfo; 7650 if (pTypeInfo) { 7651 return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID); 7652 } 7653 return DISP_E_UNKNOWNNAME; 7654} 7655 7656static long 7657ole_search_event_at(VALUE ary, VALUE ev) 7658{ 7659 VALUE event; 7660 VALUE event_name; 7661 long i, len; 7662 long ret = -1; 7663 len = RARRAY_LEN(ary); 7664 for(i = 0; i < len; i++) { 7665 event = rb_ary_entry(ary, i); 7666 event_name = rb_ary_entry(event, 1); 7667 if(NIL_P(event_name) && NIL_P(ev)) { 7668 ret = i; 7669 break; 7670 } 7671 else if (TYPE(ev) == T_STRING && 7672 TYPE(event_name) == T_STRING && 7673 rb_str_cmp(ev, event_name) == 0) { 7674 ret = i; 7675 break; 7676 } 7677 } 7678 return ret; 7679} 7680 7681static VALUE 7682ole_search_event(VALUE ary, VALUE ev, BOOL *is_default) 7683{ 7684 VALUE event; 7685 VALUE def_event; 7686 VALUE event_name; 7687 int i, len; 7688 *is_default = FALSE; 7689 def_event = Qnil; 7690 len = RARRAY_LEN(ary); 7691 for(i = 0; i < len; i++) { 7692 event = rb_ary_entry(ary, i); 7693 event_name = rb_ary_entry(event, 1); 7694 if(NIL_P(event_name)) { 7695 *is_default = TRUE; 7696 def_event = event; 7697 } 7698 else if (rb_str_cmp(ev, event_name) == 0) { 7699 *is_default = FALSE; 7700 return event; 7701 } 7702 } 7703 return def_event; 7704} 7705static VALUE 7706ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler) 7707{ 7708 VALUE mid; 7709 7710 *is_default_handler = FALSE; 7711 mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev))); 7712 if (rb_respond_to(handler, mid)) { 7713 return mid; 7714 } 7715 mid = rb_intern("method_missing"); 7716 if (rb_respond_to(handler, mid)) { 7717 *is_default_handler = TRUE; 7718 return mid; 7719 } 7720 return Qnil; 7721} 7722 7723static void 7724ole_delete_event(VALUE ary, VALUE ev) 7725{ 7726 long at = -1; 7727 at = ole_search_event_at(ary, ev); 7728 if (at >= 0) { 7729 rb_ary_delete_at(ary, at); 7730 } 7731} 7732 7733static void 7734hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams) 7735{ 7736 BSTR *bstrs; 7737 HRESULT hr; 7738 UINT len, i; 7739 VARIANT *pvar; 7740 VALUE val; 7741 VALUE key; 7742 len = 0; 7743 bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1); 7744 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 7745 bstrs, pdispparams->cArgs + 1, 7746 &len); 7747 if (FAILED(hr)) 7748 return; 7749 7750 for (i = 0; i < len - 1; i++) { 7751 key = WC2VSTR(bstrs[i + 1]); 7752 val = rb_hash_aref(hash, INT2FIX(i)); 7753 if (val == Qnil) 7754 val = rb_hash_aref(hash, key); 7755 if (val == Qnil) 7756 val = rb_hash_aref(hash, rb_str_intern(key)); 7757 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 7758 ole_val2ptr_variant(val, pvar); 7759 } 7760} 7761 7762static VALUE 7763hash2result(VALUE hash) 7764{ 7765 VALUE ret = Qnil; 7766 ret = rb_hash_aref(hash, rb_str_new2("return")); 7767 if (ret == Qnil) 7768 ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return"))); 7769 return ret; 7770} 7771 7772static void 7773ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams) 7774{ 7775 int i; 7776 VALUE v; 7777 VARIANT *pvar; 7778 for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) { 7779 v = rb_ary_entry(ary, i); 7780 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 7781 ole_val2ptr_variant(v, pvar); 7782 } 7783} 7784 7785static VALUE 7786exec_callback(VALUE arg) 7787{ 7788 VALUE *parg = (VALUE *)arg; 7789 VALUE handler = parg[0]; 7790 VALUE mid = parg[1]; 7791 VALUE args = parg[2]; 7792 return rb_apply(handler, mid, args); 7793} 7794 7795static VALUE 7796rescue_callback(VALUE arg) 7797{ 7798 7799 VALUE error; 7800 VALUE e = rb_errinfo(); 7801 VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0); 7802 VALUE msg = rb_funcall(e, rb_intern("message"), 0); 7803 bt = rb_ary_entry(bt, 0); 7804 error = rb_sprintf("%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e)); 7805 rb_write_error(StringValuePtr(error)); 7806 rb_backtrace(); 7807 ruby_finalize(); 7808 exit(-1); 7809 7810 return Qnil; 7811} 7812 7813STDMETHODIMP EVENTSINK_Invoke( 7814 PEVENTSINK pEventSink, 7815 DISPID dispid, 7816 REFIID riid, 7817 LCID lcid, 7818 WORD wFlags, 7819 DISPPARAMS *pdispparams, 7820 VARIANT *pvarResult, 7821 EXCEPINFO *pexcepinfo, 7822 UINT *puArgErr 7823 ) { 7824 7825 HRESULT hr; 7826 BSTR bstr; 7827 unsigned int count; 7828 unsigned int i; 7829 ITypeInfo *pTypeInfo; 7830 VARIANT *pvar; 7831 VALUE ary, obj, event, args, outargv, ev, result; 7832 VALUE handler = Qnil; 7833 VALUE arg[3]; 7834 VALUE mid; 7835 VALUE is_outarg = Qfalse; 7836 BOOL is_default_handler = FALSE; 7837 int state; 7838 7839 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; 7840 pTypeInfo = pEV->pTypeInfo; 7841 obj = evs_entry(pEV->m_event_id); 7842 if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) { 7843 return NOERROR; 7844 } 7845 7846 ary = rb_ivar_get(obj, id_events); 7847 if (NIL_P(ary) || TYPE(ary) != T_ARRAY) { 7848 return NOERROR; 7849 } 7850 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 7851 &bstr, 1, &count); 7852 if (FAILED(hr)) { 7853 return NOERROR; 7854 } 7855 ev = WC2VSTR(bstr); 7856 event = ole_search_event(ary, ev, &is_default_handler); 7857 if (TYPE(event) == T_ARRAY) { 7858 handler = rb_ary_entry(event, 0); 7859 mid = rb_intern("call"); 7860 is_outarg = rb_ary_entry(event, 3); 7861 } else { 7862 handler = rb_ivar_get(obj, rb_intern("handler")); 7863 if (handler == Qnil) { 7864 return NOERROR; 7865 } 7866 mid = ole_search_handler_method(handler, ev, &is_default_handler); 7867 } 7868 if (handler == Qnil || mid == Qnil) { 7869 return NOERROR; 7870 } 7871 7872 args = rb_ary_new(); 7873 if (is_default_handler) { 7874 rb_ary_push(args, ev); 7875 } 7876 7877 /* make argument of event handler */ 7878 for (i = 0; i < pdispparams->cArgs; ++i) { 7879 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 7880 rb_ary_push(args, ole_variant2val(pvar)); 7881 } 7882 outargv = Qnil; 7883 if (is_outarg == Qtrue) { 7884 outargv = rb_ary_new(); 7885 rb_ary_push(args, outargv); 7886 } 7887 7888 /* 7889 * if exception raised in event callback, 7890 * then you receive cfp consistency error. 7891 * to avoid this error we use begin rescue end. 7892 * and the exception raised then error message print 7893 * and exit ruby process by Win32OLE itself. 7894 */ 7895 arg[0] = handler; 7896 arg[1] = mid; 7897 arg[2] = args; 7898 result = rb_protect(exec_callback, (VALUE)arg, &state); 7899 if (state != 0) { 7900 rescue_callback(Qnil); 7901 } 7902 if(TYPE(result) == T_HASH) { 7903 hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); 7904 result = hash2result(result); 7905 }else if (is_outarg == Qtrue && TYPE(outargv) == T_ARRAY) { 7906 ary2ptr_dispparams(outargv, pdispparams); 7907 } 7908 7909 if (pvarResult) { 7910 VariantInit(pvarResult); 7911 ole_val2variant(result, pvarResult); 7912 } 7913 7914 return NOERROR; 7915} 7916 7917PIEVENTSINKOBJ 7918EVENTSINK_Constructor() { 7919 PIEVENTSINKOBJ pEv; 7920 if (!g_IsEventSinkVtblInitialized) { 7921 vtEventSink.QueryInterface=EVENTSINK_QueryInterface; 7922 vtEventSink.AddRef = EVENTSINK_AddRef; 7923 vtEventSink.Release = EVENTSINK_Release; 7924 vtEventSink.Invoke = EVENTSINK_Invoke; 7925 vtEventSink.GetIDsOfNames = EVENTSINK_GetIDsOfNames; 7926 vtEventSink.GetTypeInfoCount = EVENTSINK_GetTypeInfoCount; 7927 vtEventSink.GetTypeInfo = EVENTSINK_GetTypeInfo; 7928 7929 g_IsEventSinkVtblInitialized = TRUE; 7930 } 7931 pEv = ALLOC_N(IEVENTSINKOBJ, 1); 7932 if(pEv == NULL) return NULL; 7933 pEv->lpVtbl = &vtEventSink; 7934 pEv->m_cRef = 0; 7935 pEv->m_event_id = 0; 7936 pEv->pTypeInfo = NULL; 7937 return pEv; 7938} 7939 7940void EVENTSINK_Destructor( 7941 PIEVENTSINKOBJ pEVObj 7942 ) { 7943 if(pEVObj != NULL) { 7944 OLE_RELEASE(pEVObj->pTypeInfo); 7945 free(pEVObj); 7946 pEVObj = NULL; 7947 } 7948} 7949 7950static HRESULT 7951find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) 7952{ 7953 HRESULT hr; 7954 IDispatch *pDispatch; 7955 ITypeInfo *pTypeInfo; 7956 ITypeLib *pTypeLib; 7957 TYPEATTR *pTypeAttr; 7958 HREFTYPE RefType; 7959 ITypeInfo *pImplTypeInfo; 7960 TYPEATTR *pImplTypeAttr; 7961 7962 struct oledata *pole; 7963 unsigned int index; 7964 unsigned int count; 7965 int type; 7966 BSTR bstr; 7967 char *pstr; 7968 7969 BOOL is_found = FALSE; 7970 LCID lcid = cWIN32OLE_lcid; 7971 7972 OLEData_Get_Struct(ole, pole); 7973 7974 pDispatch = pole->pDispatch; 7975 7976 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo); 7977 if (FAILED(hr)) 7978 return hr; 7979 7980 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, 7981 &pTypeLib, 7982 &index); 7983 OLE_RELEASE(pTypeInfo); 7984 if (FAILED(hr)) 7985 return hr; 7986 7987 if (!pitf) { 7988 hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, 7989 piid, 7990 ppTypeInfo); 7991 OLE_RELEASE(pTypeLib); 7992 return hr; 7993 } 7994 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 7995 for (index = 0; index < count; index++) { 7996 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, 7997 index, 7998 &pTypeInfo); 7999 if (FAILED(hr)) 8000 break; 8001 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 8002 8003 if(FAILED(hr)) { 8004 OLE_RELEASE(pTypeInfo); 8005 break; 8006 } 8007 if(pTypeAttr->typekind == TKIND_COCLASS) { 8008 for (type = 0; type < pTypeAttr->cImplTypes; type++) { 8009 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 8010 type, 8011 &RefType); 8012 if (FAILED(hr)) 8013 break; 8014 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 8015 RefType, 8016 &pImplTypeInfo); 8017 if (FAILED(hr)) 8018 break; 8019 8020 hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo, 8021 -1, 8022 &bstr, 8023 NULL, NULL, NULL); 8024 if (FAILED(hr)) { 8025 OLE_RELEASE(pImplTypeInfo); 8026 break; 8027 } 8028 pstr = ole_wc2mb(bstr); 8029 if (strcmp(pitf, pstr) == 0) { 8030 hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo, 8031 &pImplTypeAttr); 8032 if (SUCCEEDED(hr)) { 8033 is_found = TRUE; 8034 *piid = pImplTypeAttr->guid; 8035 if (ppTypeInfo) { 8036 *ppTypeInfo = pImplTypeInfo; 8037 (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo)); 8038 } 8039 pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo, 8040 pImplTypeAttr); 8041 } 8042 } 8043 free(pstr); 8044 OLE_RELEASE(pImplTypeInfo); 8045 if (is_found || FAILED(hr)) 8046 break; 8047 } 8048 } 8049 8050 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 8051 OLE_RELEASE(pTypeInfo); 8052 if (is_found || FAILED(hr)) 8053 break; 8054 } 8055 OLE_RELEASE(pTypeLib); 8056 if(!is_found) 8057 return E_NOINTERFACE; 8058 return hr; 8059} 8060 8061static HRESULT 8062find_coclass( 8063 ITypeInfo *pTypeInfo, 8064 TYPEATTR *pTypeAttr, 8065 ITypeInfo **pCOTypeInfo, 8066 TYPEATTR **pCOTypeAttr) 8067{ 8068 HRESULT hr = E_NOINTERFACE; 8069 ITypeLib *pTypeLib; 8070 int count; 8071 BOOL found = FALSE; 8072 ITypeInfo *pTypeInfo2; 8073 TYPEATTR *pTypeAttr2; 8074 int flags; 8075 int i,j; 8076 HREFTYPE href; 8077 ITypeInfo *pRefTypeInfo; 8078 TYPEATTR *pRefTypeAttr; 8079 8080 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); 8081 if (FAILED(hr)) { 8082 return hr; 8083 } 8084 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 8085 for (i = 0; i < count && !found; i++) { 8086 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2); 8087 if (FAILED(hr)) 8088 continue; 8089 hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2); 8090 if (FAILED(hr)) { 8091 OLE_RELEASE(pTypeInfo2); 8092 continue; 8093 } 8094 if (pTypeAttr2->typekind != TKIND_COCLASS) { 8095 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 8096 OLE_RELEASE(pTypeInfo2); 8097 continue; 8098 } 8099 for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) { 8100 hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags); 8101 if (FAILED(hr)) 8102 continue; 8103 if (!(flags & IMPLTYPEFLAG_FDEFAULT)) 8104 continue; 8105 hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href); 8106 if (FAILED(hr)) 8107 continue; 8108 hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo); 8109 if (FAILED(hr)) 8110 continue; 8111 hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr); 8112 if (FAILED(hr)) { 8113 OLE_RELEASE(pRefTypeInfo); 8114 continue; 8115 } 8116 if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) { 8117 found = TRUE; 8118 } 8119 } 8120 if (!found) { 8121 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 8122 OLE_RELEASE(pTypeInfo2); 8123 } 8124 } 8125 OLE_RELEASE(pTypeLib); 8126 if (found) { 8127 *pCOTypeInfo = pTypeInfo2; 8128 *pCOTypeAttr = pTypeAttr2; 8129 hr = S_OK; 8130 } else { 8131 hr = E_NOINTERFACE; 8132 } 8133 return hr; 8134} 8135 8136static HRESULT 8137find_default_source_from_typeinfo( 8138 ITypeInfo *pTypeInfo, 8139 TYPEATTR *pTypeAttr, 8140 ITypeInfo **ppTypeInfo) 8141{ 8142 int i = 0; 8143 HRESULT hr = E_NOINTERFACE; 8144 int flags; 8145 HREFTYPE hRefType; 8146 /* Enumerate all implemented types of the COCLASS */ 8147 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 8148 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 8149 if (FAILED(hr)) 8150 continue; 8151 8152 /* 8153 looking for the [default] [source] 8154 we just hope that it is a dispinterface :-) 8155 */ 8156 if ((flags & IMPLTYPEFLAG_FDEFAULT) && 8157 (flags & IMPLTYPEFLAG_FSOURCE)) { 8158 8159 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 8160 i, &hRefType); 8161 if (FAILED(hr)) 8162 continue; 8163 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 8164 hRefType, ppTypeInfo); 8165 if (SUCCEEDED(hr)) 8166 break; 8167 } 8168 } 8169 return hr; 8170} 8171 8172static HRESULT 8173find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) 8174{ 8175 HRESULT hr; 8176 IProvideClassInfo2 *pProvideClassInfo2; 8177 IProvideClassInfo *pProvideClassInfo; 8178 void *p; 8179 8180 IDispatch *pDispatch; 8181 ITypeInfo *pTypeInfo; 8182 ITypeInfo *pTypeInfo2 = NULL; 8183 TYPEATTR *pTypeAttr; 8184 TYPEATTR *pTypeAttr2 = NULL; 8185 8186 struct oledata *pole; 8187 8188 OLEData_Get_Struct(ole, pole); 8189 pDispatch = pole->pDispatch; 8190 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 8191 &IID_IProvideClassInfo2, 8192 &p); 8193 if (SUCCEEDED(hr)) { 8194 pProvideClassInfo2 = p; 8195 hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2, 8196 GUIDKIND_DEFAULT_SOURCE_DISP_IID, 8197 piid); 8198 OLE_RELEASE(pProvideClassInfo2); 8199 if (SUCCEEDED(hr)) { 8200 hr = find_iid(ole, NULL, piid, ppTypeInfo); 8201 } 8202 } 8203 if (SUCCEEDED(hr)) { 8204 return hr; 8205 } 8206 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 8207 &IID_IProvideClassInfo, 8208 &p); 8209 if (SUCCEEDED(hr)) { 8210 pProvideClassInfo = p; 8211 hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo, 8212 &pTypeInfo); 8213 OLE_RELEASE(pProvideClassInfo); 8214 } 8215 if (FAILED(hr)) { 8216 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo ); 8217 } 8218 if (FAILED(hr)) 8219 return hr; 8220 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 8221 if (FAILED(hr)) { 8222 OLE_RELEASE(pTypeInfo); 8223 return hr; 8224 } 8225 8226 *ppTypeInfo = 0; 8227 hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo); 8228 if (!*ppTypeInfo) { 8229 hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2); 8230 if (SUCCEEDED(hr)) { 8231 hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo); 8232 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 8233 OLE_RELEASE(pTypeInfo2); 8234 } 8235 } 8236 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 8237 OLE_RELEASE(pTypeInfo); 8238 /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */ 8239 if (!*ppTypeInfo) { 8240 if (SUCCEEDED(hr)) 8241 hr = E_UNEXPECTED; 8242 return hr; 8243 } 8244 8245 /* Determine IID of default source interface */ 8246 hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr); 8247 if (SUCCEEDED(hr)) { 8248 *piid = pTypeAttr->guid; 8249 (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr); 8250 } 8251 else 8252 OLE_RELEASE(*ppTypeInfo); 8253 8254 return hr; 8255 8256} 8257 8258static void 8259ole_event_free(struct oleeventdata *poleev) 8260{ 8261 if (poleev->pConnectionPoint) { 8262 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); 8263 OLE_RELEASE(poleev->pConnectionPoint); 8264 poleev->pConnectionPoint = NULL; 8265 } 8266 free(poleev); 8267} 8268 8269static VALUE 8270fev_s_allocate(VALUE klass) 8271{ 8272 VALUE obj; 8273 struct oleeventdata *poleev; 8274 obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev); 8275 poleev->dwCookie = 0; 8276 poleev->pConnectionPoint = NULL; 8277 poleev->event_id = 0; 8278 return obj; 8279} 8280 8281static VALUE 8282ev_advise(int argc, VALUE *argv, VALUE self) 8283{ 8284 8285 VALUE ole, itf; 8286 struct oledata *pole; 8287 char *pitf; 8288 HRESULT hr; 8289 IID iid; 8290 ITypeInfo *pTypeInfo = 0; 8291 IDispatch *pDispatch; 8292 IConnectionPointContainer *pContainer; 8293 IConnectionPoint *pConnectionPoint; 8294 IEVENTSINKOBJ *pIEV; 8295 DWORD dwCookie; 8296 struct oleeventdata *poleev; 8297 void *p; 8298 8299 rb_secure(4); 8300 rb_scan_args(argc, argv, "11", &ole, &itf); 8301 8302 if (!rb_obj_is_kind_of(ole, cWIN32OLE)) { 8303 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object"); 8304 } 8305 8306 if(TYPE(itf) != T_NIL) { 8307 if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) { 8308 rb_raise(rb_eSecurityError, "Insecure Event Creation - %s", 8309 StringValuePtr(itf)); 8310 } 8311 SafeStringValue(itf); 8312 pitf = StringValuePtr(itf); 8313 hr = find_iid(ole, pitf, &iid, &pTypeInfo); 8314 } 8315 else { 8316 hr = find_default_source(ole, &iid, &pTypeInfo); 8317 } 8318 if (FAILED(hr)) { 8319 ole_raise(hr, rb_eRuntimeError, "interface not found"); 8320 } 8321 8322 OLEData_Get_Struct(ole, pole); 8323 pDispatch = pole->pDispatch; 8324 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 8325 &IID_IConnectionPointContainer, 8326 &p); 8327 if (FAILED(hr)) { 8328 OLE_RELEASE(pTypeInfo); 8329 ole_raise(hr, rb_eRuntimeError, 8330 "failed to query IConnectionPointContainer"); 8331 } 8332 pContainer = p; 8333 8334 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer, 8335 &iid, 8336 &pConnectionPoint); 8337 OLE_RELEASE(pContainer); 8338 if (FAILED(hr)) { 8339 OLE_RELEASE(pTypeInfo); 8340 ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint"); 8341 } 8342 pIEV = EVENTSINK_Constructor(); 8343 pIEV->m_iid = iid; 8344 hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint, 8345 (IUnknown*)pIEV, 8346 &dwCookie); 8347 if (FAILED(hr)) { 8348 ole_raise(hr, rb_eRuntimeError, "Advise Error"); 8349 } 8350 8351 Data_Get_Struct(self, struct oleeventdata, poleev); 8352 pIEV->m_event_id 8353 = NUM2INT(evs_length()); 8354 pIEV->pTypeInfo = pTypeInfo; 8355 poleev->dwCookie = dwCookie; 8356 poleev->pConnectionPoint = pConnectionPoint; 8357 poleev->event_id = pIEV->m_event_id; 8358 8359 return self; 8360} 8361 8362/* 8363 * call-seq: 8364 * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object. 8365 * 8366 * Returns OLE event object. 8367 * The first argument specifies WIN32OLE object. 8368 * The second argument specifies OLE event name. 8369 * ie = WIN32OLE.new('InternetExplorer.Application') 8370 * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') 8371 */ 8372static VALUE 8373fev_initialize(int argc, VALUE *argv, VALUE self) 8374{ 8375 ev_advise(argc, argv, self); 8376 evs_push(self); 8377 rb_ivar_set(self, id_events, rb_ary_new()); 8378 fev_set_handler(self, Qnil); 8379 return self; 8380} 8381 8382/* 8383 * call-seq: 8384 * WIN32OLE_EVENT.message_loop 8385 * 8386 * Translates and dispatches Windows message. 8387 */ 8388static VALUE 8389fev_s_msg_loop(VALUE klass) 8390{ 8391 ole_msg_loop(); 8392 return Qnil; 8393} 8394 8395 8396static void 8397add_event_call_back(VALUE obj, VALUE event, VALUE data) 8398{ 8399 VALUE events = rb_ivar_get(obj, id_events); 8400 if (NIL_P(events) || TYPE(events) != T_ARRAY) { 8401 events = rb_ary_new(); 8402 rb_ivar_set(obj, id_events, events); 8403 } 8404 ole_delete_event(events, event); 8405 rb_ary_push(events, data); 8406} 8407 8408static VALUE 8409ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) 8410{ 8411 struct oleeventdata *poleev; 8412 VALUE event, args, data; 8413 Data_Get_Struct(self, struct oleeventdata, poleev); 8414 if (poleev->pConnectionPoint == NULL) { 8415 rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first."); 8416 } 8417 rb_scan_args(argc, argv, "01*", &event, &args); 8418 if(!NIL_P(event)) { 8419 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) { 8420 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 8421 } 8422 if (TYPE(event) == T_SYMBOL) { 8423 event = rb_sym_to_s(event); 8424 } 8425 } 8426 data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg); 8427 add_event_call_back(self, event, data); 8428 return Qnil; 8429} 8430 8431/* 8432 * call-seq: 8433 * WIN32OLE_EVENT#on_event([event]){...} 8434 * 8435 * Defines the callback event. 8436 * If argument is omitted, this method defines the callback of all events. 8437 * If you want to modify reference argument in callback, return hash in 8438 * callback. If you want to return value to OLE server as result of callback 8439 * use `return' or :return. 8440 * 8441 * ie = WIN32OLE.new('InternetExplorer.Application') 8442 * ev = WIN32OLE_EVENT.new(ie) 8443 * ev.on_event("NavigateComplete") {|url| puts url} 8444 * ev.on_event() {|ev, *args| puts "#{ev} fired"} 8445 * 8446 * ev.on_event("BeforeNavigate2") {|*args| 8447 * ... 8448 * # set true to BeforeNavigate reference argument `Cancel'. 8449 * # Cancel is 7-th argument of BeforeNavigate, 8450 * # so you can use 6 as key of hash instead of 'Cancel'. 8451 * # The argument is counted from 0. 8452 * # The hash key of 0 means first argument.) 8453 * {:Cancel => true} # or {'Cancel' => true} or {6 => true} 8454 * } 8455 * 8456 * ev.on_event(...) {|*args| 8457 * {:return => 1, :xxx => yyy} 8458 * } 8459 */ 8460static VALUE 8461fev_on_event(int argc, VALUE *argv, VALUE self) 8462{ 8463 return ev_on_event(argc, argv, self, Qfalse); 8464} 8465 8466/* 8467 * call-seq: 8468 * WIN32OLE_EVENT#on_event_with_outargs([event]){...} 8469 * 8470 * Defines the callback of event. 8471 * If you want modify argument in callback, 8472 * you could use this method instead of WIN32OLE_EVENT#on_event. 8473 * 8474 * ie = WIN32OLE.new('InternetExplorer.Application') 8475 * ev = WIN32OLE_EVENT.new(ie) 8476 * ev.on_event_with_outargs('BeforeNavigate2') {|*args| 8477 * args.last[6] = true 8478 * } 8479 */ 8480static VALUE 8481fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self) 8482{ 8483 return ev_on_event(argc, argv, self, Qtrue); 8484} 8485 8486/* 8487 * call-seq: 8488 * WIN32OLE_EVENT#off_event([event]) 8489 * 8490 * removes the callback of event. 8491 * 8492 * ie = WIN32OLE.new('InternetExplorer.Application') 8493 * ev = WIN32OLE_EVENT.new(ie) 8494 * ev.on_event('BeforeNavigate2') {|*args| 8495 * args.last[6] = true 8496 * } 8497 * ... 8498 * ev.off_event('BeforeNavigate2') 8499 * ... 8500 */ 8501static VALUE 8502fev_off_event(int argc, VALUE *argv, VALUE self) 8503{ 8504 VALUE event = Qnil; 8505 VALUE events; 8506 8507 rb_secure(4); 8508 rb_scan_args(argc, argv, "01", &event); 8509 if(!NIL_P(event)) { 8510 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) { 8511 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 8512 } 8513 if (TYPE(event) == T_SYMBOL) { 8514 event = rb_sym_to_s(event); 8515 } 8516 } 8517 events = rb_ivar_get(self, id_events); 8518 if (NIL_P(events)) { 8519 return Qnil; 8520 } 8521 ole_delete_event(events, event); 8522 return Qnil; 8523} 8524 8525/* 8526 * call-seq: 8527 * WIN32OLE_EVENT#unadvise -> nil 8528 * 8529 * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object 8530 * does not receive the OLE server event any more. 8531 * This method is trial implementation. 8532 * 8533 * ie = WIN32OLE.new('InternetExplorer.Application') 8534 * ev = WIN32OLE_EVENT.new(ie) 8535 * ev.on_event() {...} 8536 * ... 8537 * ev.unadvise 8538 * 8539 */ 8540static VALUE 8541fev_unadvise(VALUE self) 8542{ 8543 struct oleeventdata *poleev; 8544 Data_Get_Struct(self, struct oleeventdata, poleev); 8545 if (poleev->pConnectionPoint) { 8546 ole_msg_loop(); 8547 evs_delete(poleev->event_id); 8548 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); 8549 OLE_RELEASE(poleev->pConnectionPoint); 8550 poleev->pConnectionPoint = NULL; 8551 } 8552 return Qnil; 8553} 8554 8555static VALUE 8556evs_push(VALUE ev) 8557{ 8558 return rb_ary_push(ary_ole_event, ev); 8559} 8560 8561static VALUE 8562evs_delete(long i) 8563{ 8564 rb_ary_store(ary_ole_event, i, Qnil); 8565 return Qnil; 8566} 8567 8568static VALUE 8569evs_entry(long i) 8570{ 8571 return rb_ary_entry(ary_ole_event, i); 8572} 8573 8574static VALUE 8575evs_length(void) 8576{ 8577 return rb_funcall(ary_ole_event, rb_intern("length"), 0); 8578} 8579 8580/* 8581 * call-seq: 8582 * WIN32OLE_EVENT#handler= 8583 * 8584 * sets event handler object. If handler object has onXXX 8585 * method according to XXX event, then onXXX method is called 8586 * when XXX event occurs. 8587 * 8588 * If handler object has method_missing and there is no 8589 * method according to the event, then method_missing 8590 * called and 1-st argument is event name. 8591 * 8592 * If handler object has onXXX method and there is block 8593 * defined by WIN32OLE_EVENT#on_event('XXX'){}, 8594 * then block is executed but handler object method is not called 8595 * when XXX event occurs. 8596 * 8597 * class Handler 8598 * def onStatusTextChange(text) 8599 * puts "StatusTextChanged" 8600 * end 8601 * def onPropertyChange(prop) 8602 * puts "PropertyChanged" 8603 * end 8604 * def method_missing(ev, *arg) 8605 * puts "other event #{ev}" 8606 * end 8607 * end 8608 * 8609 * handler = Handler.new 8610 * ie = WIN32OLE.new('InternetExplorer.Application') 8611 * ev = WIN32OLE_EVENT.new(ie) 8612 * ev.on_event("StatusTextChange") {|*args| 8613 * puts "this block executed." 8614 * puts "handler.onStatusTextChange method is not called." 8615 * } 8616 * ev.handler = handler 8617 * 8618 */ 8619static VALUE 8620fev_set_handler(VALUE self, VALUE val) 8621{ 8622 return rb_ivar_set(self, rb_intern("handler"), val); 8623} 8624 8625/* 8626 * call-seq: 8627 * WIN32OLE_EVENT#handler 8628 * 8629 * returns handler object. 8630 * 8631 */ 8632static VALUE 8633fev_get_handler(VALUE self) 8634{ 8635 return rb_ivar_get(self, rb_intern("handler")); 8636} 8637 8638static void 8639olevariant_free(struct olevariantdata *pvar) 8640{ 8641 VariantClear(&(pvar->realvar)); 8642 VariantClear(&(pvar->var)); 8643 free(pvar); 8644} 8645 8646static VALUE 8647folevariant_s_allocate(VALUE klass) 8648{ 8649 struct olevariantdata *pvar; 8650 VALUE obj; 8651 ole_initialize(); 8652 obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar); 8653 VariantInit(&(pvar->var)); 8654 VariantInit(&(pvar->realvar)); 8655 return obj; 8656} 8657 8658/* 8659 * call-seq: 8660 * WIN32OLE_VARIANT.array(ary, vt) 8661 * 8662 * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. 8663 * The first argument should be Array object which specifies dimensions 8664 * and each size of dimensions of OLE array. 8665 * The second argument specifies variant type of the element of OLE array. 8666 * 8667 * The following create 2 dimensions OLE array. The first dimensions size 8668 * is 3, and the second is 4. 8669 * 8670 * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4) 8671 * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 8672 * 8673 */ 8674static VALUE 8675folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt) 8676{ 8677 VALUE obj = Qnil; 8678 VARTYPE vt; 8679 struct olevariantdata *pvar; 8680 SAFEARRAYBOUND *psab = NULL; 8681 SAFEARRAY *psa = NULL; 8682 UINT dim = 0; 8683 UINT i = 0; 8684 8685 ole_initialize(); 8686 8687 vt = NUM2UINT(vvt); 8688 vt = (vt | VT_ARRAY); 8689 Check_Type(elems, T_ARRAY); 8690 obj = folevariant_s_allocate(klass); 8691 8692 Data_Get_Struct(obj, struct olevariantdata, pvar); 8693 dim = RARRAY_LEN(elems); 8694 8695 psab = ALLOC_N(SAFEARRAYBOUND, dim); 8696 8697 if(!psab) { 8698 rb_raise(rb_eRuntimeError, "memory allocation error"); 8699 } 8700 8701 for (i = 0; i < dim; i++) { 8702 psab[i].cElements = FIX2INT(rb_ary_entry(elems, i)); 8703 psab[i].lLbound = 0; 8704 } 8705 8706 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); 8707 if (psa == NULL) { 8708 if (psab) free(psab); 8709 rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)"); 8710 } 8711 8712 V_VT(&(pvar->var)) = vt; 8713 if (vt & VT_BYREF) { 8714 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); 8715 V_ARRAY(&(pvar->realvar)) = psa; 8716 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 8717 } else { 8718 V_ARRAY(&(pvar->var)) = psa; 8719 } 8720 if (psab) free(psab); 8721 return obj; 8722} 8723 8724/* 8725 * call-seq: 8726 * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object. 8727 * 8728 * Returns Ruby object wrapping OLE variant. 8729 * The first argument specifies Ruby object to convert OLE variant variable. 8730 * The second argument specifies VARIANT type. 8731 * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method 8732 * 8733 * shell = WIN32OLE.new("Shell.Application") 8734 * folder = shell.NameSpace("C:\\Windows") 8735 * item = folder.ParseName("tmp.txt") 8736 * # You can't use Ruby String object to call FolderItem.InvokeVerb. 8737 * # Instead, you have to use WIN32OLE_VARIANT object to call the method. 8738 * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)") 8739 * item.invokeVerb(shortcut) 8740 * 8741 */ 8742static VALUE 8743folevariant_initialize(VALUE self, VALUE args) 8744{ 8745 int len = 0; 8746 VARIANT var; 8747 VALUE val; 8748 VALUE vvt; 8749 VARTYPE vt; 8750 struct olevariantdata *pvar; 8751 8752 len = RARRAY_LEN(args); 8753 if (len < 1 || len > 3) { 8754 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); 8755 } 8756 VariantInit(&var); 8757 val = rb_ary_entry(args, 0); 8758 8759 if(!rb_obj_is_kind_of(val, cWIN32OLE) && 8760 !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) && 8761 !rb_obj_is_kind_of(val, rb_cTime)) { 8762 switch (TYPE(val)) { 8763 case T_ARRAY: 8764 case T_STRING: 8765 case T_FIXNUM: 8766 case T_BIGNUM: 8767 case T_FLOAT: 8768 case T_TRUE: 8769 case T_FALSE: 8770 case T_NIL: 8771 break; 8772 default: 8773 rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s", 8774 rb_obj_classname(val)); 8775 } 8776 } 8777 8778 Data_Get_Struct(self, struct olevariantdata, pvar); 8779 if (len == 1) { 8780 ole_val2variant(val, &(pvar->var)); 8781 } else { 8782 vvt = rb_ary_entry(args, 1); 8783 vt = NUM2INT(vvt); 8784 ole_val2olevariantdata(val, vt, pvar); 8785 } 8786 vt = V_VT(&pvar->var); 8787 return self; 8788} 8789 8790static SAFEARRAY * 8791get_locked_safe_array(VALUE val) 8792{ 8793 struct olevariantdata *pvar; 8794 SAFEARRAY *psa = NULL; 8795 HRESULT hr; 8796 Data_Get_Struct(val, struct olevariantdata, pvar); 8797 if (!(V_VT(&(pvar->var)) & VT_ARRAY)) { 8798 rb_raise(rb_eTypeError, "variant type is not VT_ARRAY."); 8799 } 8800 psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var)); 8801 if (psa == NULL) { 8802 return psa; 8803 } 8804 hr = SafeArrayLock(psa); 8805 if (FAILED(hr)) { 8806 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock"); 8807 } 8808 return psa; 8809} 8810 8811static long * 8812ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa) 8813{ 8814 long dim; 8815 long *pid; 8816 long i; 8817 dim = SafeArrayGetDim(psa); 8818 if (dim != ary_size) { 8819 rb_raise(rb_eArgError, "unmatch number of indices"); 8820 } 8821 pid = ALLOC_N(long, dim); 8822 if (pid == NULL) { 8823 rb_raise(rb_eRuntimeError, "failed to allocate memory for indices"); 8824 } 8825 for (i = 0; i < dim; i++) { 8826 pid[i] = NUM2INT(ary[i]); 8827 } 8828 return pid; 8829} 8830 8831static void 8832unlock_safe_array(SAFEARRAY *psa) 8833{ 8834 HRESULT hr; 8835 hr = SafeArrayUnlock(psa); 8836 if (FAILED(hr)) { 8837 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock"); 8838 } 8839} 8840 8841/* 8842 * call-seq: 8843 * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array. 8844 * 8845 * Returns the element of WIN32OLE_VARIANT object(OLE array). 8846 * This method is available only when the variant type of 8847 * WIN32OLE_VARIANT object is VT_ARRAY. 8848 * 8849 * REMARK: 8850 * The all indicies should be 0 or natural number and 8851 * lower than or equal to max indicies. 8852 * (This point is different with Ruby Array indicies.) 8853 * 8854 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) 8855 * p obj[0,0] # => 1 8856 * p obj[1,0] # => 4 8857 * p obj[2,0] # => WIN32OLERuntimeError 8858 * p obj[0, -1] # => WIN32OLERuntimeError 8859 * 8860 */ 8861static VALUE 8862folevariant_ary_aref(int argc, VALUE *argv, VALUE self) 8863{ 8864 struct olevariantdata *pvar; 8865 SAFEARRAY *psa; 8866 VALUE val = Qnil; 8867 VARIANT variant; 8868 long *pid; 8869 HRESULT hr; 8870 8871 Data_Get_Struct(self, struct olevariantdata, pvar); 8872 if (!V_ISARRAY(&(pvar->var))) { 8873 rb_raise(eWIN32OLERuntimeError, 8874 "`[]' is not available for this variant type object"); 8875 } 8876 psa = get_locked_safe_array(self); 8877 if (psa == NULL) { 8878 return val; 8879 } 8880 8881 pid = ary2safe_array_index(argc, argv, psa); 8882 8883 VariantInit(&variant); 8884 V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF; 8885 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); 8886 if (FAILED(hr)) { 8887 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex"); 8888 } 8889 val = ole_variant2val(&variant); 8890 8891 unlock_safe_array(psa); 8892 if (pid) free(pid); 8893 return val; 8894} 8895 8896static VOID * 8897val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt) 8898{ 8899 VOID *p = NULL; 8900 HRESULT hr = S_OK; 8901 ole_val2variant_ex(val, var, vt); 8902 if ((vt & ~VT_BYREF) == VT_VARIANT) { 8903 p = var; 8904 } else { 8905 if ( (vt & ~VT_BYREF) != V_VT(var)) { 8906 hr = VariantChangeTypeEx(var, var, 8907 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); 8908 if (FAILED(hr)) { 8909 ole_raise(hr, rb_eRuntimeError, "failed to change type"); 8910 } 8911 } 8912 p = get_ptr_of_variant(var); 8913 } 8914 if (p == NULL) { 8915 rb_raise(rb_eRuntimeError, "failed to get pointer of variant"); 8916 } 8917 return p; 8918} 8919 8920/* 8921 * call-seq: 8922 * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array 8923 * 8924 * Set the element of WIN32OLE_VARIANT object(OLE array) to val. 8925 * This method is available only when the variant type of 8926 * WIN32OLE_VARIANT object is VT_ARRAY. 8927 * 8928 * REMARK: 8929 * The all indicies should be 0 or natural number and 8930 * lower than or equal to max indicies. 8931 * (This point is different with Ruby Array indicies.) 8932 * 8933 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) 8934 * obj[0,0] = 7 8935 * obj[1,0] = 8 8936 * p obj.value # => [[7,2,3], [8,5,6]] 8937 * obj[2,0] = 9 # => WIN32OLERuntimeError 8938 * obj[0, -1] = 9 # => WIN32OLERuntimeError 8939 * 8940 */ 8941static VALUE 8942folevariant_ary_aset(int argc, VALUE *argv, VALUE self) 8943{ 8944 struct olevariantdata *pvar; 8945 SAFEARRAY *psa; 8946 VARIANT var; 8947 VARTYPE vt; 8948 long *pid; 8949 HRESULT hr; 8950 VOID *p = NULL; 8951 8952 Data_Get_Struct(self, struct olevariantdata, pvar); 8953 if (!V_ISARRAY(&(pvar->var))) { 8954 rb_raise(eWIN32OLERuntimeError, 8955 "`[]' is not available for this variant type object"); 8956 } 8957 psa = get_locked_safe_array(self); 8958 if (psa == NULL) { 8959 rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer"); 8960 } 8961 8962 pid = ary2safe_array_index(argc-1, argv, psa); 8963 8964 VariantInit(&var); 8965 vt = (V_VT(&(pvar->var)) & ~VT_ARRAY); 8966 p = val2variant_ptr(argv[argc-1], &var, vt); 8967 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || 8968 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { 8969 rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface"); 8970 } 8971 hr = SafeArrayPutElement(psa, pid, p); 8972 if (FAILED(hr)) { 8973 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement"); 8974 } 8975 8976 unlock_safe_array(psa); 8977 if (pid) free(pid); 8978 return argv[argc-1]; 8979} 8980 8981/* 8982 * call-seq: 8983 * WIN32OLE_VARIANT.value #=> Ruby object. 8984 * 8985 * Returns Ruby object value from OLE variant. 8986 * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) 8987 * obj.value # => "1" (not Fixnum object, but String object "1") 8988 * 8989 */ 8990static VALUE 8991folevariant_value(VALUE self) 8992{ 8993 struct olevariantdata *pvar; 8994 VALUE val = Qnil; 8995 VARTYPE vt; 8996 int dim; 8997 SAFEARRAY *psa; 8998 Data_Get_Struct(self, struct olevariantdata, pvar); 8999 9000 val = ole_variant2val(&(pvar->var)); 9001 vt = V_VT(&(pvar->var)); 9002 9003 if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) { 9004 if (vt & VT_BYREF) { 9005 psa = *V_ARRAYREF(&(pvar->var)); 9006 } else { 9007 psa = V_ARRAY(&(pvar->var)); 9008 } 9009 if (!psa) { 9010 return val; 9011 } 9012 dim = SafeArrayGetDim(psa); 9013 if (dim == 1) { 9014 val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*")); 9015 } 9016 } 9017 return val; 9018} 9019 9020/* 9021 * call-seq: 9022 * WIN32OLE_VARIANT.vartype #=> OLE variant type. 9023 * 9024 * Returns OLE variant type. 9025 * obj = WIN32OLE_VARIANT.new("string") 9026 * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR 9027 * 9028 */ 9029static VALUE 9030folevariant_vartype(VALUE self) 9031{ 9032 struct olevariantdata *pvar; 9033 Data_Get_Struct(self, struct olevariantdata, pvar); 9034 return INT2FIX(V_VT(&pvar->var)); 9035} 9036 9037/* 9038 * call-seq: 9039 * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val. 9040 * 9041 * Sets variant value to val. If the val type does not match variant value 9042 * type(vartype), then val is changed to match variant value type(vartype) 9043 * before setting val. 9044 * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY). 9045 * If the vartype is VT_UI1|VT_ARRAY, the val should be String object. 9046 * 9047 * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4 9048 * obj.value = 3.2 # 3.2 is changed to 3 when setting value. 9049 * p obj.value # => 3 9050 */ 9051static VALUE 9052folevariant_set_value(VALUE self, VALUE val) 9053{ 9054 struct olevariantdata *pvar; 9055 VARTYPE vt; 9056 Data_Get_Struct(self, struct olevariantdata, pvar); 9057 vt = V_VT(&(pvar->var)); 9058 if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) { 9059 rb_raise(eWIN32OLERuntimeError, 9060 "`value=' is not available for this variant type object"); 9061 } 9062 ole_val2olevariantdata(val, vt, pvar); 9063 return Qnil; 9064} 9065 9066static void 9067init_enc2cp(void) 9068{ 9069 enc2cp_table = st_init_numtable(); 9070} 9071 9072static void 9073free_enc2cp(void) 9074{ 9075 st_free_table(enc2cp_table); 9076} 9077 9078void 9079Init_win32ole(void) 9080{ 9081 g_ole_initialized_init(); 9082 ary_ole_event = rb_ary_new(); 9083 rb_gc_register_mark_object(ary_ole_event); 9084 id_events = rb_intern("events"); 9085 9086 com_vtbl.QueryInterface = QueryInterface; 9087 com_vtbl.AddRef = AddRef; 9088 com_vtbl.Release = Release; 9089 com_vtbl.GetTypeInfoCount = GetTypeInfoCount; 9090 com_vtbl.GetTypeInfo = GetTypeInfo; 9091 com_vtbl.GetIDsOfNames = GetIDsOfNames; 9092 com_vtbl.Invoke = Invoke; 9093 9094 message_filter.QueryInterface = mf_QueryInterface; 9095 message_filter.AddRef = mf_AddRef; 9096 message_filter.Release = mf_Release; 9097 message_filter.HandleInComingCall = mf_HandleInComingCall; 9098 message_filter.RetryRejectedCall = mf_RetryRejectedCall; 9099 message_filter.MessagePending = mf_MessagePending; 9100 9101 com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); 9102 rb_gc_register_mark_object(com_hash); 9103 9104 cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); 9105 9106 rb_define_alloc_func(cWIN32OLE, fole_s_allocate); 9107 9108 rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1); 9109 9110 rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1); 9111 rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1); 9112 9113 rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1); 9114 rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1); 9115 rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1); 9116 rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0); 9117 rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1); 9118 rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0); 9119 rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1); 9120 rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0); 9121 rb_define_singleton_method(cWIN32OLE, "ole_initialize", fole_s_ole_initialize, 0); 9122 rb_define_singleton_method(cWIN32OLE, "ole_uninitialize", fole_s_ole_uninitialize, 0); 9123 9124 rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1); 9125 rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1); 9126 rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3); 9127 rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3); 9128 rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3); 9129 9130 /* support propput method that takes an argument */ 9131 rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1); 9132 9133 rb_define_method(cWIN32OLE, "ole_free", fole_free, 0); 9134 9135 rb_define_method(cWIN32OLE, "each", fole_each, 0); 9136 rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1); 9137 9138 /* support setproperty method much like Perl ;-) */ 9139 rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1); 9140 9141 rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0); 9142 rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0); 9143 rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0); 9144 rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0); 9145 9146 rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1); 9147 rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method"); 9148 rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0); 9149 rb_define_method(cWIN32OLE, "ole_type", fole_type, 0); 9150 rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type"); 9151 rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0); 9152 rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1); 9153 rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1); 9154 9155 rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION)); 9156 rb_define_const(cWIN32OLE, "ARGV", rb_ary_new()); 9157 9158 rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP)); 9159 rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP)); 9160 rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP)); 9161 rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP)); 9162 rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL)); 9163 rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7)); 9164 rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8)); 9165 9166 rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT)); 9167 rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT)); 9168 9169 mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT"); 9170 rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY)); 9171 rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL)); 9172 rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2)); 9173 rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4)); 9174 rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4)); 9175 rb_define_const(mWIN32OLE_VARIANT, "VT_R8", INT2FIX(VT_R8)); 9176 rb_define_const(mWIN32OLE_VARIANT, "VT_CY", INT2FIX(VT_CY)); 9177 rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", INT2FIX(VT_DATE)); 9178 rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", INT2FIX(VT_BSTR)); 9179 rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", INT2FIX(VT_USERDEFINED)); 9180 rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", INT2FIX(VT_PTR)); 9181 rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", INT2FIX(VT_DISPATCH)); 9182 rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", INT2FIX(VT_ERROR)); 9183 rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", INT2FIX(VT_BOOL)); 9184 rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", INT2FIX(VT_VARIANT)); 9185 rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", INT2FIX(VT_UNKNOWN)); 9186 rb_define_const(mWIN32OLE_VARIANT, "VT_I1", INT2FIX(VT_I1)); 9187 rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1)); 9188 rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2)); 9189 rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4)); 9190#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 9191 rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8)); 9192 rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8)); 9193#endif 9194 rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT)); 9195 rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT)); 9196 rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY)); 9197 rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF)); 9198 9199 cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject); 9200 rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0); 9201 rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate); 9202 rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2); 9203 rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0); 9204 rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0); 9205 rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0); 9206 rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0); 9207 rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0); 9208 rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0); 9209 rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0); 9210 rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types"); 9211 rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0); 9212 rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0); 9213 rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name"); 9214 rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0); 9215 9216 cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject); 9217 rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1); 9218 rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0); 9219 rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0); 9220 rb_define_alloc_func(cWIN32OLE_TYPE, foletype_s_allocate); 9221 rb_define_method(cWIN32OLE_TYPE, "initialize", foletype_initialize, 2); 9222 rb_define_method(cWIN32OLE_TYPE, "name", foletype_name, 0); 9223 rb_define_method(cWIN32OLE_TYPE, "ole_type", foletype_ole_type, 0); 9224 rb_define_method(cWIN32OLE_TYPE, "guid", foletype_guid, 0); 9225 rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0); 9226 rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0); 9227 rb_define_alias(cWIN32OLE_TYPE, "to_s", "name"); 9228 rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0); 9229 rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0); 9230 rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0); 9231 rb_define_method(cWIN32OLE_TYPE, "helpstring", foletype_helpstring, 0); 9232 rb_define_method(cWIN32OLE_TYPE, "src_type", foletype_src_type, 0); 9233 rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0); 9234 rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0); 9235 rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0); 9236 rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0); 9237 rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0); 9238 rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0); 9239 rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0); 9240 rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0); 9241 rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0); 9242 rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0); 9243 9244 cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject); 9245 rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0); 9246 rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0); 9247 rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0); 9248 rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0); 9249 rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0); 9250 rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0); 9251 rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0); 9252 rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0); 9253 rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name"); 9254 9255 cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); 9256 rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); 9257 rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); 9258 rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0); 9259 rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0); 9260 rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0); 9261 rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0); 9262 rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0); 9263 rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0); 9264 rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0); 9265 rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0); 9266 rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0); 9267 rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0); 9268 rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0); 9269 rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0); 9270 rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0); 9271 rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0); 9272 rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0); 9273 rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0); 9274 rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0); 9275 rb_define_alias(cWIN32OLE_METHOD, "to_s", "name"); 9276 rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0); 9277 9278 cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject); 9279 rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate); 9280 rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2); 9281 rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0); 9282 rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0); 9283 rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0); 9284 rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0); 9285 rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0); 9286 rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0); 9287 rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0); 9288 rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0); 9289 rb_define_alias(cWIN32OLE_PARAM, "to_s", "name"); 9290 rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0); 9291 9292 cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject); 9293 rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0); 9294 rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate); 9295 rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1); 9296 rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1); 9297 rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1); 9298 rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1); 9299 rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0); 9300 rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1); 9301 rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0); 9302 9303 cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject); 9304 rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate); 9305 rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2); 9306 rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2); 9307 rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0); 9308 rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1); 9309 rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0); 9310 rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1); 9311 rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1); 9312 rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY))); 9313 rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL))); 9314 rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH))); 9315 9316 eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); 9317 9318 init_enc2cp(); 9319 atexit((void (*)(void))free_enc2cp); 9320 ole_init_cp(); 9321} 9322