|
Ruby
2.0.0p481(2014-05-08revision45883)
|
00001 /* 00002 * (c) 1995 Microsoft Corporation. All rights reserved. 00003 * Developed by ActiveWare Internet Corp., http://www.ActiveWare.com 00004 * 00005 * Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy 00006 * <gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net> 00007 * 00008 * You may distribute under the terms of either the GNU General Public 00009 * License or the Artistic License, as specified in the README file 00010 * of the Perl distribution. 00011 * 00012 */ 00013 00014 /* 00015 modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@nifty.ne.jp> 00016 */ 00017 00018 #include "ruby/ruby.h" 00019 #include "ruby/st.h" 00020 #include "ruby/encoding.h" 00021 00022 #define GNUC_OLDER_3_4_4 \ 00023 ((__GNUC__ < 3) || \ 00024 ((__GNUC__ <= 3) && (__GNUC_MINOR__ < 4)) || \ 00025 ((__GNUC__ <= 3) && (__GNUC_MINOR__ <= 4) && (__GNUC_PATCHLEVEL__ <= 4))) 00026 00027 #if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) 00028 #ifndef NONAMELESSUNION 00029 #define NONAMELESSUNION 1 00030 #endif 00031 #endif 00032 00033 #include <ctype.h> 00034 00035 #include <windows.h> 00036 #include <ocidl.h> 00037 #include <olectl.h> 00038 #include <ole2.h> 00039 #if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE) 00040 #include <mlang.h> 00041 #endif 00042 #include <stdlib.h> 00043 #include <math.h> 00044 #ifdef HAVE_STDARG_PROTOTYPES 00045 #include <stdarg.h> 00046 #define va_init_list(a,b) va_start(a,b) 00047 #else 00048 #include <varargs.h> 00049 #define va_init_list(a,b) va_start(a) 00050 #endif 00051 #include <objidl.h> 00052 00053 #define DOUT fprintf(stderr,"[%d]\n",__LINE__) 00054 #define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x) 00055 #define DOUTMSG(x) fprintf(stderr, "[%d]:" #x "\n",__LINE__) 00056 #define DOUTI(x) fprintf(stderr, "[%ld]:" #x "=%d\n",__LINE__,x) 00057 #define DOUTD(x) fprintf(stderr, "[%d]:" #x "=%f\n",__LINE__,x) 00058 00059 #if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) 00060 #define V_UNION1(X, Y) ((X)->u.Y) 00061 #else 00062 #define V_UNION1(X, Y) ((X)->Y) 00063 #endif 00064 00065 #if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) 00066 #undef V_UNION 00067 #define V_UNION(X,Y) ((X)->n1.n2.n3.Y) 00068 00069 #undef V_VT 00070 #define V_VT(X) ((X)->n1.n2.vt) 00071 00072 #undef V_BOOL 00073 #define V_BOOL(X) V_UNION(X,boolVal) 00074 #endif 00075 00076 #ifndef V_I1REF 00077 #define V_I1REF(X) V_UNION(X, pcVal) 00078 #endif 00079 00080 #ifndef V_UI2REF 00081 #define V_UI2REF(X) V_UNION(X, puiVal) 00082 #endif 00083 00084 #ifndef V_INT 00085 #define V_INT(X) V_UNION(X, intVal) 00086 #endif 00087 00088 #ifndef V_INTREF 00089 #define V_INTREF(X) V_UNION(X, pintVal) 00090 #endif 00091 00092 #ifndef V_UINT 00093 #define V_UINT(X) V_UNION(X, uintVal) 00094 #endif 00095 00096 #ifndef V_UINTREF 00097 #define V_UINTREF(X) V_UNION(X, puintVal) 00098 #endif 00099 00100 /* 00101 * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a 00102 * in Cygwin(mingw32). 00103 */ 00104 #if defined(__CYGWIN__) || defined(__MINGW32__) 00105 #undef IID_IMultiLanguage2 00106 const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}}; 00107 #endif 00108 00109 #define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0 00110 00111 #define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0 00112 00113 #define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y))) 00114 #define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y))) 00115 00116 #define OLE_FREE(x) {\ 00117 if(g_ole_initialized == TRUE) {\ 00118 if(x) {\ 00119 OLE_RELEASE(x);\ 00120 (x) = 0;\ 00121 }\ 00122 }\ 00123 } 00124 00125 #define OLEData_Get_Struct(obj, pole) {\ 00126 Data_Get_Struct(obj, struct oledata, pole);\ 00127 if(!pole->pDispatch) {\ 00128 rb_raise(rb_eRuntimeError, "failed to get Dispatch Interface");\ 00129 }\ 00130 } 00131 00132 #ifdef HAVE_LONG_LONG 00133 #define I8_2_NUM LL2NUM 00134 #define UI8_2_NUM ULL2NUM 00135 #define NUM2I8 NUM2LL 00136 #define NUM2UI8 NUM2ULL 00137 #else 00138 #define I8_2_NUM INT2NUM 00139 #define UI8_2_NUM UINT2NUM 00140 #define NUM2I8 NUM2INT 00141 #define NUM2UI8 NUM2UINT 00142 #endif 00143 00144 #define WC2VSTR(x) ole_wc2vstr((x), TRUE) 00145 00146 #define WIN32OLE_VERSION "1.5.4" 00147 00148 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) 00149 (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); 00150 00151 typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile, 00152 UINT uCommand, DWORD dwData); 00153 typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD); 00154 typedef struct { 00155 struct IEventSinkVtbl * lpVtbl; 00156 } IEventSink, *PEVENTSINK; 00157 00158 typedef struct IEventSinkVtbl IEventSinkVtbl; 00159 00160 struct IEventSinkVtbl { 00161 STDMETHOD(QueryInterface)( 00162 PEVENTSINK, 00163 REFIID, 00164 LPVOID *); 00165 STDMETHOD_(ULONG, AddRef)(PEVENTSINK); 00166 STDMETHOD_(ULONG, Release)(PEVENTSINK); 00167 00168 STDMETHOD(GetTypeInfoCount)( 00169 PEVENTSINK, 00170 UINT *); 00171 STDMETHOD(GetTypeInfo)( 00172 PEVENTSINK, 00173 UINT, 00174 LCID, 00175 ITypeInfo **); 00176 STDMETHOD(GetIDsOfNames)( 00177 PEVENTSINK, 00178 REFIID, 00179 OLECHAR **, 00180 UINT, 00181 LCID, 00182 DISPID *); 00183 STDMETHOD(Invoke)( 00184 PEVENTSINK, 00185 DISPID, 00186 REFIID, 00187 LCID, 00188 WORD, 00189 DISPPARAMS *, 00190 VARIANT *, 00191 EXCEPINFO *, 00192 UINT *); 00193 }; 00194 00195 typedef struct tagIEVENTSINKOBJ { 00196 IEventSinkVtbl *lpVtbl; 00197 DWORD m_cRef; 00198 IID m_iid; 00199 int m_event_id; 00200 ITypeInfo *pTypeInfo; 00201 }IEVENTSINKOBJ, *PIEVENTSINKOBJ; 00202 00203 VALUE cWIN32OLE; 00204 VALUE cWIN32OLE_TYPELIB; 00205 VALUE cWIN32OLE_TYPE; 00206 VALUE cWIN32OLE_VARIABLE; 00207 VALUE cWIN32OLE_METHOD; 00208 VALUE cWIN32OLE_PARAM; 00209 VALUE cWIN32OLE_EVENT; 00210 VALUE cWIN32OLE_VARIANT; 00211 VALUE eWIN32OLERuntimeError; 00212 VALUE mWIN32OLE_VARIANT; 00213 VALUE cWIN32OLE_PROPERTY; 00214 00215 static VALUE ary_ole_event; 00216 static ID id_events; 00217 #if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__) || defined(__MINGW32__)) 00218 static RB_THREAD_SPECIFIC BOOL g_ole_initialized; 00219 # define g_ole_initialized_init() ((void)0) 00220 # define g_ole_initialized_set(val) (g_ole_initialized = (val)) 00221 #else 00222 static volatile DWORD g_ole_initialized_key = TLS_OUT_OF_INDEXES; 00223 # define g_ole_initialized (BOOL)TlsGetValue(g_ole_initialized_key) 00224 # define g_ole_initialized_init() (g_ole_initialized_key = TlsAlloc()) 00225 # define g_ole_initialized_set(val) TlsSetValue(g_ole_initialized_key, (void*)(val)) 00226 #endif 00227 static BOOL g_uninitialize_hooked = FALSE; 00228 static BOOL g_cp_installed = FALSE; 00229 static BOOL g_lcid_installed = FALSE; 00230 static HINSTANCE ghhctrl = NULL; 00231 static HINSTANCE gole32 = NULL; 00232 static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL; 00233 static VALUE com_hash; 00234 static IDispatchVtbl com_vtbl; 00235 static UINT cWIN32OLE_cp = CP_ACP; 00236 static LCID cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT; 00237 static rb_encoding *cWIN32OLE_enc; 00238 static UINT g_cp_to_check = CP_ACP; 00239 static char g_lcid_to_check[8 + 1]; 00240 static VARTYPE g_nil_to = VT_ERROR; 00241 static st_table *enc2cp_table; 00242 static IMessageFilterVtbl message_filter; 00243 static IMessageFilter imessage_filter = { &message_filter }; 00244 static IMessageFilter* previous_filter; 00245 00246 #if defined(HAVE_TYPE_IMULTILANGUAGE2) 00247 static IMultiLanguage2 *pIMultiLanguage = NULL; 00248 #elif defined(HAVE_TYPE_IMULTILANGUAGE) 00249 static IMultiLanguage *pIMultiLanguage = NULL; 00250 #else 00251 #define pIMultiLanguage NULL /* dummy */ 00252 #endif 00253 00254 struct oledata { 00255 IDispatch *pDispatch; 00256 }; 00257 00258 struct oletypelibdata { 00259 ITypeLib *pTypeLib; 00260 }; 00261 00262 struct oletypedata { 00263 ITypeInfo *pTypeInfo; 00264 }; 00265 00266 struct olemethoddata { 00267 ITypeInfo *pOwnerTypeInfo; 00268 ITypeInfo *pTypeInfo; 00269 UINT index; 00270 }; 00271 00272 struct olevariabledata { 00273 ITypeInfo *pTypeInfo; 00274 UINT index; 00275 }; 00276 00277 struct oleparamdata { 00278 ITypeInfo *pTypeInfo; 00279 UINT method_index; 00280 UINT index; 00281 }; 00282 00283 struct oleeventdata { 00284 DWORD dwCookie; 00285 IConnectionPoint *pConnectionPoint; 00286 long event_id; 00287 }; 00288 00289 struct oleparam { 00290 DISPPARAMS dp; 00291 OLECHAR** pNamedArgs; 00292 }; 00293 00294 struct olevariantdata { 00295 VARIANT realvar; 00296 VARIANT var; 00297 }; 00298 00299 00300 static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject); 00301 static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This); 00302 static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This); 00303 static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo); 00304 static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo); 00305 static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId); 00306 static 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); 00307 static IDispatch* val2dispatch(VALUE val); 00308 static double rbtime2vtdate(VALUE tmobj); 00309 static VALUE vtdate2rbtime(double date); 00310 static rb_encoding *ole_cp2encoding(UINT cp); 00311 static UINT ole_encoding2cp(rb_encoding *enc); 00312 NORETURN(static void failed_load_conv51932(void)); 00313 #ifndef pIMultiLanguage 00314 static void load_conv_function51932(void); 00315 #endif 00316 static UINT ole_init_cp(void); 00317 static char *ole_wc2mb(LPWSTR pw); 00318 static VALUE ole_hresult2msg(HRESULT hr); 00319 static void ole_freeexceptinfo(EXCEPINFO *pExInfo); 00320 static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo); 00321 static void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...); 00322 static void ole_initialize(void); 00323 static void ole_msg_loop(void); 00324 static void ole_free(struct oledata *pole); 00325 static void oletypelib_free(struct oletypelibdata *poletypelib); 00326 static void oletype_free(struct oletypedata *poletype); 00327 static void olemethod_free(struct olemethoddata *polemethod); 00328 static void olevariable_free(struct olevariabledata *polevar); 00329 static void oleparam_free(struct oleparamdata *pole); 00330 static LPWSTR ole_vstr2wc(VALUE vstr); 00331 static LPWSTR ole_mb2wc(char *pm, int len); 00332 static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree); 00333 static VALUE ole_ary_m_entry(VALUE val, long *pid); 00334 static void * get_ptr_of_variant(VARIANT *pvar); 00335 static VALUE is_all_index_under(long *pid, long *pub, long dim); 00336 static void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt); 00337 static long dimension(VALUE val); 00338 static long ary_len_of_dim(VALUE ary, long dim); 00339 static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt); 00340 static void ole_val2variant(VALUE val, VARIANT *var); 00341 static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt); 00342 static void ole_val2ptr_variant(VALUE val, VARIANT *var); 00343 static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt); 00344 static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar); 00345 static void ole_val2variant2(VALUE val, VARIANT *var); 00346 static VALUE make_inspect(const char *class_name, VALUE detail); 00347 static VALUE default_inspect(VALUE self, const char *class_name); 00348 static VALUE ole_set_member(VALUE self, IDispatch *dispatch); 00349 static VALUE fole_s_allocate(VALUE klass); 00350 static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv); 00351 static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim); 00352 static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val); 00353 static VALUE ole_variant2val(VARIANT *pvar); 00354 static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey); 00355 static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey); 00356 static VALUE reg_enum_key(HKEY hkey, DWORD i); 00357 static VALUE reg_get_val(HKEY hkey, const char *subkey); 00358 static VALUE reg_get_typelib_file_path(HKEY hkey); 00359 static VALUE typelib_file_from_clsid(VALUE ole); 00360 static VALUE typelib_file_from_typelib(VALUE ole); 00361 static VALUE typelib_file(VALUE ole); 00362 static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self); 00363 static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid); 00364 static VALUE ole_create_dcom(int argc, VALUE *argv, VALUE self); 00365 static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self); 00366 static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self); 00367 static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self); 00368 static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes); 00369 static ULONG reference_count(struct oledata * pole); 00370 static VALUE fole_s_reference_count(VALUE self, VALUE obj); 00371 static VALUE fole_s_free(VALUE self, VALUE obj); 00372 static HWND ole_show_help(VALUE helpfile, VALUE helpcontext); 00373 static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self); 00374 static VALUE fole_s_get_code_page(VALUE self); 00375 static BOOL CALLBACK installed_code_page_proc(LPTSTR str); 00376 static BOOL code_page_installed(UINT cp); 00377 static VALUE fole_s_set_code_page(VALUE self, VALUE vcp); 00378 static VALUE fole_s_get_locale(VALUE self); 00379 static BOOL CALLBACK installed_lcid_proc(LPTSTR str); 00380 static BOOL lcid_installed(LCID lcid); 00381 static VALUE fole_s_set_locale(VALUE self, VALUE vlcid); 00382 static VALUE fole_s_create_guid(VALUE self); 00383 static VALUE fole_s_ole_initialize(VALUE self); 00384 static VALUE fole_s_ole_uninitialize(VALUE self); 00385 static VALUE fole_initialize(int argc, VALUE *argv, VALUE self); 00386 static VALUE hash2named_arg(VALUE pair, struct oleparam* pOp); 00387 static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end); 00388 static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket); 00389 static VALUE fole_invoke(int argc, VALUE *argv, VALUE self); 00390 static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind); 00391 static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types); 00392 static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types); 00393 static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types); 00394 static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self); 00395 static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self); 00396 static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self); 00397 static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value); 00398 static VALUE fole_free(VALUE self); 00399 static VALUE ole_each_sub(VALUE pEnumV); 00400 static VALUE ole_ienum_free(VALUE pEnumV); 00401 static VALUE fole_each(VALUE self); 00402 static VALUE fole_missing(int argc, VALUE *argv, VALUE self); 00403 static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name); 00404 static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name); 00405 static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask); 00406 static VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask); 00407 static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti); 00408 static VALUE ole_methods(VALUE self, int mask); 00409 static VALUE fole_methods(VALUE self); 00410 static VALUE fole_get_methods(VALUE self); 00411 static VALUE fole_put_methods(VALUE self); 00412 static VALUE fole_func_methods(VALUE self); 00413 static VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo); 00414 static VALUE fole_type(VALUE self); 00415 static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo); 00416 static VALUE fole_typelib(VALUE self); 00417 static VALUE fole_query_interface(VALUE self, VALUE str_iid); 00418 static VALUE fole_respond_to(VALUE self, VALUE method); 00419 static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); 00420 static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); 00421 static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); 00422 static VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); 00423 static VALUE fole_method_help(VALUE self, VALUE cmdname); 00424 static VALUE fole_activex_initialize(VALUE self); 00425 static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib); 00426 static VALUE foletype_s_typelibs(VALUE self); 00427 static VALUE foletype_s_progids(VALUE self); 00428 static VALUE foletype_s_allocate(VALUE klass); 00429 static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name); 00430 static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass); 00431 static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib); 00432 static ITypeLib * oletypelib_get_typelib(VALUE self); 00433 static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr); 00434 static VALUE foletypelib_s_typelibs(VALUE self); 00435 static VALUE make_version_str(VALUE major, VALUE minor); 00436 static VALUE oletypelib_search_registry2(VALUE self, VALUE args); 00437 static VALUE oletypelib_search_registry(VALUE self, VALUE typelib); 00438 static VALUE foletypelib_s_allocate(VALUE klass); 00439 static VALUE foletypelib_initialize(VALUE self, VALUE args); 00440 static VALUE foletypelib_guid(VALUE self); 00441 static VALUE foletypelib_name(VALUE self); 00442 static VALUE foletypelib_version(VALUE self); 00443 static VALUE foletypelib_major_version(VALUE self); 00444 static VALUE foletypelib_minor_version(VALUE self); 00445 static VALUE oletypelib_path(VALUE guid, VALUE version); 00446 static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib); 00447 static VALUE foletypelib_path(VALUE self); 00448 static VALUE foletypelib_visible(VALUE self); 00449 static VALUE foletypelib_library_name(VALUE self); 00450 static VALUE foletypelib_ole_types(VALUE self); 00451 static VALUE foletypelib_inspect(VALUE self); 00452 static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass); 00453 static VALUE foletype_name(VALUE self); 00454 static VALUE ole_ole_type(ITypeInfo *pTypeInfo); 00455 static VALUE foletype_ole_type(VALUE self); 00456 static VALUE ole_type_guid(ITypeInfo *pTypeInfo); 00457 static VALUE foletype_guid(VALUE self); 00458 static VALUE ole_type_progid(ITypeInfo *pTypeInfo); 00459 static VALUE foletype_progid(VALUE self); 00460 static VALUE ole_type_visible(ITypeInfo *pTypeInfo); 00461 static VALUE foletype_visible(VALUE self); 00462 static VALUE ole_type_major_version(ITypeInfo *pTypeInfo); 00463 static VALUE foletype_major_version(VALUE self); 00464 static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo); 00465 static VALUE foletype_minor_version(VALUE self); 00466 static VALUE ole_type_typekind(ITypeInfo *pTypeInfo); 00467 static VALUE foletype_typekind(VALUE self); 00468 static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo); 00469 static VALUE foletype_helpstring(VALUE self); 00470 static VALUE ole_type_src_type(ITypeInfo *pTypeInfo); 00471 static VALUE foletype_src_type(VALUE self); 00472 static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo); 00473 static VALUE foletype_helpfile(VALUE self); 00474 static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo); 00475 static VALUE foletype_helpcontext(VALUE self); 00476 static VALUE foletype_ole_typelib(VALUE self); 00477 static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags); 00478 static VALUE foletype_impl_ole_types(VALUE self); 00479 static VALUE foletype_source_ole_types(VALUE self); 00480 static VALUE foletype_default_event_sources(VALUE self); 00481 static VALUE foletype_default_ole_types(VALUE self); 00482 static VALUE foletype_inspect(VALUE self); 00483 static VALUE ole_variables(ITypeInfo *pTypeInfo); 00484 static VALUE foletype_variables(VALUE self); 00485 static VALUE foletype_methods(VALUE self); 00486 static VALUE folevariable_name(VALUE self); 00487 static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index); 00488 static VALUE folevariable_ole_type(VALUE self); 00489 static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index); 00490 static VALUE folevariable_ole_type_detail(VALUE self); 00491 static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index); 00492 static VALUE folevariable_value(VALUE self); 00493 static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index); 00494 static VALUE folevariable_visible(VALUE self); 00495 static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index); 00496 static VALUE folevariable_variable_kind(VALUE self); 00497 static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index); 00498 static VALUE folevariable_varkind(VALUE self); 00499 static VALUE folevariable_inspect(VALUE self); 00500 static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name); 00501 static VALUE folemethod_s_allocate(VALUE klass); 00502 static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method); 00503 static VALUE folemethod_name(VALUE self); 00504 static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index); 00505 static VALUE folemethod_return_type(VALUE self); 00506 static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index); 00507 static VALUE folemethod_return_vtype(VALUE self); 00508 static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index); 00509 static VALUE folemethod_return_type_detail(VALUE self); 00510 static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index); 00511 static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index); 00512 static VALUE folemethod_invkind(VALUE self); 00513 static VALUE folemethod_invoke_kind(VALUE self); 00514 static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index); 00515 static VALUE folemethod_visible(VALUE self); 00516 static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name); 00517 static VALUE folemethod_event(VALUE self); 00518 static VALUE folemethod_event_interface(VALUE self); 00519 static VALUE ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); 00520 static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index); 00521 static VALUE folemethod_helpstring(VALUE self); 00522 static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index); 00523 static VALUE folemethod_helpfile(VALUE self); 00524 static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index); 00525 static VALUE folemethod_helpcontext(VALUE self); 00526 static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index); 00527 static VALUE folemethod_dispid(VALUE self); 00528 static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index); 00529 static VALUE folemethod_offset_vtbl(VALUE self); 00530 static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index); 00531 static VALUE folemethod_size_params(VALUE self); 00532 static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index); 00533 static VALUE folemethod_size_opt_params(VALUE self); 00534 static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index); 00535 static VALUE folemethod_params(VALUE self); 00536 static VALUE folemethod_inspect(VALUE self); 00537 static VALUE foleparam_s_allocate(VALUE klass); 00538 static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index); 00539 static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n); 00540 static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n); 00541 static VALUE foleparam_name(VALUE self); 00542 static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index); 00543 static VALUE foleparam_ole_type(VALUE self); 00544 static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index); 00545 static VALUE foleparam_ole_type_detail(VALUE self); 00546 static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask); 00547 static VALUE foleparam_input(VALUE self); 00548 static VALUE foleparam_output(VALUE self); 00549 static VALUE foleparam_optional(VALUE self); 00550 static VALUE foleparam_retval(VALUE self); 00551 static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index); 00552 static VALUE foleparam_default(VALUE self); 00553 static VALUE foleparam_inspect(VALUE self); 00554 static long ole_search_event_at(VALUE ary, VALUE ev); 00555 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default); 00556 static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler); 00557 static void ole_delete_event(VALUE ary, VALUE ev); 00558 static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams); 00559 static VALUE hash2result(VALUE hash); 00560 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams); 00561 static VALUE exec_callback(VALUE arg); 00562 static VALUE rescue_callback(VALUE arg); 00563 static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo); 00564 static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2); 00565 static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo); 00566 static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo); 00567 static void ole_event_free(struct oleeventdata *poleev); 00568 static VALUE fev_s_allocate(VALUE klass); 00569 static VALUE ev_advise(int argc, VALUE *argv, VALUE self); 00570 static VALUE fev_initialize(int argc, VALUE *argv, VALUE self); 00571 static VALUE fev_s_msg_loop(VALUE klass); 00572 static void add_event_call_back(VALUE obj, VALUE event, VALUE data); 00573 static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg); 00574 static VALUE fev_on_event(int argc, VALUE *argv, VALUE self); 00575 static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self); 00576 static VALUE fev_off_event(int argc, VALUE *argv, VALUE self); 00577 static VALUE fev_unadvise(VALUE self); 00578 static VALUE fev_set_handler(VALUE self, VALUE val); 00579 static VALUE fev_get_handler(VALUE self); 00580 static VALUE evs_push(VALUE ev); 00581 static VALUE evs_delete(long i); 00582 static VALUE evs_entry(long i); 00583 static VALUE evs_length(void); 00584 static void olevariant_free(struct olevariantdata *pvar); 00585 static VALUE folevariant_s_allocate(VALUE klass); 00586 static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt); 00587 static VALUE folevariant_initialize(VALUE self, VALUE args); 00588 static long *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa); 00589 static void unlock_safe_array(SAFEARRAY *psa); 00590 static SAFEARRAY *get_locked_safe_array(VALUE val); 00591 static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self); 00592 static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt); 00593 static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self); 00594 static VALUE folevariant_value(VALUE self); 00595 static VALUE folevariant_vartype(VALUE self); 00596 static VALUE folevariant_set_value(VALUE self, VALUE val); 00597 static void init_enc2cp(void); 00598 static void free_enc2cp(void); 00599 00600 static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)( 00601 IMessageFilter __RPC_FAR * This, 00602 /* [in] */ REFIID riid, 00603 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) 00604 { 00605 if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 00606 || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0) 00607 { 00608 *ppvObject = &message_filter; 00609 return S_OK; 00610 } 00611 return E_NOINTERFACE; 00612 } 00613 00614 static ULONG (STDMETHODCALLTYPE mf_AddRef)( 00615 IMessageFilter __RPC_FAR * This) 00616 { 00617 return 1; 00618 } 00619 00620 static ULONG (STDMETHODCALLTYPE mf_Release)( 00621 IMessageFilter __RPC_FAR * This) 00622 { 00623 return 1; 00624 } 00625 00626 static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)( 00627 IMessageFilter __RPC_FAR * pThis, 00628 DWORD dwCallType, //Type of incoming call 00629 HTASK threadIDCaller, //Task handle calling this task 00630 DWORD dwTickCount, //Elapsed tick count 00631 LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure 00632 ) 00633 { 00634 #ifdef DEBUG_MESSAGEFILTER 00635 printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount); 00636 fflush(stdout); 00637 #endif 00638 switch (dwCallType) 00639 { 00640 case CALLTYPE_ASYNC: 00641 case CALLTYPE_TOPLEVEL_CALLPENDING: 00642 case CALLTYPE_ASYNC_CALLPENDING: 00643 if (rb_during_gc()) { 00644 return SERVERCALL_RETRYLATER; 00645 } 00646 break; 00647 default: 00648 break; 00649 } 00650 if (previous_filter) { 00651 return previous_filter->lpVtbl->HandleInComingCall(previous_filter, 00652 dwCallType, 00653 threadIDCaller, 00654 dwTickCount, 00655 lpInterfaceInfo); 00656 } 00657 return SERVERCALL_ISHANDLED; 00658 } 00659 00660 static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)( 00661 IMessageFilter* pThis, 00662 HTASK threadIDCallee, //Server task handle 00663 DWORD dwTickCount, //Elapsed tick count 00664 DWORD dwRejectType //Returned rejection message 00665 ) 00666 { 00667 if (previous_filter) { 00668 return previous_filter->lpVtbl->RetryRejectedCall(previous_filter, 00669 threadIDCallee, 00670 dwTickCount, 00671 dwRejectType); 00672 } 00673 return 1000; 00674 } 00675 00676 static DWORD (STDMETHODCALLTYPE mf_MessagePending)( 00677 IMessageFilter* pThis, 00678 HTASK threadIDCallee, //Called applications task handle 00679 DWORD dwTickCount, //Elapsed tick count 00680 DWORD dwPendingType //Call type 00681 ) 00682 { 00683 if (rb_during_gc()) { 00684 return PENDINGMSG_WAITNOPROCESS; 00685 } 00686 if (previous_filter) { 00687 return previous_filter->lpVtbl->MessagePending(previous_filter, 00688 threadIDCallee, 00689 dwTickCount, 00690 dwPendingType); 00691 } 00692 return PENDINGMSG_WAITNOPROCESS; 00693 } 00694 00695 typedef struct _Win32OLEIDispatch 00696 { 00697 IDispatch dispatch; 00698 ULONG refcount; 00699 VALUE obj; 00700 } Win32OLEIDispatch; 00701 00702 static HRESULT ( STDMETHODCALLTYPE QueryInterface )( 00703 IDispatch __RPC_FAR * This, 00704 /* [in] */ REFIID riid, 00705 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) 00706 { 00707 if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 00708 || MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0) 00709 { 00710 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 00711 p->refcount++; 00712 *ppvObject = This; 00713 return S_OK; 00714 } 00715 return E_NOINTERFACE; 00716 } 00717 00718 static ULONG ( STDMETHODCALLTYPE AddRef )( 00719 IDispatch __RPC_FAR * This) 00720 { 00721 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 00722 return ++(p->refcount); 00723 } 00724 00725 static ULONG ( STDMETHODCALLTYPE Release )( 00726 IDispatch __RPC_FAR * This) 00727 { 00728 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 00729 ULONG u = --(p->refcount); 00730 if (u == 0) { 00731 st_data_t key = p->obj; 00732 st_delete(DATA_PTR(com_hash), &key, 0); 00733 free(p); 00734 } 00735 return u; 00736 } 00737 00738 static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )( 00739 IDispatch __RPC_FAR * This, 00740 /* [out] */ UINT __RPC_FAR *pctinfo) 00741 { 00742 return E_NOTIMPL; 00743 } 00744 00745 static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )( 00746 IDispatch __RPC_FAR * This, 00747 /* [in] */ UINT iTInfo, 00748 /* [in] */ LCID lcid, 00749 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo) 00750 { 00751 return E_NOTIMPL; 00752 } 00753 00754 00755 static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )( 00756 IDispatch __RPC_FAR * This, 00757 /* [in] */ REFIID riid, 00758 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames, 00759 /* [in] */ UINT cNames, 00760 /* [in] */ LCID lcid, 00761 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) 00762 { 00763 /* 00764 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 00765 */ 00766 char* psz = ole_wc2mb(*rgszNames); // support only one method 00767 *rgDispId = rb_intern(psz); 00768 free(psz); 00769 return S_OK; 00770 } 00771 00772 static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )( 00773 IDispatch __RPC_FAR * This, 00774 /* [in] */ DISPID dispIdMember, 00775 /* [in] */ REFIID riid, 00776 /* [in] */ LCID lcid, 00777 /* [in] */ WORD wFlags, 00778 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams, 00779 /* [out] */ VARIANT __RPC_FAR *pVarResult, 00780 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo, 00781 /* [out] */ UINT __RPC_FAR *puArgErr) 00782 { 00783 VALUE v; 00784 int i; 00785 int args = pDispParams->cArgs; 00786 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; 00787 VALUE* parg = ALLOCA_N(VALUE, args); 00788 for (i = 0; i < args; i++) { 00789 *(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]); 00790 } 00791 if (dispIdMember == DISPID_VALUE) { 00792 if (wFlags == DISPATCH_METHOD) { 00793 dispIdMember = rb_intern("call"); 00794 } else if (wFlags & DISPATCH_PROPERTYGET) { 00795 dispIdMember = rb_intern("value"); 00796 } 00797 } 00798 v = rb_funcall2(p->obj, dispIdMember, args, parg); 00799 ole_val2variant(v, pVarResult); 00800 return S_OK; 00801 } 00802 00803 static IDispatch* 00804 val2dispatch(VALUE val) 00805 { 00806 struct st_table *tbl = DATA_PTR(com_hash); 00807 Win32OLEIDispatch* pdisp; 00808 st_data_t data; 00809 00810 if (st_lookup(tbl, val, &data)) { 00811 pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG); 00812 pdisp->refcount++; 00813 } 00814 else { 00815 pdisp = ALLOC(Win32OLEIDispatch); 00816 pdisp->dispatch.lpVtbl = &com_vtbl; 00817 pdisp->refcount = 1; 00818 pdisp->obj = val; 00819 st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG); 00820 } 00821 return &pdisp->dispatch; 00822 } 00823 00824 static double 00825 rbtime2vtdate(VALUE tmobj) 00826 { 00827 SYSTEMTIME st; 00828 double t = 0; 00829 memset(&st, 0, sizeof(SYSTEMTIME)); 00830 st.wYear = FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0)); 00831 st.wMonth = FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0)); 00832 st.wDay = FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0)); 00833 st.wHour = FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0)); 00834 st.wMinute = FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0)); 00835 st.wSecond = FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0)); 00836 st.wMilliseconds = FIX2INT(rb_funcall(tmobj, rb_intern("nsec"), 0)) / 1000000; 00837 SystemTimeToVariantTime(&st, &t); 00838 return t; 00839 } 00840 00841 static VALUE 00842 vtdate2rbtime(double date) 00843 { 00844 SYSTEMTIME st; 00845 VALUE v; 00846 VariantTimeToSystemTime(date, &st); 00847 00848 v = rb_funcall(rb_cTime, rb_intern("new"), 6, 00849 INT2FIX(st.wYear), 00850 INT2FIX(st.wMonth), 00851 INT2FIX(st.wDay), 00852 INT2FIX(st.wHour), 00853 INT2FIX(st.wMinute), 00854 INT2FIX(st.wSecond)); 00855 if (st.wMilliseconds > 0) { 00856 return rb_funcall(v, rb_intern("+"), 1, rb_float_new((double)(st.wMilliseconds / 1000.0))); 00857 } 00858 return v; 00859 } 00860 00861 #define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp 00862 00863 static UINT ole_encoding2cp(rb_encoding *enc) 00864 { 00865 /* 00866 * Is there any better solution to convert 00867 * Ruby encoding to Windows codepage??? 00868 */ 00869 ENC_MACHING_CP(enc, "Big5", 950); 00870 ENC_MACHING_CP(enc, "CP51932", 51932); 00871 ENC_MACHING_CP(enc, "CP850", 850); 00872 ENC_MACHING_CP(enc, "CP852", 852); 00873 ENC_MACHING_CP(enc, "CP855", 855); 00874 ENC_MACHING_CP(enc, "CP949", 949); 00875 ENC_MACHING_CP(enc, "EUC-JP", 20932); 00876 ENC_MACHING_CP(enc, "EUC-KR", 51949); 00877 ENC_MACHING_CP(enc, "EUC-TW", 51950); 00878 ENC_MACHING_CP(enc, "GB18030", 54936); 00879 ENC_MACHING_CP(enc, "GB2312", 20936); 00880 ENC_MACHING_CP(enc, "GBK", 936); 00881 ENC_MACHING_CP(enc, "IBM437", 437); 00882 ENC_MACHING_CP(enc, "IBM737", 737); 00883 ENC_MACHING_CP(enc, "IBM775", 775); 00884 ENC_MACHING_CP(enc, "IBM852", 852); 00885 ENC_MACHING_CP(enc, "IBM855", 855); 00886 ENC_MACHING_CP(enc, "IBM857", 857); 00887 ENC_MACHING_CP(enc, "IBM860", 860); 00888 ENC_MACHING_CP(enc, "IBM861", 861); 00889 ENC_MACHING_CP(enc, "IBM862", 862); 00890 ENC_MACHING_CP(enc, "IBM863", 863); 00891 ENC_MACHING_CP(enc, "IBM864", 864); 00892 ENC_MACHING_CP(enc, "IBM865", 865); 00893 ENC_MACHING_CP(enc, "IBM866", 866); 00894 ENC_MACHING_CP(enc, "IBM869", 869); 00895 ENC_MACHING_CP(enc, "ISO-2022-JP", 50220); 00896 ENC_MACHING_CP(enc, "ISO-8859-1", 28591); 00897 ENC_MACHING_CP(enc, "ISO-8859-15", 28605); 00898 ENC_MACHING_CP(enc, "ISO-8859-2", 28592); 00899 ENC_MACHING_CP(enc, "ISO-8859-3", 28593); 00900 ENC_MACHING_CP(enc, "ISO-8859-4", 28594); 00901 ENC_MACHING_CP(enc, "ISO-8859-5", 28595); 00902 ENC_MACHING_CP(enc, "ISO-8859-6", 28596); 00903 ENC_MACHING_CP(enc, "ISO-8859-7", 28597); 00904 ENC_MACHING_CP(enc, "ISO-8859-8", 28598); 00905 ENC_MACHING_CP(enc, "ISO-8859-9", 28599); 00906 ENC_MACHING_CP(enc, "KOI8-R", 20866); 00907 ENC_MACHING_CP(enc, "KOI8-U", 21866); 00908 ENC_MACHING_CP(enc, "Shift_JIS", 932); 00909 ENC_MACHING_CP(enc, "UTF-16BE", 1201); 00910 ENC_MACHING_CP(enc, "UTF-16LE", 1200); 00911 ENC_MACHING_CP(enc, "UTF-7", 65000); 00912 ENC_MACHING_CP(enc, "UTF-8", 65001); 00913 ENC_MACHING_CP(enc, "Windows-1250", 1250); 00914 ENC_MACHING_CP(enc, "Windows-1251", 1251); 00915 ENC_MACHING_CP(enc, "Windows-1252", 1252); 00916 ENC_MACHING_CP(enc, "Windows-1253", 1253); 00917 ENC_MACHING_CP(enc, "Windows-1254", 1254); 00918 ENC_MACHING_CP(enc, "Windows-1255", 1255); 00919 ENC_MACHING_CP(enc, "Windows-1256", 1256); 00920 ENC_MACHING_CP(enc, "Windows-1257", 1257); 00921 ENC_MACHING_CP(enc, "Windows-1258", 1258); 00922 ENC_MACHING_CP(enc, "Windows-31J", 932); 00923 ENC_MACHING_CP(enc, "Windows-874", 874); 00924 ENC_MACHING_CP(enc, "eucJP-ms", 20932); 00925 return CP_ACP; 00926 } 00927 00928 static void 00929 failed_load_conv51932(void) 00930 { 00931 rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932"); 00932 } 00933 00934 #ifndef pIMultiLanguage 00935 static void 00936 load_conv_function51932(void) 00937 { 00938 HRESULT hr = E_NOINTERFACE; 00939 void *p; 00940 if (!pIMultiLanguage) { 00941 #if defined(HAVE_TYPE_IMULTILANGUAGE2) 00942 hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, 00943 &IID_IMultiLanguage2, &p); 00944 #elif defined(HAVE_TYPE_IMULTILANGUAGE) 00945 hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, 00946 &IID_IMultiLanguage, &p); 00947 #endif 00948 if (FAILED(hr)) { 00949 failed_load_conv51932(); 00950 } 00951 pIMultiLanguage = p; 00952 } 00953 } 00954 #else 00955 #define load_conv_function51932() failed_load_conv51932() 00956 #endif 00957 00958 #define conv_51932(cp) ((cp) == 51932 && (load_conv_function51932(), 1)) 00959 00960 static void 00961 set_ole_codepage(UINT cp) 00962 { 00963 if (code_page_installed(cp)) { 00964 cWIN32OLE_cp = cp; 00965 } else { 00966 switch(cp) { 00967 case CP_ACP: 00968 case CP_OEMCP: 00969 case CP_MACCP: 00970 case CP_THREAD_ACP: 00971 case CP_SYMBOL: 00972 case CP_UTF7: 00973 case CP_UTF8: 00974 cWIN32OLE_cp = cp; 00975 break; 00976 case 51932: 00977 cWIN32OLE_cp = cp; 00978 load_conv_function51932(); 00979 break; 00980 default: 00981 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."); 00982 break; 00983 } 00984 } 00985 cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp); 00986 } 00987 00988 00989 static UINT 00990 ole_init_cp(void) 00991 { 00992 UINT cp; 00993 rb_encoding *encdef; 00994 encdef = rb_default_internal_encoding(); 00995 if (!encdef) { 00996 encdef = rb_default_external_encoding(); 00997 } 00998 cp = ole_encoding2cp(encdef); 00999 set_ole_codepage(cp); 01000 return cp; 01001 } 01002 01003 struct myCPINFOEX { 01004 UINT MaxCharSize; 01005 BYTE DefaultChar[2]; 01006 BYTE LeadByte[12]; 01007 WCHAR UnicodeDefaultChar; 01008 UINT CodePage; 01009 char CodePageName[MAX_PATH]; 01010 }; 01011 01012 static rb_encoding * 01013 ole_cp2encoding(UINT cp) 01014 { 01015 static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL; 01016 struct myCPINFOEX* buf; 01017 VALUE enc_name; 01018 char *enc_cstr; 01019 int idx; 01020 01021 if (!code_page_installed(cp)) { 01022 switch(cp) { 01023 case CP_ACP: 01024 cp = GetACP(); 01025 break; 01026 case CP_OEMCP: 01027 cp = GetOEMCP(); 01028 break; 01029 case CP_MACCP: 01030 case CP_THREAD_ACP: 01031 if (!pGetCPInfoEx) { 01032 pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *)) 01033 GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx"); 01034 if (!pGetCPInfoEx) { 01035 pGetCPInfoEx = (void*)-1; 01036 } 01037 } 01038 buf = ALLOCA_N(struct myCPINFOEX, 1); 01039 ZeroMemory(buf, sizeof(struct myCPINFOEX)); 01040 if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) { 01041 rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding."); 01042 break; /* never reach here */ 01043 } 01044 cp = buf->CodePage; 01045 break; 01046 case CP_SYMBOL: 01047 case CP_UTF7: 01048 case CP_UTF8: 01049 break; 01050 case 51932: 01051 load_conv_function51932(); 01052 break; 01053 default: 01054 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."); 01055 break; 01056 } 01057 } 01058 01059 enc_name = rb_sprintf("CP%d", cp); 01060 idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name)); 01061 if (idx < 0) 01062 idx = rb_define_dummy_encoding(enc_cstr); 01063 return rb_enc_from_index(idx); 01064 } 01065 01066 static char * 01067 ole_wc2mb(LPWSTR pw) 01068 { 01069 LPSTR pm; 01070 UINT size = 0; 01071 if (conv_51932(cWIN32OLE_cp)) { 01072 #ifndef pIMultiLanguage 01073 DWORD dw = 0; 01074 HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage, 01075 &dw, cWIN32OLE_cp, pw, NULL, NULL, &size); 01076 if (FAILED(hr)) { 01077 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); 01078 } 01079 pm = ALLOC_N(char, size + 1); 01080 hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage, 01081 &dw, cWIN32OLE_cp, pw, NULL, pm, &size); 01082 if (FAILED(hr)) { 01083 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); 01084 } 01085 pm[size] = '\0'; 01086 #endif 01087 return pm; 01088 } 01089 size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL); 01090 if (size) { 01091 pm = ALLOC_N(char, size + 1); 01092 WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, pm, size, NULL, NULL); 01093 pm[size] = '\0'; 01094 } 01095 else { 01096 pm = ALLOC_N(char, 1); 01097 *pm = '\0'; 01098 } 01099 return pm; 01100 } 01101 01102 static VALUE 01103 ole_hresult2msg(HRESULT hr) 01104 { 01105 VALUE msg = Qnil; 01106 char *p_msg = NULL; 01107 char *term = NULL; 01108 DWORD dwCount; 01109 01110 char strhr[100]; 01111 sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr); 01112 msg = rb_str_new2(strhr); 01113 dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 01114 FORMAT_MESSAGE_FROM_SYSTEM | 01115 FORMAT_MESSAGE_IGNORE_INSERTS, 01116 NULL, hr, 01117 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 01118 (LPTSTR)&p_msg, 0, NULL); 01119 if (dwCount == 0) { 01120 dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 01121 FORMAT_MESSAGE_FROM_SYSTEM | 01122 FORMAT_MESSAGE_IGNORE_INSERTS, 01123 NULL, hr, cWIN32OLE_lcid, 01124 (LPTSTR)&p_msg, 0, NULL); 01125 } 01126 if (dwCount > 0) { 01127 term = p_msg + strlen(p_msg); 01128 while (p_msg < term) { 01129 term--; 01130 if (*term == '\r' || *term == '\n') 01131 *term = '\0'; 01132 else break; 01133 } 01134 if (p_msg[0] != '\0') { 01135 rb_str_cat2(msg, p_msg); 01136 } 01137 } 01138 LocalFree(p_msg); 01139 return msg; 01140 } 01141 01142 static void 01143 ole_freeexceptinfo(EXCEPINFO *pExInfo) 01144 { 01145 SysFreeString(pExInfo->bstrDescription); 01146 SysFreeString(pExInfo->bstrSource); 01147 SysFreeString(pExInfo->bstrHelpFile); 01148 } 01149 01150 static VALUE 01151 ole_excepinfo2msg(EXCEPINFO *pExInfo) 01152 { 01153 char error_code[40]; 01154 char *pSource = NULL; 01155 char *pDescription = NULL; 01156 VALUE error_msg; 01157 if(pExInfo->pfnDeferredFillIn != NULL) { 01158 (*pExInfo->pfnDeferredFillIn)(pExInfo); 01159 } 01160 if (pExInfo->bstrSource != NULL) { 01161 pSource = ole_wc2mb(pExInfo->bstrSource); 01162 } 01163 if (pExInfo->bstrDescription != NULL) { 01164 pDescription = ole_wc2mb(pExInfo->bstrDescription); 01165 } 01166 if(pExInfo->wCode == 0) { 01167 sprintf(error_code, "\n OLE error code:%lX in ", pExInfo->scode); 01168 } 01169 else{ 01170 sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode); 01171 } 01172 error_msg = rb_str_new2(error_code); 01173 if(pSource != NULL) { 01174 rb_str_cat(error_msg, pSource, strlen(pSource)); 01175 } 01176 else { 01177 rb_str_cat(error_msg, "<Unknown>", 9); 01178 } 01179 rb_str_cat2(error_msg, "\n "); 01180 if(pDescription != NULL) { 01181 rb_str_cat2(error_msg, pDescription); 01182 } 01183 else { 01184 rb_str_cat2(error_msg, "<No Description>"); 01185 } 01186 if(pSource) free(pSource); 01187 if(pDescription) free(pDescription); 01188 ole_freeexceptinfo(pExInfo); 01189 return error_msg; 01190 } 01191 01192 static void 01193 ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...) 01194 { 01195 va_list args; 01196 VALUE msg; 01197 VALUE err_msg; 01198 va_init_list(args, fmt); 01199 msg = rb_vsprintf(fmt, args); 01200 va_end(args); 01201 01202 err_msg = ole_hresult2msg(hr); 01203 if(err_msg != Qnil) { 01204 rb_str_cat2(msg, "\n"); 01205 rb_str_append(msg, err_msg); 01206 } 01207 rb_exc_raise(rb_exc_new3(ecs, msg)); 01208 } 01209 01210 void 01211 ole_uninitialize(void) 01212 { 01213 if (!g_ole_initialized) return; 01214 OleUninitialize(); 01215 g_ole_initialized_set(FALSE); 01216 } 01217 01218 static void 01219 ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass) 01220 { 01221 ole_uninitialize(); 01222 } 01223 01224 static void 01225 ole_initialize(void) 01226 { 01227 HRESULT hr; 01228 01229 if(!g_uninitialize_hooked) { 01230 rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil); 01231 g_uninitialize_hooked = TRUE; 01232 } 01233 01234 if(g_ole_initialized == FALSE) { 01235 hr = OleInitialize(NULL); 01236 if(FAILED(hr)) { 01237 ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize"); 01238 } 01239 g_ole_initialized_set(TRUE); 01240 01241 hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter); 01242 if(FAILED(hr)) { 01243 previous_filter = NULL; 01244 ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter"); 01245 } 01246 } 01247 } 01248 01249 static void 01250 ole_msg_loop() { 01251 MSG msg; 01252 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { 01253 TranslateMessage(&msg); 01254 DispatchMessage(&msg); 01255 } 01256 } 01257 01258 static void 01259 ole_free(struct oledata *pole) 01260 { 01261 OLE_FREE(pole->pDispatch); 01262 free(pole); 01263 } 01264 01265 static void 01266 oletypelib_free(struct oletypelibdata *poletypelib) 01267 { 01268 OLE_FREE(poletypelib->pTypeLib); 01269 free(poletypelib); 01270 } 01271 01272 static void 01273 oletype_free(struct oletypedata *poletype) 01274 { 01275 OLE_FREE(poletype->pTypeInfo); 01276 free(poletype); 01277 } 01278 01279 static void 01280 olemethod_free(struct olemethoddata *polemethod) 01281 { 01282 OLE_FREE(polemethod->pTypeInfo); 01283 OLE_FREE(polemethod->pOwnerTypeInfo); 01284 free(polemethod); 01285 } 01286 01287 static void 01288 olevariable_free(struct olevariabledata *polevar) 01289 { 01290 OLE_FREE(polevar->pTypeInfo); 01291 free(polevar); 01292 } 01293 01294 static void 01295 oleparam_free(struct oleparamdata *pole) 01296 { 01297 OLE_FREE(pole->pTypeInfo); 01298 free(pole); 01299 } 01300 01301 01302 static LPWSTR 01303 ole_vstr2wc(VALUE vstr) 01304 { 01305 rb_encoding *enc; 01306 int cp; 01307 UINT size = 0; 01308 LPWSTR pw; 01309 st_data_t data; 01310 enc = rb_enc_get(vstr); 01311 01312 if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) { 01313 cp = data; 01314 } else { 01315 cp = ole_encoding2cp(enc); 01316 if (code_page_installed(cp) || 01317 cp == CP_ACP || 01318 cp == CP_OEMCP || 01319 cp == CP_MACCP || 01320 cp == CP_THREAD_ACP || 01321 cp == CP_SYMBOL || 01322 cp == CP_UTF7 || 01323 cp == CP_UTF8 || 01324 cp == 51932) { 01325 st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp); 01326 } else { 01327 rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc)); 01328 } 01329 } 01330 if (conv_51932(cp)) { 01331 #ifndef pIMultiLanguage 01332 DWORD dw = 0; 01333 UINT len = RSTRING_LENINT(vstr); 01334 HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 01335 &dw, cp, RSTRING_PTR(vstr), &len, NULL, &size); 01336 if (FAILED(hr)) { 01337 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp); 01338 } 01339 pw = SysAllocStringLen(NULL, size); 01340 len = RSTRING_LEN(vstr); 01341 hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 01342 &dw, cp, RSTRING_PTR(vstr), &len, pw, &size); 01343 if (FAILED(hr)) { 01344 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp); 01345 } 01346 #endif 01347 return pw; 01348 } 01349 size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0); 01350 pw = SysAllocStringLen(NULL, size); 01351 MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size); 01352 return pw; 01353 } 01354 01355 static LPWSTR 01356 ole_mb2wc(char *pm, int len) 01357 { 01358 UINT size = 0; 01359 LPWSTR pw; 01360 01361 if (conv_51932(cWIN32OLE_cp)) { 01362 #ifndef pIMultiLanguage 01363 DWORD dw = 0; 01364 UINT n = len; 01365 HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 01366 &dw, cWIN32OLE_cp, pm, &n, NULL, &size); 01367 if (FAILED(hr)) { 01368 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp); 01369 } 01370 pw = SysAllocStringLen(NULL, size); 01371 hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, 01372 &dw, cWIN32OLE_cp, pm, &n, pw, &size); 01373 if (FAILED(hr)) { 01374 ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp); 01375 } 01376 #endif 01377 return pw; 01378 } 01379 size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0); 01380 pw = SysAllocStringLen(NULL, size - 1); 01381 MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size); 01382 return pw; 01383 } 01384 01385 static VALUE 01386 ole_wc2vstr(LPWSTR pw, BOOL isfree) 01387 { 01388 char *p = ole_wc2mb(pw); 01389 VALUE vstr = rb_enc_str_new(p, strlen(p), cWIN32OLE_enc); 01390 if(isfree) 01391 SysFreeString(pw); 01392 free(p); 01393 return vstr; 01394 } 01395 01396 static VALUE 01397 ole_ary_m_entry(VALUE val, long *pid) 01398 { 01399 VALUE obj = Qnil; 01400 int i = 0; 01401 obj = val; 01402 while(TYPE(obj) == T_ARRAY) { 01403 obj = rb_ary_entry(obj, pid[i]); 01404 i++; 01405 } 01406 return obj; 01407 } 01408 01409 static void * 01410 get_ptr_of_variant(VARIANT *pvar) 01411 { 01412 switch(V_VT(pvar)) { 01413 case VT_UI1: 01414 return &V_UI1(pvar); 01415 break; 01416 case VT_I2: 01417 return &V_I2(pvar); 01418 break; 01419 case VT_UI2: 01420 return &V_UI2(pvar); 01421 break; 01422 case VT_I4: 01423 return &V_I4(pvar); 01424 break; 01425 case VT_UI4: 01426 return &V_UI4(pvar); 01427 break; 01428 case VT_R4: 01429 return &V_R4(pvar); 01430 break; 01431 case VT_R8: 01432 return &V_R8(pvar); 01433 break; 01434 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 01435 case VT_I8: 01436 return &V_I8(pvar); 01437 break; 01438 case VT_UI8: 01439 return &V_UI8(pvar); 01440 break; 01441 #endif 01442 case VT_INT: 01443 return &V_INT(pvar); 01444 break; 01445 case VT_UINT: 01446 return &V_UINT(pvar); 01447 break; 01448 case VT_CY: 01449 return &V_CY(pvar); 01450 break; 01451 case VT_DATE: 01452 return &V_DATE(pvar); 01453 break; 01454 case VT_BSTR: 01455 return V_BSTR(pvar); 01456 break; 01457 case VT_DISPATCH: 01458 return V_DISPATCH(pvar); 01459 break; 01460 case VT_ERROR: 01461 return &V_ERROR(pvar); 01462 break; 01463 case VT_BOOL: 01464 return &V_BOOL(pvar); 01465 break; 01466 case VT_UNKNOWN: 01467 return V_UNKNOWN(pvar); 01468 break; 01469 case VT_ARRAY: 01470 return &V_ARRAY(pvar); 01471 break; 01472 default: 01473 return NULL; 01474 break; 01475 } 01476 } 01477 01478 static VALUE 01479 is_all_index_under(long *pid, long *pub, long dim) 01480 { 01481 long i = 0; 01482 for (i = 0; i < dim; i++) { 01483 if (pid[i] > pub[i]) { 01484 return Qfalse; 01485 } 01486 } 01487 return Qtrue; 01488 } 01489 01490 static void 01491 ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt) 01492 { 01493 VALUE val1; 01494 HRESULT hr = S_OK; 01495 VARIANT var; 01496 VOID *p = NULL; 01497 long i = n; 01498 while(i >= 0) { 01499 val1 = ole_ary_m_entry(val, pid); 01500 VariantInit(&var); 01501 p = val2variant_ptr(val1, &var, vt); 01502 if (is_all_index_under(pid, pub, dim) == Qtrue) { 01503 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || 01504 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { 01505 rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface"); 01506 } 01507 hr = SafeArrayPutElement(psa, pid, p); 01508 } 01509 if (FAILED(hr)) { 01510 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement"); 01511 } 01512 pid[i] += 1; 01513 if (pid[i] > pub[i]) { 01514 pid[i] = 0; 01515 i -= 1; 01516 } else { 01517 i = dim - 1; 01518 } 01519 } 01520 } 01521 01522 static long 01523 dimension(VALUE val) { 01524 long dim = 0; 01525 long dim1 = 0; 01526 long len = 0; 01527 long i = 0; 01528 if (TYPE(val) == T_ARRAY) { 01529 len = RARRAY_LEN(val); 01530 for (i = 0; i < len; i++) { 01531 dim1 = dimension(rb_ary_entry(val, i)); 01532 if (dim < dim1) { 01533 dim = dim1; 01534 } 01535 } 01536 dim += 1; 01537 } 01538 return dim; 01539 } 01540 01541 static long 01542 ary_len_of_dim(VALUE ary, long dim) { 01543 long ary_len = 0; 01544 long ary_len1 = 0; 01545 long len = 0; 01546 long i = 0; 01547 VALUE val; 01548 if (dim == 0) { 01549 if (TYPE(ary) == T_ARRAY) { 01550 ary_len = RARRAY_LEN(ary); 01551 } 01552 } else { 01553 if (TYPE(ary) == T_ARRAY) { 01554 len = RARRAY_LEN(ary); 01555 for (i = 0; i < len; i++) { 01556 val = rb_ary_entry(ary, i); 01557 ary_len1 = ary_len_of_dim(val, dim-1); 01558 if (ary_len < ary_len1) { 01559 ary_len = ary_len1; 01560 } 01561 } 01562 } 01563 } 01564 return ary_len; 01565 } 01566 01567 static HRESULT 01568 ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt) 01569 { 01570 long dim = 0; 01571 int i = 0; 01572 HRESULT hr = S_OK; 01573 01574 SAFEARRAYBOUND *psab = NULL; 01575 SAFEARRAY *psa = NULL; 01576 long *pub, *pid; 01577 01578 Check_Type(val, T_ARRAY); 01579 01580 dim = dimension(val); 01581 01582 psab = ALLOC_N(SAFEARRAYBOUND, dim); 01583 pub = ALLOC_N(long, dim); 01584 pid = ALLOC_N(long, dim); 01585 01586 if(!psab || !pub || !pid) { 01587 if(pub) free(pub); 01588 if(psab) free(psab); 01589 if(pid) free(pid); 01590 rb_raise(rb_eRuntimeError, "memory allocation error"); 01591 } 01592 01593 for (i = 0; i < dim; i++) { 01594 psab[i].cElements = ary_len_of_dim(val, i); 01595 psab[i].lLbound = 0; 01596 pub[i] = psab[i].cElements - 1; 01597 pid[i] = 0; 01598 } 01599 /* Create and fill VARIANT array */ 01600 if ((vt & ~VT_BYREF) == VT_ARRAY) { 01601 vt = (vt | VT_VARIANT); 01602 } 01603 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); 01604 if (psa == NULL) 01605 hr = E_OUTOFMEMORY; 01606 else 01607 hr = SafeArrayLock(psa); 01608 if (SUCCEEDED(hr)) { 01609 ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK)); 01610 hr = SafeArrayUnlock(psa); 01611 } 01612 01613 if(pub) free(pub); 01614 if(psab) free(psab); 01615 if(pid) free(pid); 01616 01617 if (SUCCEEDED(hr)) { 01618 V_VT(var) = vt; 01619 V_ARRAY(var) = psa; 01620 } 01621 else { 01622 if (psa != NULL) 01623 SafeArrayDestroy(psa); 01624 } 01625 return hr; 01626 } 01627 01628 static void 01629 ole_val2variant(VALUE val, VARIANT *var) 01630 { 01631 struct oledata *pole; 01632 struct olevariantdata *pvar; 01633 if(rb_obj_is_kind_of(val, cWIN32OLE)) { 01634 Data_Get_Struct(val, struct oledata, pole); 01635 OLE_ADDREF(pole->pDispatch); 01636 V_VT(var) = VT_DISPATCH; 01637 V_DISPATCH(var) = pole->pDispatch; 01638 return; 01639 } 01640 if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) { 01641 Data_Get_Struct(val, struct olevariantdata, pvar); 01642 VariantCopy(var, &(pvar->var)); 01643 return; 01644 } 01645 01646 if (rb_obj_is_kind_of(val, rb_cTime)) { 01647 V_VT(var) = VT_DATE; 01648 V_DATE(var) = rbtime2vtdate(val); 01649 return; 01650 } 01651 switch (TYPE(val)) { 01652 case T_ARRAY: 01653 ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY); 01654 break; 01655 case T_STRING: 01656 V_VT(var) = VT_BSTR; 01657 V_BSTR(var) = ole_vstr2wc(val); 01658 break; 01659 case T_FIXNUM: 01660 V_VT(var) = VT_I4; 01661 V_I4(var) = NUM2INT(val); 01662 break; 01663 case T_BIGNUM: 01664 V_VT(var) = VT_R8; 01665 V_R8(var) = rb_big2dbl(val); 01666 break; 01667 case T_FLOAT: 01668 V_VT(var) = VT_R8; 01669 V_R8(var) = NUM2DBL(val); 01670 break; 01671 case T_TRUE: 01672 V_VT(var) = VT_BOOL; 01673 V_BOOL(var) = VARIANT_TRUE; 01674 break; 01675 case T_FALSE: 01676 V_VT(var) = VT_BOOL; 01677 V_BOOL(var) = VARIANT_FALSE; 01678 break; 01679 case T_NIL: 01680 if (g_nil_to == VT_ERROR) { 01681 V_VT(var) = VT_ERROR; 01682 V_ERROR(var) = DISP_E_PARAMNOTFOUND; 01683 }else { 01684 V_VT(var) = VT_EMPTY; 01685 } 01686 break; 01687 default: 01688 V_VT(var) = VT_DISPATCH; 01689 V_DISPATCH(var) = val2dispatch(val); 01690 break; 01691 } 01692 } 01693 01694 static void 01695 ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt) 01696 { 01697 if (val == Qnil) { 01698 if (vt == VT_VARIANT) { 01699 ole_val2variant2(val, var); 01700 } else { 01701 V_VT(var) = (vt & ~VT_BYREF); 01702 if (V_VT(var) == VT_DISPATCH) { 01703 V_DISPATCH(var) = NULL; 01704 } else if (V_VT(var) == VT_UNKNOWN) { 01705 V_UNKNOWN(var) = NULL; 01706 } 01707 } 01708 return; 01709 } 01710 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 01711 switch(vt & ~VT_BYREF) { 01712 case VT_I8: 01713 V_VT(var) = VT_I8; 01714 V_I8(var) = NUM2I8 (val); 01715 break; 01716 case VT_UI8: 01717 V_VT(var) = VT_UI8; 01718 V_UI8(var) = NUM2UI8(val); 01719 break; 01720 default: 01721 ole_val2variant2(val, var); 01722 break; 01723 } 01724 #else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ 01725 ole_val2variant2(val, var); 01726 #endif 01727 } 01728 01729 static void 01730 ole_val2ptr_variant(VALUE val, VARIANT *var) 01731 { 01732 switch (TYPE(val)) { 01733 case T_STRING: 01734 if (V_VT(var) == (VT_BSTR | VT_BYREF)) { 01735 *V_BSTRREF(var) = ole_vstr2wc(val); 01736 } 01737 break; 01738 case T_FIXNUM: 01739 switch(V_VT(var)) { 01740 case (VT_UI1 | VT_BYREF) : 01741 *V_UI1REF(var) = NUM2CHR(val); 01742 break; 01743 case (VT_I2 | VT_BYREF) : 01744 *V_I2REF(var) = (short)NUM2INT(val); 01745 break; 01746 case (VT_I4 | VT_BYREF) : 01747 *V_I4REF(var) = NUM2INT(val); 01748 break; 01749 case (VT_R4 | VT_BYREF) : 01750 *V_R4REF(var) = (float)NUM2INT(val); 01751 break; 01752 case (VT_R8 | VT_BYREF) : 01753 *V_R8REF(var) = NUM2INT(val); 01754 break; 01755 default: 01756 break; 01757 } 01758 break; 01759 case T_FLOAT: 01760 switch(V_VT(var)) { 01761 case (VT_I2 | VT_BYREF) : 01762 *V_I2REF(var) = (short)NUM2INT(val); 01763 break; 01764 case (VT_I4 | VT_BYREF) : 01765 *V_I4REF(var) = NUM2INT(val); 01766 break; 01767 case (VT_R4 | VT_BYREF) : 01768 *V_R4REF(var) = (float)NUM2DBL(val); 01769 break; 01770 case (VT_R8 | VT_BYREF) : 01771 *V_R8REF(var) = NUM2DBL(val); 01772 break; 01773 default: 01774 break; 01775 } 01776 break; 01777 case T_BIGNUM: 01778 if (V_VT(var) == (VT_R8 | VT_BYREF)) { 01779 *V_R8REF(var) = rb_big2dbl(val); 01780 } 01781 break; 01782 case T_TRUE: 01783 if (V_VT(var) == (VT_BOOL | VT_BYREF)) { 01784 *V_BOOLREF(var) = VARIANT_TRUE; 01785 } 01786 break; 01787 case T_FALSE: 01788 if (V_VT(var) == (VT_BOOL | VT_BYREF)) { 01789 *V_BOOLREF(var) = VARIANT_FALSE; 01790 } 01791 break; 01792 default: 01793 break; 01794 } 01795 } 01796 01797 static void 01798 ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt) 01799 { 01800 V_VT(var) = vt; 01801 if (vt == (VT_VARIANT|VT_BYREF)) { 01802 V_VARIANTREF(var) = realvar; 01803 } else { 01804 if (V_VT(realvar) != (vt & ~VT_BYREF)) { 01805 rb_raise(eWIN32OLERuntimeError, "variant type mismatch"); 01806 } 01807 switch(vt & ~VT_BYREF) { 01808 case VT_I1: 01809 V_I1REF(var) = &V_I1(realvar); 01810 break; 01811 case VT_UI1: 01812 V_UI1REF(var) = &V_UI1(realvar); 01813 break; 01814 case VT_I2: 01815 V_I2REF(var) = &V_I2(realvar); 01816 break; 01817 case VT_UI2: 01818 V_UI2REF(var) = &V_UI2(realvar); 01819 break; 01820 case VT_I4: 01821 V_I4REF(var) = &V_I4(realvar); 01822 break; 01823 case VT_UI4: 01824 V_UI4REF(var) = &V_UI4(realvar); 01825 break; 01826 case VT_R4: 01827 V_R4REF(var) = &V_R4(realvar); 01828 break; 01829 case VT_R8: 01830 V_R8REF(var) = &V_R8(realvar); 01831 break; 01832 01833 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 01834 #ifdef V_I8REF 01835 case VT_I8: 01836 V_I8REF(var) = &V_I8(realvar); 01837 break; 01838 #endif 01839 #ifdef V_UI8REF 01840 case VT_UI8: 01841 V_UI8REF(var) = &V_UI8(realvar); 01842 break; 01843 #endif 01844 #endif 01845 case VT_INT: 01846 V_INTREF(var) = &V_INT(realvar); 01847 break; 01848 01849 case VT_UINT: 01850 V_UINTREF(var) = &V_UINT(realvar); 01851 break; 01852 01853 case VT_CY: 01854 V_CYREF(var) = &V_CY(realvar); 01855 break; 01856 case VT_DATE: 01857 V_DATEREF(var) = &V_DATE(realvar); 01858 break; 01859 case VT_BSTR: 01860 V_BSTRREF(var) = &V_BSTR(realvar); 01861 break; 01862 case VT_DISPATCH: 01863 V_DISPATCHREF(var) = &V_DISPATCH(realvar); 01864 break; 01865 case VT_ERROR: 01866 V_ERRORREF(var) = &V_ERROR(realvar); 01867 break; 01868 case VT_BOOL: 01869 V_BOOLREF(var) = &V_BOOL(realvar); 01870 break; 01871 case VT_UNKNOWN: 01872 V_UNKNOWNREF(var) = &V_UNKNOWN(realvar); 01873 break; 01874 case VT_ARRAY: 01875 V_ARRAYREF(var) = &V_ARRAY(realvar); 01876 break; 01877 default: 01878 rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt); 01879 break; 01880 } 01881 } 01882 } 01883 01884 static void 01885 ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar) 01886 { 01887 HRESULT hr = S_OK; 01888 01889 if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && TYPE(val) == T_STRING) { 01890 long len = RSTRING_LEN(val); 01891 void *pdest = NULL; 01892 SAFEARRAY *p = NULL; 01893 SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len); 01894 if (!psa) { 01895 rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector"); 01896 } 01897 hr = SafeArrayAccessData(psa, &pdest); 01898 if (SUCCEEDED(hr)) { 01899 memcpy(pdest, RSTRING_PTR(val), len); 01900 SafeArrayUnaccessData(psa); 01901 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); 01902 p = V_ARRAY(&(pvar->realvar)); 01903 if (p != NULL) { 01904 SafeArrayDestroy(p); 01905 } 01906 V_ARRAY(&(pvar->realvar)) = psa; 01907 if (vt & VT_BYREF) { 01908 V_VT(&(pvar->var)) = vt; 01909 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 01910 } else { 01911 hr = VariantCopy(&(pvar->var), &(pvar->realvar)); 01912 } 01913 } else { 01914 if (psa) 01915 SafeArrayDestroy(psa); 01916 } 01917 } else if (vt & VT_ARRAY) { 01918 if (val == Qnil) { 01919 V_VT(&(pvar->var)) = vt; 01920 if (vt & VT_BYREF) { 01921 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 01922 } 01923 } else { 01924 hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); 01925 if (SUCCEEDED(hr)) { 01926 if (vt & VT_BYREF) { 01927 V_VT(&(pvar->var)) = vt; 01928 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 01929 } else { 01930 hr = VariantCopy(&(pvar->var), &(pvar->realvar)); 01931 } 01932 } 01933 } 01934 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 01935 } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) { 01936 ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF)); 01937 ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF)); 01938 V_VT(&(pvar->var)) = vt; 01939 if (vt & VT_BYREF) { 01940 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 01941 } 01942 #endif 01943 } else { 01944 if (val == Qnil) { 01945 V_VT(&(pvar->var)) = vt; 01946 if (vt == (VT_BYREF | VT_VARIANT)) { 01947 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 01948 } else { 01949 V_VT(&(pvar->realvar)) = vt & ~VT_BYREF; 01950 if (vt & VT_BYREF) { 01951 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 01952 } 01953 } 01954 } else { 01955 ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); 01956 if (vt == (VT_BYREF | VT_VARIANT)) { 01957 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 01958 } else if (vt & VT_BYREF) { 01959 if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) { 01960 hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar), 01961 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); 01962 } 01963 if (SUCCEEDED(hr)) { 01964 ole_set_byref(&(pvar->realvar), &(pvar->var), vt); 01965 } 01966 } else { 01967 if (vt == V_VT(&(pvar->realvar))) { 01968 hr = VariantCopy(&(pvar->var), &(pvar->realvar)); 01969 } else { 01970 hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar), 01971 cWIN32OLE_lcid, 0, vt); 01972 } 01973 } 01974 } 01975 } 01976 if (FAILED(hr)) { 01977 ole_raise(hr, eWIN32OLERuntimeError, "failed to change type"); 01978 } 01979 } 01980 01981 static void 01982 ole_val2variant2(VALUE val, VARIANT *var) 01983 { 01984 g_nil_to = VT_EMPTY; 01985 ole_val2variant(val, var); 01986 g_nil_to = VT_ERROR; 01987 } 01988 01989 static VALUE 01990 make_inspect(const char *class_name, VALUE detail) 01991 { 01992 VALUE str; 01993 str = rb_str_new2("#<"); 01994 rb_str_cat2(str, class_name); 01995 rb_str_cat2(str, ":"); 01996 rb_str_concat(str, detail); 01997 rb_str_cat2(str, ">"); 01998 return str; 01999 } 02000 02001 static VALUE 02002 default_inspect(VALUE self, const char *class_name) 02003 { 02004 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0); 02005 return make_inspect(class_name, detail); 02006 } 02007 02008 static VALUE 02009 ole_set_member(VALUE self, IDispatch *dispatch) 02010 { 02011 struct oledata *pole; 02012 Data_Get_Struct(self, struct oledata, pole); 02013 if (pole->pDispatch) { 02014 OLE_RELEASE(pole->pDispatch); 02015 pole->pDispatch = NULL; 02016 } 02017 pole->pDispatch = dispatch; 02018 return self; 02019 } 02020 02021 02022 static VALUE 02023 fole_s_allocate(VALUE klass) 02024 { 02025 struct oledata *pole; 02026 VALUE obj; 02027 ole_initialize(); 02028 obj = Data_Make_Struct(klass,struct oledata,0,ole_free,pole); 02029 pole->pDispatch = NULL; 02030 return obj; 02031 } 02032 02033 static VALUE 02034 create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv) 02035 { 02036 VALUE obj = fole_s_allocate(klass); 02037 ole_set_member(obj, pDispatch); 02038 return obj; 02039 } 02040 02041 static VALUE 02042 ary_new_dim(VALUE myary, long *pid, long *plb, long dim) { 02043 long i; 02044 VALUE obj = Qnil; 02045 VALUE pobj = Qnil; 02046 long *ids = ALLOC_N(long, dim); 02047 if (!ids) { 02048 rb_raise(rb_eRuntimeError, "memory allocation error"); 02049 } 02050 for(i = 0; i < dim; i++) { 02051 ids[i] = pid[i] - plb[i]; 02052 } 02053 obj = myary; 02054 pobj = myary; 02055 for(i = 0; i < dim-1; i++) { 02056 obj = rb_ary_entry(pobj, ids[i]); 02057 if (obj == Qnil) { 02058 rb_ary_store(pobj, ids[i], rb_ary_new()); 02059 } 02060 obj = rb_ary_entry(pobj, ids[i]); 02061 pobj = obj; 02062 } 02063 if (ids) free(ids); 02064 return obj; 02065 } 02066 02067 static void 02068 ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val) { 02069 long id = pid[dim - 1] - plb[dim - 1]; 02070 VALUE obj = ary_new_dim(myary, pid, plb, dim); 02071 rb_ary_store(obj, id, val); 02072 } 02073 02074 static VALUE 02075 ole_variant2val(VARIANT *pvar) 02076 { 02077 VALUE obj = Qnil; 02078 HRESULT hr; 02079 while ( V_VT(pvar) == (VT_BYREF | VT_VARIANT) ) 02080 pvar = V_VARIANTREF(pvar); 02081 02082 if(V_ISARRAY(pvar)) { 02083 SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar); 02084 UINT i = 0; 02085 long *pid, *plb, *pub; 02086 VARIANT variant; 02087 VALUE val; 02088 UINT dim = 0; 02089 if (!psa) { 02090 return obj; 02091 } 02092 dim = SafeArrayGetDim(psa); 02093 VariantInit(&variant); 02094 V_VT(&variant) = (V_VT(pvar) & ~VT_ARRAY) | VT_BYREF; 02095 02096 pid = ALLOC_N(long, dim); 02097 plb = ALLOC_N(long, dim); 02098 pub = ALLOC_N(long, dim); 02099 02100 if(!pid || !plb || !pub) { 02101 if(pid) free(pid); 02102 if(plb) free(plb); 02103 if(pub) free(pub); 02104 rb_raise(rb_eRuntimeError, "memory allocation error"); 02105 } 02106 02107 for(i = 0; i < dim; ++i) { 02108 SafeArrayGetLBound(psa, i+1, &plb[i]); 02109 SafeArrayGetLBound(psa, i+1, &pid[i]); 02110 SafeArrayGetUBound(psa, i+1, &pub[i]); 02111 } 02112 hr = SafeArrayLock(psa); 02113 if (SUCCEEDED(hr)) { 02114 obj = rb_ary_new(); 02115 i = 0; 02116 while (i < dim) { 02117 ary_new_dim(obj, pid, plb, dim); 02118 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); 02119 if (SUCCEEDED(hr)) { 02120 val = ole_variant2val(&variant); 02121 ary_store_dim(obj, pid, plb, dim, val); 02122 } 02123 for (i = 0; i < dim; ++i) { 02124 if (++pid[i] <= pub[i]) 02125 break; 02126 pid[i] = plb[i]; 02127 } 02128 } 02129 SafeArrayUnlock(psa); 02130 } 02131 if(pid) free(pid); 02132 if(plb) free(plb); 02133 if(pub) free(pub); 02134 return obj; 02135 } 02136 switch(V_VT(pvar) & ~VT_BYREF){ 02137 case VT_EMPTY: 02138 break; 02139 case VT_NULL: 02140 break; 02141 case VT_I1: 02142 if(V_ISBYREF(pvar)) 02143 obj = INT2NUM((long)*V_I1REF(pvar)); 02144 else 02145 obj = INT2NUM((long)V_I1(pvar)); 02146 break; 02147 02148 case VT_UI1: 02149 if(V_ISBYREF(pvar)) 02150 obj = INT2NUM((long)*V_UI1REF(pvar)); 02151 else 02152 obj = INT2NUM((long)V_UI1(pvar)); 02153 break; 02154 02155 case VT_I2: 02156 if(V_ISBYREF(pvar)) 02157 obj = INT2NUM((long)*V_I2REF(pvar)); 02158 else 02159 obj = INT2NUM((long)V_I2(pvar)); 02160 break; 02161 02162 case VT_UI2: 02163 if(V_ISBYREF(pvar)) 02164 obj = INT2NUM((long)*V_UI2REF(pvar)); 02165 else 02166 obj = INT2NUM((long)V_UI2(pvar)); 02167 break; 02168 02169 case VT_I4: 02170 if(V_ISBYREF(pvar)) 02171 obj = INT2NUM((long)*V_I4REF(pvar)); 02172 else 02173 obj = INT2NUM((long)V_I4(pvar)); 02174 break; 02175 02176 case VT_UI4: 02177 if(V_ISBYREF(pvar)) 02178 obj = INT2NUM((long)*V_UI4REF(pvar)); 02179 else 02180 obj = INT2NUM((long)V_UI4(pvar)); 02181 break; 02182 02183 case VT_INT: 02184 if(V_ISBYREF(pvar)) 02185 obj = INT2NUM((long)*V_INTREF(pvar)); 02186 else 02187 obj = INT2NUM((long)V_INT(pvar)); 02188 break; 02189 02190 case VT_UINT: 02191 if(V_ISBYREF(pvar)) 02192 obj = INT2NUM((long)*V_UINTREF(pvar)); 02193 else 02194 obj = INT2NUM((long)V_UINT(pvar)); 02195 break; 02196 02197 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 02198 case VT_I8: 02199 if(V_ISBYREF(pvar)) 02200 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 02201 #ifdef V_I8REF 02202 obj = I8_2_NUM(*V_I8REF(pvar)); 02203 #endif 02204 #else 02205 obj = Qnil; 02206 #endif 02207 else 02208 obj = I8_2_NUM(V_I8(pvar)); 02209 break; 02210 case VT_UI8: 02211 if(V_ISBYREF(pvar)) 02212 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 02213 #ifdef V_UI8REF 02214 obj = UI8_2_NUM(*V_UI8REF(pvar)); 02215 #endif 02216 #else 02217 obj = Qnil; 02218 #endif 02219 else 02220 obj = UI8_2_NUM(V_UI8(pvar)); 02221 break; 02222 #endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ 02223 02224 case VT_R4: 02225 if(V_ISBYREF(pvar)) 02226 obj = rb_float_new(*V_R4REF(pvar)); 02227 else 02228 obj = rb_float_new(V_R4(pvar)); 02229 break; 02230 02231 case VT_R8: 02232 if(V_ISBYREF(pvar)) 02233 obj = rb_float_new(*V_R8REF(pvar)); 02234 else 02235 obj = rb_float_new(V_R8(pvar)); 02236 break; 02237 02238 case VT_BSTR: 02239 { 02240 if(V_ISBYREF(pvar)) 02241 obj = ole_wc2vstr(*V_BSTRREF(pvar), FALSE); 02242 else 02243 obj = ole_wc2vstr(V_BSTR(pvar), FALSE); 02244 break; 02245 } 02246 02247 case VT_ERROR: 02248 if(V_ISBYREF(pvar)) 02249 obj = INT2NUM(*V_ERRORREF(pvar)); 02250 else 02251 obj = INT2NUM(V_ERROR(pvar)); 02252 break; 02253 02254 case VT_BOOL: 02255 if (V_ISBYREF(pvar)) 02256 obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse); 02257 else 02258 obj = (V_BOOL(pvar) ? Qtrue : Qfalse); 02259 break; 02260 02261 case VT_DISPATCH: 02262 { 02263 IDispatch *pDispatch; 02264 02265 if (V_ISBYREF(pvar)) 02266 pDispatch = *V_DISPATCHREF(pvar); 02267 else 02268 pDispatch = V_DISPATCH(pvar); 02269 02270 if (pDispatch != NULL ) { 02271 OLE_ADDREF(pDispatch); 02272 obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 02273 } 02274 break; 02275 } 02276 02277 case VT_UNKNOWN: 02278 { 02279 /* get IDispatch interface from IUnknown interface */ 02280 IUnknown *punk; 02281 IDispatch *pDispatch; 02282 void *p; 02283 HRESULT hr; 02284 02285 if (V_ISBYREF(pvar)) 02286 punk = *V_UNKNOWNREF(pvar); 02287 else 02288 punk = V_UNKNOWN(pvar); 02289 02290 if(punk != NULL) { 02291 hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p); 02292 if(SUCCEEDED(hr)) { 02293 pDispatch = p; 02294 obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 02295 } 02296 } 02297 break; 02298 } 02299 02300 case VT_DATE: 02301 { 02302 DATE date; 02303 if(V_ISBYREF(pvar)) 02304 date = *V_DATEREF(pvar); 02305 else 02306 date = V_DATE(pvar); 02307 02308 obj = vtdate2rbtime(date); 02309 break; 02310 } 02311 case VT_CY: 02312 default: 02313 { 02314 HRESULT hr; 02315 VARIANT variant; 02316 VariantInit(&variant); 02317 hr = VariantChangeTypeEx(&variant, pvar, 02318 cWIN32OLE_lcid, 0, VT_BSTR); 02319 if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) { 02320 obj = ole_wc2vstr(V_BSTR(&variant), FALSE); 02321 } 02322 VariantClear(&variant); 02323 break; 02324 } 02325 } 02326 return obj; 02327 } 02328 02329 static LONG 02330 reg_open_key(HKEY hkey, const char *name, HKEY *phkey) 02331 { 02332 return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey); 02333 } 02334 02335 static LONG 02336 reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey) 02337 { 02338 return reg_open_key(hkey, StringValuePtr(key), phkey); 02339 } 02340 02341 static VALUE 02342 reg_enum_key(HKEY hkey, DWORD i) 02343 { 02344 char buf[BUFSIZ + 1]; 02345 DWORD size_buf = sizeof(buf); 02346 FILETIME ft; 02347 LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf, 02348 NULL, NULL, NULL, &ft); 02349 if(err == ERROR_SUCCESS) { 02350 buf[BUFSIZ] = '\0'; 02351 return rb_str_new2(buf); 02352 } 02353 return Qnil; 02354 } 02355 02356 static VALUE 02357 reg_get_val(HKEY hkey, const char *subkey) 02358 { 02359 char *pbuf; 02360 DWORD dwtype = 0; 02361 DWORD size = 0; 02362 VALUE val = Qnil; 02363 LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size); 02364 02365 if (err == ERROR_SUCCESS) { 02366 pbuf = ALLOC_N(char, size + 1); 02367 err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, (BYTE *)pbuf, &size); 02368 if (err == ERROR_SUCCESS) { 02369 pbuf[size] = '\0'; 02370 if (dwtype == REG_EXPAND_SZ) { 02371 char* pbuf2 = (char *)pbuf; 02372 DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0); 02373 pbuf = ALLOC_N(char, len + 1); 02374 ExpandEnvironmentStrings(pbuf2, pbuf, len + 1); 02375 free(pbuf2); 02376 } 02377 val = rb_str_new2((char *)pbuf); 02378 } 02379 free(pbuf); 02380 } 02381 return val; 02382 } 02383 02384 static VALUE 02385 reg_get_val2(HKEY hkey, const char *subkey) 02386 { 02387 HKEY hsubkey; 02388 LONG err; 02389 VALUE val = Qnil; 02390 err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey); 02391 if (err == ERROR_SUCCESS) { 02392 val = reg_get_val(hsubkey, NULL); 02393 RegCloseKey(hsubkey); 02394 } 02395 if (val == Qnil) { 02396 val = reg_get_val(hkey, subkey); 02397 } 02398 return val; 02399 } 02400 02401 static VALUE 02402 reg_get_typelib_file_path(HKEY hkey) 02403 { 02404 VALUE path = Qnil; 02405 path = reg_get_val2(hkey, "win64"); 02406 if (path != Qnil) { 02407 return path; 02408 } 02409 path = reg_get_val2(hkey, "win32"); 02410 if (path != Qnil) { 02411 return path; 02412 } 02413 path = reg_get_val2(hkey, "win16"); 02414 return path; 02415 } 02416 02417 static VALUE 02418 typelib_file_from_clsid(VALUE ole) 02419 { 02420 HKEY hroot, hclsid; 02421 LONG err; 02422 VALUE typelib; 02423 char path[MAX_PATH + 1]; 02424 02425 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot); 02426 if (err != ERROR_SUCCESS) { 02427 return Qnil; 02428 } 02429 err = reg_open_key(hroot, StringValuePtr(ole), &hclsid); 02430 if (err != ERROR_SUCCESS) { 02431 RegCloseKey(hroot); 02432 return Qnil; 02433 } 02434 typelib = reg_get_val2(hclsid, "InprocServer32"); 02435 RegCloseKey(hroot); 02436 RegCloseKey(hclsid); 02437 if (typelib != Qnil) { 02438 ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path)); 02439 path[MAX_PATH] = '\0'; 02440 typelib = rb_str_new2(path); 02441 } 02442 return typelib; 02443 } 02444 02445 static VALUE 02446 typelib_file_from_typelib(VALUE ole) 02447 { 02448 HKEY htypelib, hclsid, hversion, hlang; 02449 double fver; 02450 DWORD i, j, k; 02451 LONG err; 02452 BOOL found = FALSE; 02453 VALUE typelib; 02454 VALUE file = Qnil; 02455 VALUE clsid; 02456 VALUE ver; 02457 VALUE lang; 02458 02459 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 02460 if(err != ERROR_SUCCESS) { 02461 return Qnil; 02462 } 02463 for(i = 0; !found; i++) { 02464 clsid = reg_enum_key(htypelib, i); 02465 if (clsid == Qnil) 02466 break; 02467 err = reg_open_vkey(htypelib, clsid, &hclsid); 02468 if (err != ERROR_SUCCESS) 02469 continue; 02470 fver = 0; 02471 for(j = 0; !found; j++) { 02472 ver = reg_enum_key(hclsid, j); 02473 if (ver == Qnil) 02474 break; 02475 err = reg_open_vkey(hclsid, ver, &hversion); 02476 if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver))) 02477 continue; 02478 fver = atof(StringValuePtr(ver)); 02479 typelib = reg_get_val(hversion, NULL); 02480 if (typelib == Qnil) 02481 continue; 02482 if (rb_str_cmp(typelib, ole) == 0) { 02483 for(k = 0; !found; k++) { 02484 lang = reg_enum_key(hversion, k); 02485 if (lang == Qnil) 02486 break; 02487 err = reg_open_vkey(hversion, lang, &hlang); 02488 if (err == ERROR_SUCCESS) { 02489 if ((file = reg_get_typelib_file_path(hlang)) != Qnil) 02490 found = TRUE; 02491 RegCloseKey(hlang); 02492 } 02493 } 02494 } 02495 RegCloseKey(hversion); 02496 } 02497 RegCloseKey(hclsid); 02498 } 02499 RegCloseKey(htypelib); 02500 return file; 02501 } 02502 02503 static VALUE 02504 typelib_file(VALUE ole) 02505 { 02506 VALUE file = typelib_file_from_clsid(ole); 02507 if (file != Qnil) { 02508 return file; 02509 } 02510 return typelib_file_from_typelib(ole); 02511 } 02512 02513 static void 02514 ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self) 02515 { 02516 unsigned int count; 02517 unsigned int index; 02518 int iVar; 02519 ITypeInfo *pTypeInfo; 02520 TYPEATTR *pTypeAttr; 02521 VARDESC *pVarDesc; 02522 HRESULT hr; 02523 unsigned int len; 02524 BSTR bstr; 02525 char *pName = NULL; 02526 VALUE val; 02527 VALUE constant; 02528 ID id; 02529 constant = rb_hash_new(); 02530 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 02531 for (index = 0; index < count; index++) { 02532 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo); 02533 if (FAILED(hr)) 02534 continue; 02535 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 02536 if(FAILED(hr)) { 02537 OLE_RELEASE(pTypeInfo); 02538 continue; 02539 } 02540 for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) { 02541 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc); 02542 if(FAILED(hr)) 02543 continue; 02544 if(pVarDesc->varkind == VAR_CONST && 02545 !(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | 02546 VARFLAG_FRESTRICTED | 02547 VARFLAG_FNONBROWSABLE))) { 02548 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 02549 1, &len); 02550 if(FAILED(hr) || len == 0 || !bstr) 02551 continue; 02552 pName = ole_wc2mb(bstr); 02553 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); 02554 *pName = toupper((int)*pName); 02555 id = rb_intern(pName); 02556 if (rb_is_const_id(id)) { 02557 rb_define_const(klass, pName, val); 02558 } 02559 else { 02560 rb_hash_aset(constant, rb_str_new2(pName), val); 02561 } 02562 SysFreeString(bstr); 02563 if(pName) { 02564 free(pName); 02565 pName = NULL; 02566 } 02567 } 02568 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 02569 } 02570 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); 02571 OLE_RELEASE(pTypeInfo); 02572 } 02573 rb_define_const(klass, "CONSTANTS", constant); 02574 } 02575 02576 static HRESULT 02577 clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid) 02578 { 02579 HKEY hlm; 02580 HKEY hpid; 02581 VALUE subkey; 02582 LONG err; 02583 char clsid[100]; 02584 OLECHAR *pbuf; 02585 DWORD len; 02586 DWORD dwtype; 02587 HRESULT hr = S_OK; 02588 err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm); 02589 if (err != ERROR_SUCCESS) 02590 return HRESULT_FROM_WIN32(err); 02591 subkey = rb_str_new2("SOFTWARE\\Classes\\"); 02592 rb_str_concat(subkey, com); 02593 rb_str_cat2(subkey, "\\CLSID"); 02594 err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid); 02595 if (err != ERROR_SUCCESS) 02596 hr = HRESULT_FROM_WIN32(err); 02597 else { 02598 len = sizeof(clsid); 02599 err = RegQueryValueEx(hpid, "", NULL, &dwtype, (BYTE *)clsid, &len); 02600 if (err == ERROR_SUCCESS && dwtype == REG_SZ) { 02601 pbuf = ole_mb2wc(clsid, -1); 02602 hr = CLSIDFromString(pbuf, pclsid); 02603 SysFreeString(pbuf); 02604 } 02605 else { 02606 hr = HRESULT_FROM_WIN32(err); 02607 } 02608 RegCloseKey(hpid); 02609 } 02610 RegCloseKey(hlm); 02611 return hr; 02612 } 02613 02614 static VALUE 02615 ole_create_dcom(int argc, VALUE *argv, VALUE self) 02616 { 02617 VALUE ole, host, others; 02618 HRESULT hr; 02619 CLSID clsid; 02620 OLECHAR *pbuf; 02621 02622 COSERVERINFO serverinfo; 02623 MULTI_QI multi_qi; 02624 DWORD clsctx = CLSCTX_REMOTE_SERVER; 02625 02626 if (!gole32) 02627 gole32 = LoadLibrary("OLE32"); 02628 if (!gole32) 02629 rb_raise(rb_eRuntimeError, "failed to load OLE32"); 02630 if (!gCoCreateInstanceEx) 02631 gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*) 02632 GetProcAddress(gole32, "CoCreateInstanceEx"); 02633 if (!gCoCreateInstanceEx) 02634 rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment"); 02635 rb_scan_args(argc, argv, "2*", &ole, &host, &others); 02636 02637 pbuf = ole_vstr2wc(ole); 02638 hr = CLSIDFromProgID(pbuf, &clsid); 02639 if (FAILED(hr)) 02640 hr = clsid_from_remote(host, ole, &clsid); 02641 if (FAILED(hr)) 02642 hr = CLSIDFromString(pbuf, &clsid); 02643 SysFreeString(pbuf); 02644 if (FAILED(hr)) 02645 ole_raise(hr, eWIN32OLERuntimeError, 02646 "unknown OLE server: `%s'", 02647 StringValuePtr(ole)); 02648 memset(&serverinfo, 0, sizeof(COSERVERINFO)); 02649 serverinfo.pwszName = ole_vstr2wc(host); 02650 memset(&multi_qi, 0, sizeof(MULTI_QI)); 02651 multi_qi.pIID = &IID_IDispatch; 02652 hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi); 02653 SysFreeString(serverinfo.pwszName); 02654 if (FAILED(hr)) 02655 ole_raise(hr, eWIN32OLERuntimeError, 02656 "failed to create DCOM server `%s' in `%s'", 02657 StringValuePtr(ole), 02658 StringValuePtr(host)); 02659 02660 ole_set_member(self, (IDispatch*)multi_qi.pItf); 02661 return self; 02662 } 02663 02664 static VALUE 02665 ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self) 02666 { 02667 IBindCtx *pBindCtx; 02668 IMoniker *pMoniker; 02669 IDispatch *pDispatch; 02670 void *p; 02671 HRESULT hr; 02672 OLECHAR *pbuf; 02673 ULONG eaten = 0; 02674 02675 ole_initialize(); 02676 02677 hr = CreateBindCtx(0, &pBindCtx); 02678 if(FAILED(hr)) { 02679 ole_raise(hr, eWIN32OLERuntimeError, 02680 "failed to create bind context"); 02681 } 02682 02683 pbuf = ole_vstr2wc(moniker); 02684 hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker); 02685 SysFreeString(pbuf); 02686 if(FAILED(hr)) { 02687 OLE_RELEASE(pBindCtx); 02688 ole_raise(hr, eWIN32OLERuntimeError, 02689 "failed to parse display name of moniker `%s'", 02690 StringValuePtr(moniker)); 02691 } 02692 hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, 02693 &IID_IDispatch, &p); 02694 pDispatch = p; 02695 OLE_RELEASE(pMoniker); 02696 OLE_RELEASE(pBindCtx); 02697 02698 if(FAILED(hr)) { 02699 ole_raise(hr, eWIN32OLERuntimeError, 02700 "failed to bind moniker `%s'", 02701 StringValuePtr(moniker)); 02702 } 02703 return create_win32ole_object(self, pDispatch, argc, argv); 02704 } 02705 02706 /* 02707 * call-seq: 02708 * WIN32OLE.connect( ole ) --> aWIN32OLE 02709 * 02710 * Returns running OLE Automation object or WIN32OLE object from moniker. 02711 * 1st argument should be OLE program id or class id or moniker. 02712 * 02713 * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel. 02714 */ 02715 static VALUE 02716 fole_s_connect(int argc, VALUE *argv, VALUE self) 02717 { 02718 VALUE svr_name; 02719 VALUE others; 02720 HRESULT hr; 02721 CLSID clsid; 02722 OLECHAR *pBuf; 02723 IDispatch *pDispatch; 02724 void *p; 02725 IUnknown *pUnknown; 02726 02727 rb_secure(4); 02728 /* initialize to use OLE */ 02729 ole_initialize(); 02730 02731 rb_scan_args(argc, argv, "1*", &svr_name, &others); 02732 SafeStringValue(svr_name); 02733 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { 02734 rb_raise(rb_eSecurityError, "Insecure Object Connection - %s", 02735 StringValuePtr(svr_name)); 02736 } 02737 02738 /* get CLSID from OLE server name */ 02739 pBuf = ole_vstr2wc(svr_name); 02740 hr = CLSIDFromProgID(pBuf, &clsid); 02741 if(FAILED(hr)) { 02742 hr = CLSIDFromString(pBuf, &clsid); 02743 } 02744 SysFreeString(pBuf); 02745 if(FAILED(hr)) { 02746 return ole_bind_obj(svr_name, argc, argv, self); 02747 } 02748 02749 hr = GetActiveObject(&clsid, 0, &pUnknown); 02750 if (FAILED(hr)) { 02751 ole_raise(hr, eWIN32OLERuntimeError, 02752 "OLE server `%s' not running", StringValuePtr(svr_name)); 02753 } 02754 hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p); 02755 pDispatch = p; 02756 if(FAILED(hr)) { 02757 OLE_RELEASE(pUnknown); 02758 ole_raise(hr, eWIN32OLERuntimeError, 02759 "failed to create WIN32OLE server `%s'", 02760 StringValuePtr(svr_name)); 02761 } 02762 02763 OLE_RELEASE(pUnknown); 02764 02765 return create_win32ole_object(self, pDispatch, argc, argv); 02766 } 02767 02768 /* 02769 * call-seq: 02770 * WIN32OLE.const_load( ole, mod = WIN32OLE) 02771 * 02772 * Defines the constants of OLE Automation server as mod's constants. 02773 * The first argument is WIN32OLE object or type library name. 02774 * If 2nd argument is omitted, the default is WIN32OLE. 02775 * The first letter of Ruby's constant variable name is upper case, 02776 * so constant variable name of WIN32OLE object is capitalized. 02777 * For example, the 'xlTop' constant of Excel is changed to 'XlTop' 02778 * in WIN32OLE. 02779 * If the first letter of constant variabl is not [A-Z], then 02780 * the constant is defined as CONSTANTS hash element. 02781 * 02782 * module EXCEL_CONST 02783 * end 02784 * excel = WIN32OLE.new('Excel.Application') 02785 * WIN32OLE.const_load(excel, EXCEL_CONST) 02786 * puts EXCEL_CONST::XlTop # => -4160 02787 * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541 02788 * 02789 * WIN32OLE.const_load(excel) 02790 * puts WIN32OLE::XlTop # => -4160 02791 * 02792 * module MSO 02793 * end 02794 * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO) 02795 * puts MSO::MsoLineSingle # => 1 02796 */ 02797 static VALUE 02798 fole_s_const_load(int argc, VALUE *argv, VALUE self) 02799 { 02800 VALUE ole; 02801 VALUE klass; 02802 struct oledata *pole; 02803 ITypeInfo *pTypeInfo; 02804 ITypeLib *pTypeLib; 02805 unsigned int index; 02806 HRESULT hr; 02807 OLECHAR *pBuf; 02808 VALUE file; 02809 LCID lcid = cWIN32OLE_lcid; 02810 02811 rb_secure(4); 02812 rb_scan_args(argc, argv, "11", &ole, &klass); 02813 if (TYPE(klass) != T_CLASS && 02814 TYPE(klass) != T_MODULE && 02815 TYPE(klass) != T_NIL) { 02816 rb_raise(rb_eTypeError, "2nd parameter must be Class or Module"); 02817 } 02818 if (rb_obj_is_kind_of(ole, cWIN32OLE)) { 02819 OLEData_Get_Struct(ole, pole); 02820 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 02821 0, lcid, &pTypeInfo); 02822 if(FAILED(hr)) { 02823 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 02824 } 02825 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); 02826 if(FAILED(hr)) { 02827 OLE_RELEASE(pTypeInfo); 02828 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); 02829 } 02830 OLE_RELEASE(pTypeInfo); 02831 if(TYPE(klass) != T_NIL) { 02832 ole_const_load(pTypeLib, klass, self); 02833 } 02834 else { 02835 ole_const_load(pTypeLib, cWIN32OLE, self); 02836 } 02837 OLE_RELEASE(pTypeLib); 02838 } 02839 else if(TYPE(ole) == T_STRING) { 02840 file = typelib_file(ole); 02841 if (file == Qnil) { 02842 file = ole; 02843 } 02844 pBuf = ole_vstr2wc(file); 02845 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib); 02846 SysFreeString(pBuf); 02847 if (FAILED(hr)) 02848 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); 02849 if(TYPE(klass) != T_NIL) { 02850 ole_const_load(pTypeLib, klass, self); 02851 } 02852 else { 02853 ole_const_load(pTypeLib, cWIN32OLE, self); 02854 } 02855 OLE_RELEASE(pTypeLib); 02856 } 02857 else { 02858 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance"); 02859 } 02860 return Qnil; 02861 } 02862 02863 static VALUE 02864 ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes) 02865 { 02866 02867 long count; 02868 int i; 02869 HRESULT hr; 02870 BSTR bstr; 02871 ITypeInfo *pTypeInfo; 02872 VALUE type; 02873 02874 rb_secure(4); 02875 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 02876 for (i = 0; i < count; i++) { 02877 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 02878 &bstr, NULL, NULL, NULL); 02879 if (FAILED(hr)) 02880 continue; 02881 02882 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 02883 if (FAILED(hr)) 02884 continue; 02885 02886 type = foletype_s_allocate(cWIN32OLE_TYPE); 02887 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr)); 02888 02889 rb_ary_push(classes, type); 02890 OLE_RELEASE(pTypeInfo); 02891 } 02892 return classes; 02893 } 02894 02895 static ULONG 02896 reference_count(struct oledata * pole) 02897 { 02898 ULONG n = 0; 02899 if(pole->pDispatch) { 02900 OLE_ADDREF(pole->pDispatch); 02901 n = OLE_RELEASE(pole->pDispatch); 02902 } 02903 return n; 02904 } 02905 02906 /* 02907 * call-seq: 02908 * WIN32OLE.ole_reference_count(aWIN32OLE) --> number 02909 * 02910 * Returns reference counter of Dispatch interface of WIN32OLE object. 02911 * You should not use this method because this method 02912 * exists only for debugging WIN32OLE. 02913 */ 02914 static VALUE 02915 fole_s_reference_count(VALUE self, VALUE obj) 02916 { 02917 struct oledata * pole; 02918 OLEData_Get_Struct(obj, pole); 02919 return INT2NUM(reference_count(pole)); 02920 } 02921 02922 /* 02923 * call-seq: 02924 * WIN32OLE.ole_free(aWIN32OLE) --> number 02925 * 02926 * Invokes Release method of Dispatch interface of WIN32OLE object. 02927 * You should not use this method because this method 02928 * exists only for debugging WIN32OLE. 02929 * The return value is reference counter of OLE object. 02930 */ 02931 static VALUE 02932 fole_s_free(VALUE self, VALUE obj) 02933 { 02934 ULONG n = 0; 02935 struct oledata * pole; 02936 OLEData_Get_Struct(obj, pole); 02937 if(pole->pDispatch) { 02938 if (reference_count(pole) > 0) { 02939 n = OLE_RELEASE(pole->pDispatch); 02940 } 02941 } 02942 return INT2NUM(n); 02943 } 02944 02945 static HWND 02946 ole_show_help(VALUE helpfile, VALUE helpcontext) 02947 { 02948 FNHTMLHELP *pfnHtmlHelp; 02949 HWND hwnd = 0; 02950 02951 if(!ghhctrl) 02952 ghhctrl = LoadLibrary("HHCTRL.OCX"); 02953 if (!ghhctrl) 02954 return hwnd; 02955 pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA"); 02956 if (!pfnHtmlHelp) 02957 return hwnd; 02958 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), 02959 0x0f, NUM2INT(helpcontext)); 02960 if (hwnd == 0) 02961 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), 02962 0, NUM2INT(helpcontext)); 02963 return hwnd; 02964 } 02965 02966 /* 02967 * call-seq: 02968 * WIN32OLE.ole_show_help(obj [,helpcontext]) 02969 * 02970 * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE 02971 * object or WIN32OLE_METHOD object or helpfile. 02972 * 02973 * excel = WIN32OLE.new('Excel.Application') 02974 * typeobj = excel.ole_type 02975 * WIN32OLE.ole_show_help(typeobj) 02976 */ 02977 static VALUE 02978 fole_s_show_help(int argc, VALUE *argv, VALUE self) 02979 { 02980 VALUE target; 02981 VALUE helpcontext; 02982 VALUE helpfile; 02983 VALUE name; 02984 HWND hwnd; 02985 rb_scan_args(argc, argv, "11", &target, &helpcontext); 02986 if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) || 02987 rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) { 02988 helpfile = rb_funcall(target, rb_intern("helpfile"), 0); 02989 if(strlen(StringValuePtr(helpfile)) == 0) { 02990 name = rb_ivar_get(target, rb_intern("name")); 02991 rb_raise(rb_eRuntimeError, "no helpfile of `%s'", 02992 StringValuePtr(name)); 02993 } 02994 helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0); 02995 } else { 02996 helpfile = target; 02997 } 02998 if (TYPE(helpfile) != T_STRING) { 02999 rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)"); 03000 } 03001 hwnd = ole_show_help(helpfile, helpcontext); 03002 if(hwnd == 0) { 03003 rb_raise(rb_eRuntimeError, "failed to open help file `%s'", 03004 StringValuePtr(helpfile)); 03005 } 03006 return Qnil; 03007 } 03008 03009 /* 03010 * call-seq: 03011 * WIN32OLE.codepage 03012 * 03013 * Returns current codepage. 03014 * WIN32OLE.codepage # => WIN32OLE::CP_ACP 03015 */ 03016 static VALUE 03017 fole_s_get_code_page(VALUE self) 03018 { 03019 return INT2FIX(cWIN32OLE_cp); 03020 } 03021 03022 static BOOL CALLBACK 03023 installed_code_page_proc(LPTSTR str) { 03024 if (strtoul(str, NULL, 10) == g_cp_to_check) { 03025 g_cp_installed = TRUE; 03026 return FALSE; 03027 } 03028 return TRUE; 03029 } 03030 03031 static BOOL 03032 code_page_installed(UINT cp) 03033 { 03034 g_cp_installed = FALSE; 03035 g_cp_to_check = cp; 03036 EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED); 03037 return g_cp_installed; 03038 } 03039 03040 /* 03041 * call-seq: 03042 * WIN32OLE.codepage = CP 03043 * 03044 * Sets current codepage. 03045 * The WIN32OLE.codepage is initialized according to 03046 * Encoding.default_internal. 03047 * If Encoding.default_internal is nil then WIN32OLE.codepage 03048 * is initialized according to Encoding.default_external. 03049 * 03050 * WIN32OLE.codepage = WIN32OLE::CP_UTF8 03051 * WIN32OLE.codepage = 65001 03052 */ 03053 static VALUE 03054 fole_s_set_code_page(VALUE self, VALUE vcp) 03055 { 03056 UINT cp = FIX2INT(vcp); 03057 set_ole_codepage(cp); 03058 /* 03059 * Should this method return old codepage? 03060 */ 03061 return Qnil; 03062 } 03063 03064 /* 03065 * call-seq: 03066 * WIN32OLE.locale -> locale id. 03067 * 03068 * Returns current locale id (lcid). The default locale is 03069 * LOCALE_SYSTEM_DEFAULT. 03070 * 03071 * lcid = WIN32OLE.locale 03072 */ 03073 static VALUE 03074 fole_s_get_locale(VALUE self) 03075 { 03076 return INT2FIX(cWIN32OLE_lcid); 03077 } 03078 03079 static BOOL 03080 CALLBACK installed_lcid_proc(LPTSTR str) 03081 { 03082 if (strcmp(str, g_lcid_to_check) == 0) { 03083 g_lcid_installed = TRUE; 03084 return FALSE; 03085 } 03086 return TRUE; 03087 } 03088 03089 static BOOL 03090 lcid_installed(LCID lcid) 03091 { 03092 g_lcid_installed = FALSE; 03093 snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", lcid); 03094 EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED); 03095 return g_lcid_installed; 03096 } 03097 03098 /* 03099 * call-seq: 03100 * WIN32OLE.locale = lcid 03101 * 03102 * Sets current locale id (lcid). 03103 * 03104 * WIN32OLE.locale = 1033 # set locale English(U.S) 03105 * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY) 03106 * 03107 */ 03108 static VALUE 03109 fole_s_set_locale(VALUE self, VALUE vlcid) 03110 { 03111 LCID lcid = FIX2INT(vlcid); 03112 if (lcid_installed(lcid)) { 03113 cWIN32OLE_lcid = lcid; 03114 } else { 03115 switch (lcid) { 03116 case LOCALE_SYSTEM_DEFAULT: 03117 case LOCALE_USER_DEFAULT: 03118 cWIN32OLE_lcid = lcid; 03119 break; 03120 default: 03121 rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid); 03122 } 03123 } 03124 return Qnil; 03125 } 03126 03127 /* 03128 * call-seq: 03129 * WIN32OLE.create_guid 03130 * 03131 * Creates GUID. 03132 * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8} 03133 */ 03134 static VALUE 03135 fole_s_create_guid(VALUE self) 03136 { 03137 GUID guid; 03138 HRESULT hr; 03139 OLECHAR bstr[80]; 03140 int len = 0; 03141 hr = CoCreateGuid(&guid); 03142 if (FAILED(hr)) { 03143 ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID"); 03144 } 03145 len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 03146 if (len == 0) { 03147 rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)"); 03148 } 03149 return ole_wc2vstr(bstr, FALSE); 03150 } 03151 03152 /* 03153 * WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize 03154 * are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634). 03155 * You must not use thease method. 03156 */ 03157 03158 /* :nodoc */ 03159 static VALUE 03160 fole_s_ole_initialize(VALUE self) 03161 { 03162 ole_initialize(); 03163 return Qnil; 03164 } 03165 03166 /* :nodoc */ 03167 static VALUE 03168 fole_s_ole_uninitialize(VALUE self) 03169 { 03170 ole_uninitialize(); 03171 return Qnil; 03172 } 03173 03174 /* 03175 * Document-class: WIN32OLE 03176 * 03177 * <code>WIN32OLE</code> objects represent OLE Automation object in Ruby. 03178 * 03179 * By using WIN32OLE, you can access OLE server like VBScript. 03180 * 03181 * Here is sample script. 03182 * 03183 * require 'win32ole' 03184 * 03185 * excel = WIN32OLE.new('Excel.Application') 03186 * excel.visible = true 03187 * workbook = excel.Workbooks.Add(); 03188 * worksheet = workbook.Worksheets(1); 03189 * worksheet.Range("A1:D1").value = ["North","South","East","West"]; 03190 * worksheet.Range("A2:B2").value = [5.2, 10]; 03191 * worksheet.Range("C2").value = 8; 03192 * worksheet.Range("D2").value = 20; 03193 * 03194 * range = worksheet.Range("A1:D2"); 03195 * range.select 03196 * chart = workbook.Charts.Add; 03197 * 03198 * workbook.saved = true; 03199 * 03200 * excel.ActiveWorkbook.Close(0); 03201 * excel.Quit(); 03202 * 03203 * Unfortunately, Win32OLE doesn't support the argument passed by 03204 * reference directly. 03205 * Instead, Win32OLE provides WIN32OLE::ARGV. 03206 * If you want to get the result value of argument passed by reference, 03207 * you can use WIN32OLE::ARGV. 03208 * 03209 * oleobj.method(arg1, arg2, refargv3) 03210 * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method 03211 * 03212 */ 03213 03214 /* 03215 * call-seq: 03216 * WIN32OLE.new(server, [host]) -> WIN32OLE object 03217 * 03218 * Returns a new WIN32OLE object(OLE Automation object). 03219 * The first argument server specifies OLE Automation server. 03220 * The first argument should be CLSID or PROGID. 03221 * If second argument host specified, then returns OLE Automation 03222 * object on host. 03223 * 03224 * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object. 03225 * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object. 03226 */ 03227 static VALUE 03228 fole_initialize(int argc, VALUE *argv, VALUE self) 03229 { 03230 VALUE svr_name; 03231 VALUE host; 03232 VALUE others; 03233 HRESULT hr; 03234 CLSID clsid; 03235 OLECHAR *pBuf; 03236 IDispatch *pDispatch; 03237 void *p; 03238 rb_secure(4); 03239 rb_call_super(0, 0); 03240 rb_scan_args(argc, argv, "11*", &svr_name, &host, &others); 03241 03242 SafeStringValue(svr_name); 03243 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { 03244 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s", 03245 StringValuePtr(svr_name)); 03246 } 03247 if (!NIL_P(host)) { 03248 SafeStringValue(host); 03249 if (rb_safe_level() > 0 && OBJ_TAINTED(host)) { 03250 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s", 03251 StringValuePtr(svr_name)); 03252 } 03253 return ole_create_dcom(argc, argv, self); 03254 } 03255 03256 /* get CLSID from OLE server name */ 03257 pBuf = ole_vstr2wc(svr_name); 03258 hr = CLSIDFromProgID(pBuf, &clsid); 03259 if(FAILED(hr)) { 03260 hr = CLSIDFromString(pBuf, &clsid); 03261 } 03262 SysFreeString(pBuf); 03263 if(FAILED(hr)) { 03264 ole_raise(hr, eWIN32OLERuntimeError, 03265 "unknown OLE server: `%s'", 03266 StringValuePtr(svr_name)); 03267 } 03268 03269 /* get IDispatch interface */ 03270 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 03271 &IID_IDispatch, &p); 03272 pDispatch = p; 03273 if(FAILED(hr)) { 03274 ole_raise(hr, eWIN32OLERuntimeError, 03275 "failed to create WIN32OLE object from `%s'", 03276 StringValuePtr(svr_name)); 03277 } 03278 03279 ole_set_member(self, pDispatch); 03280 return self; 03281 } 03282 03283 static VALUE 03284 hash2named_arg(VALUE pair, struct oleparam* pOp) 03285 { 03286 unsigned int index, i; 03287 VALUE key, value; 03288 index = pOp->dp.cNamedArgs; 03289 03290 /*--------------------------------------------- 03291 the data-type of key must be String or Symbol 03292 -----------------------------------------------*/ 03293 key = rb_ary_entry(pair, 0); 03294 if(TYPE(key) != T_STRING && TYPE(key) != T_SYMBOL) { 03295 /* clear name of dispatch parameters */ 03296 for(i = 1; i < index + 1; i++) { 03297 SysFreeString(pOp->pNamedArgs[i]); 03298 } 03299 /* clear dispatch parameters */ 03300 for(i = 0; i < index; i++ ) { 03301 VariantClear(&(pOp->dp.rgvarg[i])); 03302 } 03303 /* raise an exception */ 03304 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 03305 } 03306 if (TYPE(key) == T_SYMBOL) { 03307 key = rb_sym_to_s(key); 03308 } 03309 03310 /* pNamedArgs[0] is <method name>, so "index + 1" */ 03311 pOp->pNamedArgs[index + 1] = ole_vstr2wc(key); 03312 03313 value = rb_ary_entry(pair, 1); 03314 VariantInit(&(pOp->dp.rgvarg[index])); 03315 ole_val2variant(value, &(pOp->dp.rgvarg[index])); 03316 03317 pOp->dp.cNamedArgs += 1; 03318 return Qnil; 03319 } 03320 03321 static VALUE 03322 set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end) 03323 { 03324 VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV")); 03325 03326 Check_Type(argv, T_ARRAY); 03327 rb_ary_clear(argv); 03328 while (end-- > beg) { 03329 rb_ary_push(argv, ole_variant2val(&realargs[end])); 03330 VariantClear(&realargs[end]); 03331 } 03332 return argv; 03333 } 03334 03335 static VALUE 03336 ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket) 03337 { 03338 LCID lcid = cWIN32OLE_lcid; 03339 struct oledata *pole; 03340 HRESULT hr; 03341 VALUE cmd; 03342 VALUE paramS; 03343 VALUE param; 03344 VALUE obj; 03345 VALUE v; 03346 03347 BSTR wcmdname; 03348 03349 DISPID DispID; 03350 DISPID* pDispID; 03351 EXCEPINFO excepinfo; 03352 VARIANT result; 03353 VARIANTARG* realargs = NULL; 03354 unsigned int argErr = 0; 03355 unsigned int i; 03356 unsigned int cNamedArgs; 03357 int n; 03358 struct oleparam op; 03359 struct olevariantdata *pvar; 03360 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03361 03362 VariantInit(&result); 03363 03364 op.dp.rgvarg = NULL; 03365 op.dp.rgdispidNamedArgs = NULL; 03366 op.dp.cNamedArgs = 0; 03367 op.dp.cArgs = 0; 03368 03369 rb_scan_args(argc, argv, "1*", &cmd, ¶mS); 03370 if(TYPE(cmd) != T_STRING && TYPE(cmd) != T_SYMBOL && !is_bracket) { 03371 rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)"); 03372 } 03373 if (TYPE(cmd) == T_SYMBOL) { 03374 cmd = rb_sym_to_s(cmd); 03375 } 03376 OLEData_Get_Struct(self, pole); 03377 if(!pole->pDispatch) { 03378 rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); 03379 } 03380 if (is_bracket) { 03381 DispID = DISPID_VALUE; 03382 argc += 1; 03383 rb_ary_unshift(paramS, cmd); 03384 } else { 03385 wcmdname = ole_vstr2wc(cmd); 03386 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, 03387 &wcmdname, 1, lcid, &DispID); 03388 SysFreeString(wcmdname); 03389 if(FAILED(hr)) { 03390 ole_raise(hr, rb_eNoMethodError, 03391 "unknown property or method: `%s'", 03392 StringValuePtr(cmd)); 03393 } 03394 } 03395 03396 /* pick up last argument of method */ 03397 param = rb_ary_entry(paramS, argc-2); 03398 03399 op.dp.cNamedArgs = 0; 03400 03401 /* if last arg is hash object */ 03402 if(TYPE(param) == T_HASH) { 03403 /*------------------------------------------ 03404 hash object ==> named dispatch parameters 03405 --------------------------------------------*/ 03406 cNamedArgs = NUM2INT(rb_funcall(param, rb_intern("length"), 0)); 03407 op.dp.cArgs = cNamedArgs + argc - 2; 03408 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); 03409 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); 03410 rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op); 03411 03412 pDispID = ALLOCA_N(DISPID, cNamedArgs + 1); 03413 op.pNamedArgs[0] = ole_vstr2wc(cmd); 03414 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, 03415 &IID_NULL, 03416 op.pNamedArgs, 03417 op.dp.cNamedArgs + 1, 03418 lcid, pDispID); 03419 for(i = 0; i < op.dp.cNamedArgs + 1; i++) { 03420 SysFreeString(op.pNamedArgs[i]); 03421 op.pNamedArgs[i] = NULL; 03422 } 03423 if(FAILED(hr)) { 03424 /* clear dispatch parameters */ 03425 for(i = 0; i < op.dp.cArgs; i++ ) { 03426 VariantClear(&op.dp.rgvarg[i]); 03427 } 03428 ole_raise(hr, eWIN32OLERuntimeError, 03429 "failed to get named argument info: `%s'", 03430 StringValuePtr(cmd)); 03431 } 03432 op.dp.rgdispidNamedArgs = &(pDispID[1]); 03433 } 03434 else { 03435 cNamedArgs = 0; 03436 op.dp.cArgs = argc - 1; 03437 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); 03438 if (op.dp.cArgs > 0) { 03439 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); 03440 } 03441 } 03442 /*-------------------------------------- 03443 non hash args ==> dispatch parameters 03444 ----------------------------------------*/ 03445 if(op.dp.cArgs > cNamedArgs) { 03446 realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1); 03447 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03448 n = op.dp.cArgs - i + cNamedArgs - 1; 03449 VariantInit(&realargs[n]); 03450 VariantInit(&op.dp.rgvarg[n]); 03451 param = rb_ary_entry(paramS, i-cNamedArgs); 03452 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { 03453 Data_Get_Struct(param, struct olevariantdata, pvar); 03454 VariantCopy(&op.dp.rgvarg[n], &(pvar->var)); 03455 } else { 03456 ole_val2variant(param, &realargs[n]); 03457 V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF; 03458 V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n]; 03459 } 03460 } 03461 } 03462 /* apparent you need to call propput, you need this */ 03463 if (wFlags & DISPATCH_PROPERTYPUT) { 03464 if (op.dp.cArgs == 0) 03465 ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error"); 03466 03467 op.dp.cNamedArgs = 1; 03468 op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); 03469 op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; 03470 } 03471 03472 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03473 &IID_NULL, lcid, wFlags, &op.dp, 03474 &result, &excepinfo, &argErr); 03475 03476 if (FAILED(hr)) { 03477 /* retry to call args by value */ 03478 if(op.dp.cArgs >= cNamedArgs) { 03479 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03480 n = op.dp.cArgs - i + cNamedArgs - 1; 03481 param = rb_ary_entry(paramS, i-cNamedArgs); 03482 ole_val2variant(param, &op.dp.rgvarg[n]); 03483 } 03484 if (hr == DISP_E_EXCEPTION) { 03485 ole_freeexceptinfo(&excepinfo); 03486 } 03487 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03488 VariantInit(&result); 03489 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03490 &IID_NULL, lcid, wFlags, 03491 &op.dp, &result, 03492 &excepinfo, &argErr); 03493 03494 /* mega kludge. if a method in WORD is called and we ask 03495 * for a result when one is not returned then 03496 * hResult == DISP_E_EXCEPTION. this only happens on 03497 * functions whose DISPID > 0x8000 */ 03498 if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) { 03499 if (hr == DISP_E_EXCEPTION) { 03500 ole_freeexceptinfo(&excepinfo); 03501 } 03502 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03503 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03504 &IID_NULL, lcid, wFlags, 03505 &op.dp, NULL, 03506 &excepinfo, &argErr); 03507 03508 } 03509 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03510 n = op.dp.cArgs - i + cNamedArgs - 1; 03511 VariantClear(&op.dp.rgvarg[n]); 03512 } 03513 } 03514 03515 if (FAILED(hr)) { 03516 /* retry after converting nil to VT_EMPTY */ 03517 if (op.dp.cArgs > cNamedArgs) { 03518 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03519 n = op.dp.cArgs - i + cNamedArgs - 1; 03520 param = rb_ary_entry(paramS, i-cNamedArgs); 03521 ole_val2variant2(param, &op.dp.rgvarg[n]); 03522 } 03523 if (hr == DISP_E_EXCEPTION) { 03524 ole_freeexceptinfo(&excepinfo); 03525 } 03526 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03527 VariantInit(&result); 03528 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03529 &IID_NULL, lcid, wFlags, 03530 &op.dp, &result, 03531 &excepinfo, &argErr); 03532 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03533 n = op.dp.cArgs - i + cNamedArgs - 1; 03534 VariantClear(&op.dp.rgvarg[n]); 03535 } 03536 } 03537 } 03538 03539 } 03540 /* clear dispatch parameter */ 03541 if(op.dp.cArgs > cNamedArgs) { 03542 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03543 n = op.dp.cArgs - i + cNamedArgs - 1; 03544 param = rb_ary_entry(paramS, i-cNamedArgs); 03545 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { 03546 ole_val2variant(param, &realargs[n]); 03547 } 03548 } 03549 set_argv(realargs, cNamedArgs, op.dp.cArgs); 03550 } 03551 else { 03552 for(i = 0; i < op.dp.cArgs; i++) { 03553 VariantClear(&op.dp.rgvarg[i]); 03554 } 03555 } 03556 03557 if (FAILED(hr)) { 03558 v = ole_excepinfo2msg(&excepinfo); 03559 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s", 03560 StringValuePtr(cmd), 03561 StringValuePtr(v)); 03562 } 03563 obj = ole_variant2val(&result); 03564 VariantClear(&result); 03565 return obj; 03566 } 03567 03568 /* 03569 * call-seq: 03570 * WIN32OLE#invoke(method, [arg1,...]) => return value of method. 03571 * 03572 * Runs OLE method. 03573 * The first argument specifies the method name of OLE Automation object. 03574 * The others specify argument of the <i>method</i>. 03575 * If you can not execute <i>method</i> directly, then use this method instead. 03576 * 03577 * excel = WIN32OLE.new('Excel.Application') 03578 * excel.invoke('Quit') # => same as excel.Quit 03579 * 03580 */ 03581 static VALUE 03582 fole_invoke(int argc, VALUE *argv, VALUE self) 03583 { 03584 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); 03585 } 03586 03587 static VALUE 03588 ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind) 03589 { 03590 HRESULT hr; 03591 struct oledata *pole; 03592 unsigned int argErr = 0; 03593 EXCEPINFO excepinfo; 03594 VARIANT result; 03595 DISPPARAMS dispParams; 03596 VARIANTARG* realargs = NULL; 03597 int i, j; 03598 VALUE obj = Qnil; 03599 VALUE tp, param; 03600 VALUE v; 03601 VARTYPE vt; 03602 03603 Check_Type(args, T_ARRAY); 03604 Check_Type(types, T_ARRAY); 03605 03606 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03607 memset(&dispParams, 0, sizeof(DISPPARAMS)); 03608 VariantInit(&result); 03609 OLEData_Get_Struct(self, pole); 03610 03611 dispParams.cArgs = RARRAY_LEN(args); 03612 dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs); 03613 realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs); 03614 for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--) 03615 { 03616 VariantInit(&realargs[i]); 03617 VariantInit(&dispParams.rgvarg[i]); 03618 tp = rb_ary_entry(types, j); 03619 vt = (VARTYPE)FIX2INT(tp); 03620 V_VT(&dispParams.rgvarg[i]) = vt; 03621 param = rb_ary_entry(args, j); 03622 if (param == Qnil) 03623 { 03624 03625 V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR; 03626 V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND; 03627 } 03628 else 03629 { 03630 if (vt & VT_ARRAY) 03631 { 03632 int ent; 03633 LPBYTE pb; 03634 short* ps; 03635 LPLONG pl; 03636 VARIANT* pv; 03637 CY *py; 03638 VARTYPE v; 03639 SAFEARRAYBOUND rgsabound[1]; 03640 Check_Type(param, T_ARRAY); 03641 rgsabound[0].lLbound = 0; 03642 rgsabound[0].cElements = RARRAY_LEN(param); 03643 v = vt & ~(VT_ARRAY | VT_BYREF); 03644 V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound); 03645 V_VT(&realargs[i]) = VT_ARRAY | v; 03646 SafeArrayLock(V_ARRAY(&realargs[i])); 03647 pb = V_ARRAY(&realargs[i])->pvData; 03648 ps = V_ARRAY(&realargs[i])->pvData; 03649 pl = V_ARRAY(&realargs[i])->pvData; 03650 py = V_ARRAY(&realargs[i])->pvData; 03651 pv = V_ARRAY(&realargs[i])->pvData; 03652 for (ent = 0; ent < (int)rgsabound[0].cElements; ent++) 03653 { 03654 VARIANT velem; 03655 VALUE elem = rb_ary_entry(param, ent); 03656 ole_val2variant(elem, &velem); 03657 if (v != VT_VARIANT) 03658 { 03659 VariantChangeTypeEx(&velem, &velem, 03660 cWIN32OLE_lcid, 0, v); 03661 } 03662 switch (v) 03663 { 03664 /* 128 bits */ 03665 case VT_VARIANT: 03666 *pv++ = velem; 03667 break; 03668 /* 64 bits */ 03669 case VT_R8: 03670 case VT_CY: 03671 case VT_DATE: 03672 *py++ = V_CY(&velem); 03673 break; 03674 /* 16 bits */ 03675 case VT_BOOL: 03676 case VT_I2: 03677 case VT_UI2: 03678 *ps++ = V_I2(&velem); 03679 break; 03680 /* 8 bites */ 03681 case VT_UI1: 03682 case VT_I1: 03683 *pb++ = V_UI1(&velem); 03684 break; 03685 /* 32 bits */ 03686 default: 03687 *pl++ = V_I4(&velem); 03688 break; 03689 } 03690 } 03691 SafeArrayUnlock(V_ARRAY(&realargs[i])); 03692 } 03693 else 03694 { 03695 ole_val2variant(param, &realargs[i]); 03696 if ((vt & (~VT_BYREF)) != VT_VARIANT) 03697 { 03698 hr = VariantChangeTypeEx(&realargs[i], &realargs[i], 03699 cWIN32OLE_lcid, 0, 03700 (VARTYPE)(vt & (~VT_BYREF))); 03701 if (hr != S_OK) 03702 { 03703 rb_raise(rb_eTypeError, "not valid value"); 03704 } 03705 } 03706 } 03707 if ((vt & VT_BYREF) || vt == VT_VARIANT) 03708 { 03709 if (vt == VT_VARIANT) 03710 V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF; 03711 switch (vt & (~VT_BYREF)) 03712 { 03713 /* 128 bits */ 03714 case VT_VARIANT: 03715 V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i]; 03716 break; 03717 /* 64 bits */ 03718 case VT_R8: 03719 case VT_CY: 03720 case VT_DATE: 03721 V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]); 03722 break; 03723 /* 16 bits */ 03724 case VT_BOOL: 03725 case VT_I2: 03726 case VT_UI2: 03727 V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]); 03728 break; 03729 /* 8 bites */ 03730 case VT_UI1: 03731 case VT_I1: 03732 V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]); 03733 break; 03734 /* 32 bits */ 03735 default: 03736 V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]); 03737 break; 03738 } 03739 } 03740 else 03741 { 03742 /* copy 64 bits of data */ 03743 V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]); 03744 } 03745 } 03746 } 03747 03748 if (dispkind & DISPATCH_PROPERTYPUT) { 03749 dispParams.cNamedArgs = 1; 03750 dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); 03751 dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; 03752 } 03753 03754 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid), 03755 &IID_NULL, cWIN32OLE_lcid, 03756 dispkind, 03757 &dispParams, &result, 03758 &excepinfo, &argErr); 03759 03760 if (FAILED(hr)) { 03761 v = ole_excepinfo2msg(&excepinfo); 03762 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s", 03763 NUM2INT(dispid), 03764 StringValuePtr(v)); 03765 } 03766 03767 /* clear dispatch parameter */ 03768 if(dispParams.cArgs > 0) { 03769 set_argv(realargs, 0, dispParams.cArgs); 03770 } 03771 03772 obj = ole_variant2val(&result); 03773 VariantClear(&result); 03774 return obj; 03775 } 03776 03777 /* 03778 * call-seq: 03779 * WIN32OLE#_invoke(dispid, args, types) 03780 * 03781 * Runs the early binding method. 03782 * The 1st argument specifies dispatch ID, 03783 * the 2nd argument specifies the array of arguments, 03784 * the 3rd argument specifies the array of the type of arguments. 03785 * 03786 * excel = WIN32OLE.new('Excel.Application') 03787 * excel._invoke(302, [], []) # same effect as excel.Quit 03788 */ 03789 static VALUE 03790 fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types) 03791 { 03792 return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD); 03793 } 03794 03795 /* 03796 * call-seq: 03797 * WIN32OLE#_getproperty(dispid, args, types) 03798 * 03799 * Runs the early binding method to get property. 03800 * The 1st argument specifies dispatch ID, 03801 * the 2nd argument specifies the array of arguments, 03802 * the 3rd argument specifies the array of the type of arguments. 03803 * 03804 * excel = WIN32OLE.new('Excel.Application') 03805 * puts excel._getproperty(558, [], []) # same effect as puts excel.visible 03806 */ 03807 static VALUE 03808 fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) 03809 { 03810 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET); 03811 } 03812 03813 /* 03814 * call-seq: 03815 * WIN32OLE#_setproperty(dispid, args, types) 03816 * 03817 * Runs the early binding method to set property. 03818 * The 1st argument specifies dispatch ID, 03819 * the 2nd argument specifies the array of arguments, 03820 * the 3rd argument specifies the array of the type of arguments. 03821 * 03822 * excel = WIN32OLE.new('Excel.Application') 03823 * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true 03824 */ 03825 static VALUE 03826 fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) 03827 { 03828 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT); 03829 } 03830 03831 /* 03832 * call-seq: 03833 * WIN32OLE[a1, a2, ...]=val 03834 * 03835 * Sets the value to WIN32OLE object specified by a1, a2, ... 03836 * 03837 * dict = WIN32OLE.new('Scripting.Dictionary') 03838 * dict.add('ruby', 'RUBY') 03839 * dict['ruby'] = 'Ruby' 03840 * puts dict['ruby'] # => 'Ruby' 03841 * 03842 * Remark: You can not use this method to set the property value. 03843 * 03844 * excel = WIN32OLE.new('Excel.Application') 03845 * # excel['Visible'] = true # This is error !!! 03846 * excel.Visible = true # You should to use this style to set the property. 03847 * 03848 */ 03849 static VALUE 03850 fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self) 03851 { 03852 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE); 03853 } 03854 03855 /* 03856 * call-seq: 03857 * WIN32OLE.setproperty('property', [arg1, arg2,...] val) 03858 * 03859 * Sets property of OLE object. 03860 * When you want to set property with argument, you can use this method. 03861 * 03862 * excel = WIN32OLE.new('Excel.Application') 03863 * excel.Visible = true 03864 * book = excel.workbooks.add 03865 * sheet = book.worksheets(1) 03866 * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10. 03867 */ 03868 static VALUE 03869 fole_setproperty(int argc, VALUE *argv, VALUE self) 03870 { 03871 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE); 03872 } 03873 03874 /* 03875 * call-seq: 03876 * WIN32OLE[a1,a2,...] 03877 * 03878 * Returns the value of Collection specified by a1, a2,.... 03879 * 03880 * dict = WIN32OLE.new('Scripting.Dictionary') 03881 * dict.add('ruby', 'Ruby') 03882 * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')') 03883 * 03884 * Remark: You can not use this method to get the property. 03885 * excel = WIN32OLE.new('Excel.Application') 03886 * # puts excel['Visible'] This is error !!! 03887 * puts excel.Visible # You should to use this style to get the property. 03888 * 03889 */ 03890 static VALUE 03891 fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self) 03892 { 03893 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE); 03894 } 03895 03896 static VALUE 03897 ole_propertyput(VALUE self, VALUE property, VALUE value) 03898 { 03899 struct oledata *pole; 03900 unsigned argErr; 03901 unsigned int index; 03902 HRESULT hr; 03903 EXCEPINFO excepinfo; 03904 DISPID dispID = DISPID_VALUE; 03905 DISPID dispIDParam = DISPID_PROPERTYPUT; 03906 USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF; 03907 DISPPARAMS dispParams; 03908 VARIANTARG propertyValue[2]; 03909 OLECHAR* pBuf[1]; 03910 VALUE v; 03911 LCID lcid = cWIN32OLE_lcid; 03912 dispParams.rgdispidNamedArgs = &dispIDParam; 03913 dispParams.rgvarg = propertyValue; 03914 dispParams.cNamedArgs = 1; 03915 dispParams.cArgs = 1; 03916 03917 VariantInit(&propertyValue[0]); 03918 VariantInit(&propertyValue[1]); 03919 memset(&excepinfo, 0, sizeof(excepinfo)); 03920 03921 OLEData_Get_Struct(self, pole); 03922 03923 /* get ID from property name */ 03924 pBuf[0] = ole_vstr2wc(property); 03925 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL, 03926 pBuf, 1, lcid, &dispID); 03927 SysFreeString(pBuf[0]); 03928 pBuf[0] = NULL; 03929 03930 if(FAILED(hr)) { 03931 ole_raise(hr, eWIN32OLERuntimeError, 03932 "unknown property or method: `%s'", 03933 StringValuePtr(property)); 03934 } 03935 /* set property value */ 03936 ole_val2variant(value, &propertyValue[0]); 03937 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL, 03938 lcid, wFlags, &dispParams, 03939 NULL, &excepinfo, &argErr); 03940 03941 for(index = 0; index < dispParams.cArgs; ++index) { 03942 VariantClear(&propertyValue[index]); 03943 } 03944 if (FAILED(hr)) { 03945 v = ole_excepinfo2msg(&excepinfo); 03946 ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s", 03947 StringValuePtr(property), 03948 StringValuePtr(v)); 03949 } 03950 return Qnil; 03951 } 03952 03953 /* 03954 * call-seq: 03955 * WIN32OLE#ole_free 03956 * 03957 * invokes Release method of Dispatch interface of WIN32OLE object. 03958 * Usually, you do not need to call this method because Release method 03959 * called automatically when WIN32OLE object garbaged. 03960 * 03961 */ 03962 static VALUE 03963 fole_free(VALUE self) 03964 { 03965 struct oledata *pole; 03966 rb_secure(4); 03967 OLEData_Get_Struct(self, pole); 03968 OLE_FREE(pole->pDispatch); 03969 pole->pDispatch = NULL; 03970 return Qnil; 03971 } 03972 03973 static VALUE 03974 ole_each_sub(VALUE pEnumV) 03975 { 03976 VARIANT variant; 03977 VALUE obj = Qnil; 03978 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; 03979 VariantInit(&variant); 03980 while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) { 03981 obj = ole_variant2val(&variant); 03982 VariantClear(&variant); 03983 VariantInit(&variant); 03984 rb_yield(obj); 03985 } 03986 return Qnil; 03987 } 03988 03989 static VALUE 03990 ole_ienum_free(VALUE pEnumV) 03991 { 03992 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; 03993 OLE_RELEASE(pEnum); 03994 return Qnil; 03995 } 03996 03997 /* 03998 * call-seq: 03999 * WIN32OLE#each {|i|...} 04000 * 04001 * Iterates over each item of OLE collection which has IEnumVARIANT interface. 04002 * 04003 * excel = WIN32OLE.new('Excel.Application') 04004 * book = excel.workbooks.add 04005 * sheets = book.worksheets(1) 04006 * cells = sheets.cells("A1:A5") 04007 * cells.each do |cell| 04008 * cell.value = 10 04009 * end 04010 */ 04011 static VALUE 04012 fole_each(VALUE self) 04013 { 04014 LCID lcid = cWIN32OLE_lcid; 04015 04016 struct oledata *pole; 04017 04018 unsigned int argErr; 04019 EXCEPINFO excepinfo; 04020 DISPPARAMS dispParams; 04021 VARIANT result; 04022 HRESULT hr; 04023 IEnumVARIANT *pEnum = NULL; 04024 void *p; 04025 04026 RETURN_ENUMERATOR(self, 0, 0); 04027 04028 VariantInit(&result); 04029 dispParams.rgvarg = NULL; 04030 dispParams.rgdispidNamedArgs = NULL; 04031 dispParams.cNamedArgs = 0; 04032 dispParams.cArgs = 0; 04033 memset(&excepinfo, 0, sizeof(excepinfo)); 04034 04035 OLEData_Get_Struct(self, pole); 04036 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM, 04037 &IID_NULL, lcid, 04038 DISPATCH_METHOD | DISPATCH_PROPERTYGET, 04039 &dispParams, &result, 04040 &excepinfo, &argErr); 04041 04042 if (FAILED(hr)) { 04043 VariantClear(&result); 04044 ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface"); 04045 } 04046 04047 if (V_VT(&result) == VT_UNKNOWN) { 04048 hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result), 04049 &IID_IEnumVARIANT, 04050 &p); 04051 pEnum = p; 04052 } else if (V_VT(&result) == VT_DISPATCH) { 04053 hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result), 04054 &IID_IEnumVARIANT, 04055 &p); 04056 pEnum = p; 04057 } 04058 if (FAILED(hr) || !pEnum) { 04059 VariantClear(&result); 04060 ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface"); 04061 } 04062 04063 VariantClear(&result); 04064 rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum); 04065 return Qnil; 04066 } 04067 04068 /* 04069 * call-seq: 04070 * WIN32OLE#method_missing(id [,arg1, arg2, ...]) 04071 * 04072 * Calls WIN32OLE#invoke method. 04073 */ 04074 static VALUE 04075 fole_missing(int argc, VALUE *argv, VALUE self) 04076 { 04077 ID id; 04078 const char* mname; 04079 int n; 04080 id = rb_to_id(argv[0]); 04081 mname = rb_id2name(id); 04082 if(!mname) { 04083 rb_raise(rb_eRuntimeError, "fail: unknown method or property"); 04084 } 04085 n = strlen(mname); 04086 if(mname[n-1] == '=') { 04087 argv[0] = rb_enc_str_new(mname, n-1, cWIN32OLE_enc); 04088 04089 return ole_propertyput(self, argv[0], argv[1]); 04090 } 04091 else { 04092 argv[0] = rb_enc_str_new(mname, n, cWIN32OLE_enc); 04093 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); 04094 } 04095 } 04096 04097 static VALUE 04098 ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name) 04099 { 04100 HRESULT hr; 04101 TYPEATTR *pTypeAttr; 04102 BSTR bstr; 04103 FUNCDESC *pFuncDesc; 04104 WORD i; 04105 VALUE fname; 04106 VALUE method = Qnil; 04107 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04108 if (FAILED(hr)) { 04109 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04110 } 04111 for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) { 04112 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); 04113 if (FAILED(hr)) 04114 continue; 04115 04116 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 04117 &bstr, NULL, NULL, NULL); 04118 if (FAILED(hr)) { 04119 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04120 continue; 04121 } 04122 fname = WC2VSTR(bstr); 04123 if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) { 04124 olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname); 04125 method = self; 04126 } 04127 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04128 pFuncDesc=NULL; 04129 } 04130 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04131 return method; 04132 } 04133 04134 static VALUE 04135 olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name) 04136 { 04137 HRESULT hr; 04138 TYPEATTR *pTypeAttr; 04139 WORD i; 04140 HREFTYPE href; 04141 ITypeInfo *pRefTypeInfo; 04142 VALUE method = Qnil; 04143 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04144 if (FAILED(hr)) { 04145 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04146 } 04147 method = ole_method_sub(self, 0, pTypeInfo, name); 04148 if (method != Qnil) { 04149 return method; 04150 } 04151 for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){ 04152 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 04153 if(FAILED(hr)) 04154 continue; 04155 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 04156 if (FAILED(hr)) 04157 continue; 04158 method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name); 04159 OLE_RELEASE(pRefTypeInfo); 04160 } 04161 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04162 return method; 04163 } 04164 04165 static VALUE 04166 ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask) 04167 { 04168 HRESULT hr; 04169 TYPEATTR *pTypeAttr; 04170 BSTR bstr; 04171 FUNCDESC *pFuncDesc; 04172 VALUE method; 04173 WORD i; 04174 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04175 if (FAILED(hr)) { 04176 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04177 } 04178 for(i = 0; i < pTypeAttr->cFuncs; i++) { 04179 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); 04180 if (FAILED(hr)) 04181 continue; 04182 04183 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 04184 &bstr, NULL, NULL, NULL); 04185 if (FAILED(hr)) { 04186 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04187 continue; 04188 } 04189 if(pFuncDesc->invkind & mask) { 04190 method = folemethod_s_allocate(cWIN32OLE_METHOD); 04191 olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo, 04192 i, WC2VSTR(bstr)); 04193 rb_ary_push(methods, method); 04194 } 04195 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04196 pFuncDesc=NULL; 04197 } 04198 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04199 04200 return methods; 04201 } 04202 04203 static VALUE 04204 ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) 04205 { 04206 HRESULT hr; 04207 TYPEATTR *pTypeAttr; 04208 WORD i; 04209 HREFTYPE href; 04210 ITypeInfo *pRefTypeInfo; 04211 VALUE methods = rb_ary_new(); 04212 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04213 if (FAILED(hr)) { 04214 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04215 } 04216 04217 ole_methods_sub(0, pTypeInfo, methods, mask); 04218 for(i=0; i < pTypeAttr->cImplTypes; i++){ 04219 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 04220 if(FAILED(hr)) 04221 continue; 04222 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 04223 if (FAILED(hr)) 04224 continue; 04225 ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask); 04226 OLE_RELEASE(pRefTypeInfo); 04227 } 04228 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04229 return methods; 04230 } 04231 04232 static HRESULT 04233 typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti) 04234 { 04235 ITypeInfo *pTypeInfo; 04236 ITypeLib *pTypeLib; 04237 BSTR bstr; 04238 VALUE type; 04239 UINT i; 04240 UINT count; 04241 LCID lcid = cWIN32OLE_lcid; 04242 HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 04243 0, lcid, &pTypeInfo); 04244 if(FAILED(hr)) { 04245 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 04246 } 04247 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, 04248 -1, 04249 &bstr, 04250 NULL, NULL, NULL); 04251 type = WC2VSTR(bstr); 04252 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); 04253 OLE_RELEASE(pTypeInfo); 04254 if (FAILED(hr)) { 04255 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); 04256 } 04257 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 04258 for (i = 0; i < count; i++) { 04259 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 04260 &bstr, NULL, NULL, NULL); 04261 if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) { 04262 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 04263 if (SUCCEEDED(hr)) { 04264 *ppti = pTypeInfo; 04265 break; 04266 } 04267 } 04268 } 04269 OLE_RELEASE(pTypeLib); 04270 return hr; 04271 } 04272 04273 static VALUE 04274 ole_methods(VALUE self, int mask) 04275 { 04276 ITypeInfo *pTypeInfo; 04277 HRESULT hr; 04278 VALUE methods; 04279 struct oledata *pole; 04280 04281 OLEData_Get_Struct(self, pole); 04282 methods = rb_ary_new(); 04283 04284 hr = typeinfo_from_ole(pole, &pTypeInfo); 04285 if(FAILED(hr)) 04286 return methods; 04287 rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask)); 04288 OLE_RELEASE(pTypeInfo); 04289 return methods; 04290 } 04291 04292 /* 04293 * call-seq: 04294 * WIN32OLE#ole_methods 04295 * 04296 * Returns the array of WIN32OLE_METHOD object. 04297 * The element is OLE method of WIN32OLE object. 04298 * 04299 * excel = WIN32OLE.new('Excel.Application') 04300 * methods = excel.ole_methods 04301 * 04302 */ 04303 static VALUE 04304 fole_methods(VALUE self) 04305 { 04306 return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); 04307 } 04308 04309 /* 04310 * call-seq: 04311 * WIN32OLE#ole_get_methods 04312 * 04313 * Returns the array of WIN32OLE_METHOD object . 04314 * The element of the array is property (gettable) of WIN32OLE object. 04315 * 04316 * excel = WIN32OLE.new('Excel.Application') 04317 * properties = excel.ole_get_methods 04318 */ 04319 static VALUE 04320 fole_get_methods(VALUE self) 04321 { 04322 return ole_methods( self, INVOKE_PROPERTYGET); 04323 } 04324 04325 /* 04326 * call-seq: 04327 * WIN32OLE#ole_put_methods 04328 * 04329 * Returns the array of WIN32OLE_METHOD object . 04330 * The element of the array is property (settable) of WIN32OLE object. 04331 * 04332 * excel = WIN32OLE.new('Excel.Application') 04333 * properties = excel.ole_put_methods 04334 */ 04335 static VALUE 04336 fole_put_methods(VALUE self) 04337 { 04338 return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF); 04339 } 04340 04341 /* 04342 * call-seq: 04343 * WIN32OLE#ole_func_methods 04344 * 04345 * Returns the array of WIN32OLE_METHOD object . 04346 * The element of the array is property (settable) of WIN32OLE object. 04347 * 04348 * excel = WIN32OLE.new('Excel.Application') 04349 * properties = excel.ole_func_methods 04350 * 04351 */ 04352 static VALUE 04353 fole_func_methods(VALUE self) 04354 { 04355 return ole_methods( self, INVOKE_FUNC); 04356 } 04357 04358 static VALUE 04359 ole_type_from_itypeinfo(ITypeInfo *pTypeInfo) 04360 { 04361 ITypeLib *pTypeLib; 04362 VALUE type = Qnil; 04363 HRESULT hr; 04364 unsigned int index; 04365 BSTR bstr; 04366 04367 hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index ); 04368 if(FAILED(hr)) { 04369 return Qnil; 04370 } 04371 hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index, 04372 &bstr, NULL, NULL, NULL); 04373 OLE_RELEASE(pTypeLib); 04374 if (FAILED(hr)) { 04375 return Qnil; 04376 } 04377 type = foletype_s_allocate(cWIN32OLE_TYPE); 04378 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr)); 04379 return type; 04380 } 04381 04382 /* 04383 * call-seq: 04384 * WIN32OLE#ole_type 04385 * 04386 * Returns WIN32OLE_TYPE object. 04387 * 04388 * excel = WIN32OLE.new('Excel.Application') 04389 * tobj = excel.ole_type 04390 */ 04391 static VALUE 04392 fole_type(VALUE self) 04393 { 04394 ITypeInfo *pTypeInfo; 04395 HRESULT hr; 04396 struct oledata *pole; 04397 LCID lcid = cWIN32OLE_lcid; 04398 VALUE type = Qnil; 04399 04400 OLEData_Get_Struct(self, pole); 04401 04402 hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo ); 04403 if(FAILED(hr)) { 04404 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 04405 } 04406 type = ole_type_from_itypeinfo(pTypeInfo); 04407 OLE_RELEASE(pTypeInfo); 04408 if (type == Qnil) { 04409 rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo"); 04410 } 04411 return type; 04412 } 04413 04414 static VALUE 04415 ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo) 04416 { 04417 HRESULT hr; 04418 ITypeLib *pTypeLib; 04419 unsigned int index; 04420 VALUE retval = Qnil; 04421 04422 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); 04423 if(FAILED(hr)) { 04424 return Qnil; 04425 } 04426 retval = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0); 04427 oletypelib_set_member(retval, pTypeLib); 04428 return retval; 04429 } 04430 04431 /* 04432 * call-seq: 04433 * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object 04434 * 04435 * Returns the WIN32OLE_TYPELIB object. The object represents the 04436 * type library which contains the WIN32OLE object. 04437 * 04438 * excel = WIN32OLE.new('Excel.Application') 04439 * tlib = excel.ole_typelib 04440 * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library' 04441 */ 04442 static VALUE 04443 fole_typelib(VALUE self) 04444 { 04445 struct oledata *pole; 04446 HRESULT hr; 04447 ITypeInfo *pTypeInfo; 04448 LCID lcid = cWIN32OLE_lcid; 04449 VALUE vtlib = Qnil; 04450 04451 OLEData_Get_Struct(self, pole); 04452 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 04453 0, lcid, &pTypeInfo); 04454 if(FAILED(hr)) { 04455 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 04456 } 04457 vtlib = ole_typelib_from_itypeinfo(pTypeInfo); 04458 OLE_RELEASE(pTypeInfo); 04459 if (vtlib == Qnil) { 04460 rb_raise(rb_eRuntimeError, "failed to get type library info."); 04461 } 04462 return vtlib; 04463 } 04464 04465 /* 04466 * call-seq: 04467 * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object 04468 * 04469 * Returns WIN32OLE object for a specific dispatch or dual 04470 * interface specified by iid. 04471 * 04472 * ie = WIN32OLE.new('InternetExplorer.Application') 04473 * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp 04474 */ 04475 static VALUE 04476 fole_query_interface(VALUE self, VALUE str_iid) 04477 { 04478 HRESULT hr; 04479 OLECHAR *pBuf; 04480 IID iid; 04481 struct oledata *pole; 04482 IDispatch *pDispatch; 04483 void *p; 04484 04485 pBuf = ole_vstr2wc(str_iid); 04486 hr = CLSIDFromString(pBuf, &iid); 04487 SysFreeString(pBuf); 04488 if(FAILED(hr)) { 04489 ole_raise(hr, eWIN32OLERuntimeError, 04490 "invalid iid: `%s'", 04491 StringValuePtr(str_iid)); 04492 } 04493 04494 OLEData_Get_Struct(self, pole); 04495 if(!pole->pDispatch) { 04496 rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); 04497 } 04498 04499 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid, 04500 &p); 04501 if(FAILED(hr)) { 04502 ole_raise(hr, eWIN32OLERuntimeError, 04503 "failed to get interface `%s'", 04504 StringValuePtr(str_iid)); 04505 } 04506 04507 pDispatch = p; 04508 return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 04509 } 04510 04511 /* 04512 * call-seq: 04513 * WIN32OLE#ole_respond_to?(method) -> true or false 04514 * 04515 * Returns true when OLE object has OLE method, otherwise returns false. 04516 * 04517 * ie = WIN32OLE.new('InternetExplorer.Application') 04518 * ie.ole_respond_to?("gohome") => true 04519 */ 04520 static VALUE 04521 fole_respond_to(VALUE self, VALUE method) 04522 { 04523 struct oledata *pole; 04524 BSTR wcmdname; 04525 DISPID DispID; 04526 HRESULT hr; 04527 rb_secure(4); 04528 if(TYPE(method) != T_STRING && TYPE(method) != T_SYMBOL) { 04529 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 04530 } 04531 if (TYPE(method) == T_SYMBOL) { 04532 method = rb_sym_to_s(method); 04533 } 04534 OLEData_Get_Struct(self, pole); 04535 wcmdname = ole_vstr2wc(method); 04536 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, 04537 &wcmdname, 1, cWIN32OLE_lcid, &DispID); 04538 SysFreeString(wcmdname); 04539 return SUCCEEDED(hr) ? Qtrue : Qfalse; 04540 } 04541 04542 static HRESULT 04543 ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile) 04544 { 04545 HRESULT hr; 04546 ITypeLib *pTypeLib; 04547 UINT i; 04548 04549 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); 04550 if (FAILED(hr)) { 04551 return hr; 04552 } 04553 04554 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 04555 name, helpstr, 04556 helpcontext, helpfile); 04557 if (FAILED(hr)) { 04558 OLE_RELEASE(pTypeLib); 04559 return hr; 04560 } 04561 OLE_RELEASE(pTypeLib); 04562 return hr; 04563 } 04564 04565 static VALUE 04566 ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 04567 { 04568 HRESULT hr; 04569 BSTR bstr; 04570 ITypeInfo *pRefTypeInfo; 04571 VALUE type = Qnil; 04572 04573 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 04574 V_UNION1(pTypeDesc, hreftype), 04575 &pRefTypeInfo); 04576 if(FAILED(hr)) 04577 return Qnil; 04578 hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL); 04579 if(FAILED(hr)) { 04580 OLE_RELEASE(pRefTypeInfo); 04581 return Qnil; 04582 } 04583 OLE_RELEASE(pRefTypeInfo); 04584 type = WC2VSTR(bstr); 04585 if(typedetails != Qnil) 04586 rb_ary_push(typedetails, type); 04587 return type; 04588 } 04589 04590 static VALUE 04591 ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 04592 { 04593 TYPEDESC *p = pTypeDesc; 04594 VALUE type = rb_str_new2(""); 04595 04596 if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) { 04597 p = V_UNION1(p, lptdesc); 04598 type = ole_typedesc2val(pTypeInfo, p, typedetails); 04599 } 04600 return type; 04601 } 04602 04603 static VALUE 04604 ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 04605 { 04606 VALUE str; 04607 VALUE typestr = Qnil; 04608 switch(pTypeDesc->vt) { 04609 case VT_I2: 04610 typestr = rb_str_new2("I2"); 04611 break; 04612 case VT_I4: 04613 typestr = rb_str_new2("I4"); 04614 break; 04615 case VT_R4: 04616 typestr = rb_str_new2("R4"); 04617 break; 04618 case VT_R8: 04619 typestr = rb_str_new2("R8"); 04620 break; 04621 case VT_CY: 04622 typestr = rb_str_new2("CY"); 04623 break; 04624 case VT_DATE: 04625 typestr = rb_str_new2("DATE"); 04626 break; 04627 case VT_BSTR: 04628 typestr = rb_str_new2("BSTR"); 04629 break; 04630 case VT_BOOL: 04631 typestr = rb_str_new2("BOOL"); 04632 break; 04633 case VT_VARIANT: 04634 typestr = rb_str_new2("VARIANT"); 04635 break; 04636 case VT_DECIMAL: 04637 typestr = rb_str_new2("DECIMAL"); 04638 break; 04639 case VT_I1: 04640 typestr = rb_str_new2("I1"); 04641 break; 04642 case VT_UI1: 04643 typestr = rb_str_new2("UI1"); 04644 break; 04645 case VT_UI2: 04646 typestr = rb_str_new2("UI2"); 04647 break; 04648 case VT_UI4: 04649 typestr = rb_str_new2("UI4"); 04650 break; 04651 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 04652 case VT_I8: 04653 typestr = rb_str_new2("I8"); 04654 break; 04655 case VT_UI8: 04656 typestr = rb_str_new2("UI8"); 04657 break; 04658 #endif 04659 case VT_INT: 04660 typestr = rb_str_new2("INT"); 04661 break; 04662 case VT_UINT: 04663 typestr = rb_str_new2("UINT"); 04664 break; 04665 case VT_VOID: 04666 typestr = rb_str_new2("VOID"); 04667 break; 04668 case VT_HRESULT: 04669 typestr = rb_str_new2("HRESULT"); 04670 break; 04671 case VT_PTR: 04672 typestr = rb_str_new2("PTR"); 04673 if(typedetails != Qnil) 04674 rb_ary_push(typedetails, typestr); 04675 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); 04676 case VT_SAFEARRAY: 04677 typestr = rb_str_new2("SAFEARRAY"); 04678 if(typedetails != Qnil) 04679 rb_ary_push(typedetails, typestr); 04680 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); 04681 case VT_CARRAY: 04682 typestr = rb_str_new2("CARRAY"); 04683 break; 04684 case VT_USERDEFINED: 04685 typestr = rb_str_new2("USERDEFINED"); 04686 if (typedetails != Qnil) 04687 rb_ary_push(typedetails, typestr); 04688 str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails); 04689 if (str != Qnil) { 04690 return str; 04691 } 04692 return typestr; 04693 case VT_UNKNOWN: 04694 typestr = rb_str_new2("UNKNOWN"); 04695 break; 04696 case VT_DISPATCH: 04697 typestr = rb_str_new2("DISPATCH"); 04698 break; 04699 case VT_ERROR: 04700 typestr = rb_str_new2("ERROR"); 04701 break; 04702 case VT_LPWSTR: 04703 typestr = rb_str_new2("LPWSTR"); 04704 break; 04705 case VT_LPSTR: 04706 typestr = rb_str_new2("LPSTR"); 04707 break; 04708 default: 04709 typestr = rb_str_new2("Unknown Type "); 04710 rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10)); 04711 break; 04712 } 04713 if (typedetails != Qnil) 04714 rb_ary_push(typedetails, typestr); 04715 return typestr; 04716 } 04717 04718 /* 04719 * call-seq: 04720 * WIN32OLE#ole_method_help(method) 04721 * 04722 * Returns WIN32OLE_METHOD object corresponding with method 04723 * specified by 1st argument. 04724 * 04725 * excel = WIN32OLE.new('Excel.Application') 04726 * method = excel.ole_method_help('Quit') 04727 * 04728 */ 04729 static VALUE 04730 fole_method_help(VALUE self, VALUE cmdname) 04731 { 04732 ITypeInfo *pTypeInfo; 04733 HRESULT hr; 04734 struct oledata *pole; 04735 VALUE method, obj; 04736 04737 SafeStringValue(cmdname); 04738 OLEData_Get_Struct(self, pole); 04739 hr = typeinfo_from_ole(pole, &pTypeInfo); 04740 if(FAILED(hr)) 04741 ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo"); 04742 method = folemethod_s_allocate(cWIN32OLE_METHOD); 04743 obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname); 04744 OLE_RELEASE(pTypeInfo); 04745 if (obj == Qnil) 04746 rb_raise(eWIN32OLERuntimeError, "not found %s", 04747 StringValuePtr(cmdname)); 04748 return obj; 04749 } 04750 04751 /* 04752 * call-seq: 04753 * WIN32OLE#ole_activex_initialize() -> Qnil 04754 * 04755 * Initialize WIN32OLE object(ActiveX Control) by calling 04756 * IPersistMemory::InitNew. 04757 * 04758 * Before calling OLE method, some kind of the ActiveX controls 04759 * created with MFC should be initialized by calling 04760 * IPersistXXX::InitNew. 04761 * 04762 * If and only if you received the exception "HRESULT error code: 04763 * 0x8000ffff catastrophic failure", try this method before 04764 * invoking any ole_method. 04765 * 04766 * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control") 04767 * obj.ole_activex_initialize 04768 * obj.method(...) 04769 * 04770 */ 04771 static VALUE 04772 fole_activex_initialize(VALUE self) 04773 { 04774 struct oledata *pole; 04775 IPersistMemory *pPersistMemory; 04776 void *p; 04777 04778 HRESULT hr = S_OK; 04779 04780 OLEData_Get_Struct(self, pole); 04781 04782 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p); 04783 pPersistMemory = p; 04784 if (SUCCEEDED(hr)) { 04785 hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory); 04786 OLE_RELEASE(pPersistMemory); 04787 if (SUCCEEDED(hr)) { 04788 return Qnil; 04789 } 04790 } 04791 04792 if (FAILED(hr)) { 04793 ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control"); 04794 } 04795 04796 return Qnil; 04797 } 04798 04799 /* 04800 * call-seq: 04801 * WIN32OLE_TYPE.ole_classes(typelib) 04802 * 04803 * Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library. 04804 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead. 04805 */ 04806 static VALUE 04807 foletype_s_ole_classes(VALUE self, VALUE typelib) 04808 { 04809 VALUE obj; 04810 04811 /* 04812 rb_warn("%s is obsolete; use %s instead.", 04813 "WIN32OLE_TYPE.ole_classes", 04814 "WIN32OLE_TYPELIB.new(typelib).ole_types"); 04815 */ 04816 obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib); 04817 return rb_funcall(obj, rb_intern("ole_types"), 0); 04818 } 04819 04820 /* 04821 * call-seq: 04822 * WIN32OLE_TYPE.typelibs 04823 * 04824 * Returns array of type libraries. 04825 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead. 04826 * 04827 */ 04828 static VALUE 04829 foletype_s_typelibs(VALUE self) 04830 { 04831 /* 04832 rb_warn("%s is obsolete. use %s instead.", 04833 "WIN32OLE_TYPE.typelibs", 04834 "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}"); 04835 */ 04836 return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}"); 04837 } 04838 04839 /* 04840 * call-seq: 04841 * WIN32OLE_TYPE.progids 04842 * 04843 * Returns array of ProgID. 04844 */ 04845 static VALUE 04846 foletype_s_progids(VALUE self) 04847 { 04848 HKEY hclsids, hclsid; 04849 DWORD i; 04850 LONG err; 04851 VALUE clsid; 04852 VALUE v = rb_str_new2(""); 04853 VALUE progids = rb_ary_new(); 04854 04855 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids); 04856 if(err != ERROR_SUCCESS) { 04857 return progids; 04858 } 04859 for(i = 0; ; i++) { 04860 clsid = reg_enum_key(hclsids, i); 04861 if (clsid == Qnil) 04862 break; 04863 err = reg_open_vkey(hclsids, clsid, &hclsid); 04864 if (err != ERROR_SUCCESS) 04865 continue; 04866 if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil) 04867 rb_ary_push(progids, v); 04868 if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil) 04869 rb_ary_push(progids, v); 04870 RegCloseKey(hclsid); 04871 } 04872 RegCloseKey(hclsids); 04873 return progids; 04874 } 04875 04876 static VALUE 04877 foletype_s_allocate(VALUE klass) 04878 { 04879 struct oletypedata *poletype; 04880 VALUE obj; 04881 ole_initialize(); 04882 obj = Data_Make_Struct(klass,struct oletypedata,0,oletype_free,poletype); 04883 poletype->pTypeInfo = NULL; 04884 return obj; 04885 } 04886 04887 static VALUE 04888 oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name) 04889 { 04890 struct oletypedata *ptype; 04891 Data_Get_Struct(self, struct oletypedata, ptype); 04892 rb_ivar_set(self, rb_intern("name"), name); 04893 ptype->pTypeInfo = pTypeInfo; 04894 if(pTypeInfo) OLE_ADDREF(pTypeInfo); 04895 return self; 04896 } 04897 04898 static VALUE 04899 oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) 04900 { 04901 04902 long count; 04903 int i; 04904 HRESULT hr; 04905 BSTR bstr; 04906 VALUE typelib; 04907 ITypeInfo *pTypeInfo; 04908 04909 VALUE found = Qfalse; 04910 04911 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 04912 for (i = 0; i < count && found == Qfalse; i++) { 04913 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 04914 if (FAILED(hr)) 04915 continue; 04916 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 04917 &bstr, NULL, NULL, NULL); 04918 if (FAILED(hr)) 04919 continue; 04920 typelib = WC2VSTR(bstr); 04921 if (rb_str_cmp(oleclass, typelib) == 0) { 04922 oletype_set_member(self, pTypeInfo, typelib); 04923 found = Qtrue; 04924 } 04925 OLE_RELEASE(pTypeInfo); 04926 } 04927 return found; 04928 } 04929 04930 /* 04931 * Document-class: WIN32OLE_TYPELIB 04932 * 04933 * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information. 04934 */ 04935 04936 static VALUE 04937 oletypelib_set_member(VALUE self, ITypeLib *pTypeLib) 04938 { 04939 struct oletypelibdata *ptlib; 04940 Data_Get_Struct(self, struct oletypelibdata, ptlib); 04941 ptlib->pTypeLib = pTypeLib; 04942 return self; 04943 } 04944 04945 static ITypeLib * 04946 oletypelib_get_typelib(VALUE self) 04947 { 04948 struct oletypelibdata *ptlib; 04949 Data_Get_Struct(self, struct oletypelibdata, ptlib); 04950 return ptlib->pTypeLib; 04951 } 04952 04953 static void 04954 oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr) 04955 { 04956 HRESULT hr; 04957 hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr); 04958 if (FAILED(hr)) { 04959 ole_raise(hr, eWIN32OLERuntimeError, 04960 "failed to get library attribute(TLIBATTR) from ITypeLib"); 04961 } 04962 } 04963 04964 /* 04965 * call-seq: 04966 * 04967 * WIN32OLE_TYPELIB.typelibs 04968 * 04969 * Returns the array of WIN32OLE_TYPELIB object. 04970 * 04971 * tlibs = WIN32OLE_TYPELIB.typelibs 04972 * 04973 */ 04974 static VALUE 04975 foletypelib_s_typelibs(VALUE self) 04976 { 04977 HKEY htypelib, hguid; 04978 DWORD i, j; 04979 LONG err; 04980 VALUE guid; 04981 VALUE version; 04982 VALUE name = Qnil; 04983 VALUE typelibs = rb_ary_new(); 04984 VALUE typelib = Qnil; 04985 HRESULT hr; 04986 ITypeLib *pTypeLib; 04987 04988 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 04989 if(err != ERROR_SUCCESS) { 04990 return typelibs; 04991 } 04992 for(i = 0; ; i++) { 04993 guid = reg_enum_key(htypelib, i); 04994 if (guid == Qnil) 04995 break; 04996 err = reg_open_vkey(htypelib, guid, &hguid); 04997 if (err != ERROR_SUCCESS) 04998 continue; 04999 for(j = 0; ; j++) { 05000 version = reg_enum_key(hguid, j); 05001 if (version == Qnil) 05002 break; 05003 if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) { 05004 hr = oletypelib_from_guid(guid, version, &pTypeLib); 05005 if (SUCCEEDED(hr)) { 05006 typelib = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0); 05007 oletypelib_set_member(typelib, pTypeLib); 05008 rb_ary_push(typelibs, typelib); 05009 } 05010 } 05011 } 05012 RegCloseKey(hguid); 05013 } 05014 RegCloseKey(htypelib); 05015 return typelibs; 05016 } 05017 05018 static VALUE 05019 make_version_str(VALUE major, VALUE minor) 05020 { 05021 VALUE version_str = Qnil; 05022 VALUE minor_str = Qnil; 05023 if (major == Qnil) { 05024 return Qnil; 05025 } 05026 version_str = rb_String(major); 05027 if (minor != Qnil) { 05028 minor_str = rb_String(minor); 05029 rb_str_cat2(version_str, "."); 05030 rb_str_append(version_str, minor_str); 05031 } 05032 return version_str; 05033 } 05034 05035 static VALUE 05036 oletypelib_search_registry2(VALUE self, VALUE args) 05037 { 05038 HKEY htypelib, hguid, hversion; 05039 double fver; 05040 DWORD j; 05041 LONG err; 05042 VALUE found = Qfalse; 05043 VALUE tlib; 05044 VALUE ver; 05045 VALUE version_str; 05046 VALUE version = Qnil; 05047 VALUE typelib = Qnil; 05048 HRESULT hr; 05049 ITypeLib *pTypeLib; 05050 05051 VALUE guid = rb_ary_entry(args, 0); 05052 version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2)); 05053 05054 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 05055 if(err != ERROR_SUCCESS) { 05056 return Qfalse; 05057 } 05058 err = reg_open_vkey(htypelib, guid, &hguid); 05059 if (err != ERROR_SUCCESS) { 05060 RegCloseKey(htypelib); 05061 return Qfalse; 05062 } 05063 if (version_str != Qnil) { 05064 err = reg_open_vkey(hguid, version_str, &hversion); 05065 if (err == ERROR_SUCCESS) { 05066 tlib = reg_get_val(hversion, NULL); 05067 if (tlib != Qnil) { 05068 typelib = tlib; 05069 version = version_str; 05070 } 05071 } 05072 RegCloseKey(hversion); 05073 } else { 05074 fver = 0.0; 05075 for(j = 0; ;j++) { 05076 ver = reg_enum_key(hguid, j); 05077 if (ver == Qnil) 05078 break; 05079 err = reg_open_vkey(hguid, ver, &hversion); 05080 if (err != ERROR_SUCCESS) 05081 continue; 05082 tlib = reg_get_val(hversion, NULL); 05083 if (tlib == Qnil) { 05084 RegCloseKey(hversion); 05085 continue; 05086 } 05087 if (fver < atof(StringValuePtr(ver))) { 05088 fver = atof(StringValuePtr(ver)); 05089 version = ver; 05090 typelib = tlib; 05091 } 05092 RegCloseKey(hversion); 05093 } 05094 } 05095 RegCloseKey(hguid); 05096 RegCloseKey(htypelib); 05097 if (typelib != Qnil) { 05098 hr = oletypelib_from_guid(guid, version, &pTypeLib); 05099 if (SUCCEEDED(hr)) { 05100 found = Qtrue; 05101 oletypelib_set_member(self, pTypeLib); 05102 } 05103 } 05104 return found; 05105 } 05106 05107 static VALUE 05108 oletypelib_search_registry(VALUE self, VALUE typelib) 05109 { 05110 HKEY htypelib, hguid, hversion; 05111 DWORD i, j; 05112 LONG err; 05113 VALUE found = Qfalse; 05114 VALUE tlib; 05115 VALUE guid; 05116 VALUE ver; 05117 HRESULT hr; 05118 ITypeLib *pTypeLib; 05119 05120 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 05121 if(err != ERROR_SUCCESS) { 05122 return Qfalse; 05123 } 05124 for(i = 0; !found; i++) { 05125 guid = reg_enum_key(htypelib, i); 05126 if (guid == Qnil) 05127 break; 05128 err = reg_open_vkey(htypelib, guid, &hguid); 05129 if (err != ERROR_SUCCESS) 05130 continue; 05131 for(j = 0; found == Qfalse; j++) { 05132 ver = reg_enum_key(hguid, j); 05133 if (ver == Qnil) 05134 break; 05135 err = reg_open_vkey(hguid, ver, &hversion); 05136 if (err != ERROR_SUCCESS) 05137 continue; 05138 tlib = reg_get_val(hversion, NULL); 05139 if (tlib == Qnil) { 05140 RegCloseKey(hversion); 05141 continue; 05142 } 05143 if (rb_str_cmp(typelib, tlib) == 0) { 05144 hr = oletypelib_from_guid(guid, ver, &pTypeLib); 05145 if (SUCCEEDED(hr)) { 05146 oletypelib_set_member(self, pTypeLib); 05147 found = Qtrue; 05148 } 05149 } 05150 RegCloseKey(hversion); 05151 } 05152 RegCloseKey(hguid); 05153 } 05154 RegCloseKey(htypelib); 05155 return found; 05156 } 05157 05158 static VALUE 05159 foletypelib_s_allocate(VALUE klass) 05160 { 05161 struct oletypelibdata *poletypelib; 05162 VALUE obj; 05163 ole_initialize(); 05164 obj = Data_Make_Struct(klass, struct oletypelibdata, 0, oletypelib_free, poletypelib); 05165 poletypelib->pTypeLib = NULL; 05166 return obj; 05167 } 05168 05169 /* 05170 * call-seq: 05171 * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object 05172 * 05173 * Returns a new WIN32OLE_TYPELIB object. 05174 * 05175 * The first argument <i>typelib</i> specifies OLE type library name or GUID or 05176 * OLE library file. 05177 * The second argument is major version or version of the type library. 05178 * The third argument is minor version. 05179 * The second argument and third argument are optional. 05180 * If the first argument is type library name, then the second and third argument 05181 * are ignored. 05182 * 05183 * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05184 * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}') 05185 * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3) 05186 * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3) 05187 * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL") 05188 * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library' 05189 * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library' 05190 * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library' 05191 * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library' 05192 * puts tlib5.name # -> 'Microsoft Shell Controls And Automation' 05193 * 05194 */ 05195 static VALUE 05196 foletypelib_initialize(VALUE self, VALUE args) 05197 { 05198 VALUE found = Qfalse; 05199 VALUE typelib = Qnil; 05200 int len = 0; 05201 OLECHAR * pbuf; 05202 ITypeLib *pTypeLib; 05203 HRESULT hr = S_OK; 05204 05205 len = RARRAY_LEN(args); 05206 if (len < 1 || len > 3) { 05207 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); 05208 } 05209 05210 typelib = rb_ary_entry(args, 0); 05211 05212 SafeStringValue(typelib); 05213 05214 found = oletypelib_search_registry(self, typelib); 05215 if (found == Qfalse) { 05216 found = oletypelib_search_registry2(self, args); 05217 } 05218 if (found == Qfalse) { 05219 pbuf = ole_vstr2wc(typelib); 05220 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); 05221 SysFreeString(pbuf); 05222 if (SUCCEEDED(hr)) { 05223 found = Qtrue; 05224 oletypelib_set_member(self, pTypeLib); 05225 } 05226 } 05227 05228 if (found == Qfalse) { 05229 rb_raise(eWIN32OLERuntimeError, "not found type library `%s`", 05230 StringValuePtr(typelib)); 05231 } 05232 return self; 05233 } 05234 05235 /* 05236 * call-seq: 05237 * WIN32OLE_TYPELIB#guid -> The guid string. 05238 * 05239 * Returns guid string which specifies type library. 05240 * 05241 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05242 * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}' 05243 */ 05244 static VALUE 05245 foletypelib_guid(VALUE self) 05246 { 05247 ITypeLib *pTypeLib; 05248 OLECHAR bstr[80]; 05249 VALUE guid = Qnil; 05250 int len; 05251 TLIBATTR *pTLibAttr; 05252 05253 pTypeLib = oletypelib_get_typelib(self); 05254 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05255 len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 05256 if (len > 3) { 05257 guid = ole_wc2vstr(bstr, FALSE); 05258 } 05259 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05260 return guid; 05261 } 05262 05263 /* 05264 * call-seq: 05265 * WIN32OLE_TYPELIB#name -> The type library name 05266 * 05267 * Returns the type library name. 05268 * 05269 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05270 * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library' 05271 */ 05272 static VALUE 05273 foletypelib_name(VALUE self) 05274 { 05275 ITypeLib *pTypeLib; 05276 HRESULT hr; 05277 BSTR bstr; 05278 VALUE name; 05279 pTypeLib = oletypelib_get_typelib(self); 05280 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, 05281 NULL, &bstr, NULL, NULL); 05282 05283 if (FAILED(hr)) { 05284 ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib"); 05285 } 05286 name = WC2VSTR(bstr); 05287 return rb_enc_str_new(StringValuePtr(name), strlen(StringValuePtr(name)), cWIN32OLE_enc); 05288 } 05289 05290 /* 05291 * call-seq: 05292 * WIN32OLE_TYPELIB#version -> The type library version. 05293 * 05294 * Returns the type library version. 05295 * 05296 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05297 * puts tlib.version #-> 1.3 05298 */ 05299 static VALUE 05300 foletypelib_version(VALUE self) 05301 { 05302 TLIBATTR *pTLibAttr; 05303 VALUE major; 05304 VALUE minor; 05305 ITypeLib *pTypeLib; 05306 05307 pTypeLib = oletypelib_get_typelib(self); 05308 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05309 major = INT2NUM(pTLibAttr->wMajorVerNum); 05310 minor = INT2NUM(pTLibAttr->wMinorVerNum); 05311 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05312 return rb_Float(make_version_str(major, minor)); 05313 } 05314 05315 /* 05316 * call-seq: 05317 * WIN32OLE_TYPELIB#major_version -> The type library major version. 05318 * 05319 * Returns the type library major version. 05320 * 05321 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05322 * puts tlib.major_version # -> 1 05323 */ 05324 static VALUE 05325 foletypelib_major_version(VALUE self) 05326 { 05327 TLIBATTR *pTLibAttr; 05328 VALUE major; 05329 ITypeLib *pTypeLib; 05330 pTypeLib = oletypelib_get_typelib(self); 05331 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05332 05333 major = INT2NUM(pTLibAttr->wMajorVerNum); 05334 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05335 return major; 05336 } 05337 05338 /* 05339 * call-seq: 05340 * WIN32OLE_TYPELIB#minor_version -> The type library minor version. 05341 * 05342 * Returns the type library minor version. 05343 * 05344 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05345 * puts tlib.minor_version # -> 3 05346 */ 05347 static VALUE 05348 foletypelib_minor_version(VALUE self) 05349 { 05350 TLIBATTR *pTLibAttr; 05351 VALUE minor; 05352 ITypeLib *pTypeLib; 05353 pTypeLib = oletypelib_get_typelib(self); 05354 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05355 minor = INT2NUM(pTLibAttr->wMinorVerNum); 05356 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05357 return minor; 05358 } 05359 05360 static VALUE 05361 oletypelib_path(VALUE guid, VALUE version) 05362 { 05363 int k; 05364 LONG err; 05365 HKEY hkey; 05366 HKEY hlang; 05367 VALUE lang; 05368 VALUE path = Qnil; 05369 05370 VALUE key = rb_str_new2("TypeLib\\"); 05371 rb_str_concat(key, guid); 05372 rb_str_cat2(key, "\\"); 05373 rb_str_concat(key, version); 05374 05375 err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey); 05376 if (err != ERROR_SUCCESS) { 05377 return Qnil; 05378 } 05379 for(k = 0; path == Qnil; k++) { 05380 lang = reg_enum_key(hkey, k); 05381 if (lang == Qnil) 05382 break; 05383 err = reg_open_vkey(hkey, lang, &hlang); 05384 if (err == ERROR_SUCCESS) { 05385 path = reg_get_typelib_file_path(hlang); 05386 RegCloseKey(hlang); 05387 } 05388 } 05389 RegCloseKey(hkey); 05390 return path; 05391 } 05392 05393 static HRESULT 05394 oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib) 05395 { 05396 VALUE path; 05397 OLECHAR *pBuf; 05398 HRESULT hr; 05399 path = oletypelib_path(guid, version); 05400 if (path == Qnil) { 05401 return E_UNEXPECTED; 05402 } 05403 pBuf = ole_vstr2wc(path); 05404 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib); 05405 SysFreeString(pBuf); 05406 return hr; 05407 } 05408 05409 /* 05410 * call-seq: 05411 * WIN32OLE_TYPELIB#path -> The type library file path. 05412 * 05413 * Returns the type library file path. 05414 * 05415 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05416 * puts tlib.path #-> 'C:\...\EXCEL9.OLB' 05417 */ 05418 static VALUE 05419 foletypelib_path(VALUE self) 05420 { 05421 TLIBATTR *pTLibAttr; 05422 HRESULT hr = S_OK; 05423 BSTR bstr; 05424 LCID lcid = cWIN32OLE_lcid; 05425 VALUE path; 05426 ITypeLib *pTypeLib; 05427 05428 pTypeLib = oletypelib_get_typelib(self); 05429 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05430 hr = QueryPathOfRegTypeLib(&pTLibAttr->guid, 05431 pTLibAttr->wMajorVerNum, 05432 pTLibAttr->wMinorVerNum, 05433 lcid, 05434 &bstr); 05435 if (FAILED(hr)) { 05436 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05437 ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib"); 05438 } 05439 05440 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05441 path = WC2VSTR(bstr); 05442 return rb_enc_str_new(StringValuePtr(path), strlen(StringValuePtr(path)), cWIN32OLE_enc); 05443 } 05444 05445 /* 05446 * call-seq: 05447 * WIN32OLE_TYPELIB#visible? 05448 * 05449 * Returns true if the type library information is not hidden. 05450 * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN, 05451 * the method returns false, otherwise, returns true. 05452 * If the method fails to access the TLIBATTR information, then 05453 * WIN32OLERuntimeError is raised. 05454 * 05455 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05456 * tlib.visible? # => true 05457 */ 05458 static VALUE 05459 foletypelib_visible(VALUE self) 05460 { 05461 ITypeLib *pTypeLib = NULL; 05462 VALUE visible = Qtrue; 05463 TLIBATTR *pTLibAttr; 05464 05465 pTypeLib = oletypelib_get_typelib(self); 05466 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05467 05468 if ((pTLibAttr->wLibFlags == 0) || 05469 (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) || 05470 (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) { 05471 visible = Qfalse; 05472 } 05473 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05474 return visible; 05475 } 05476 05477 /* 05478 * call-seq: 05479 * WIN32OLE_TYPELIB#library_name 05480 * 05481 * Returns library name. 05482 * If the method fails to access library name, WIN32OLERuntimeError is raised. 05483 * 05484 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05485 * tlib.library_name # => Excel 05486 */ 05487 static VALUE 05488 foletypelib_library_name(VALUE self) 05489 { 05490 HRESULT hr; 05491 ITypeLib *pTypeLib = NULL; 05492 VALUE libname = Qnil; 05493 BSTR bstr; 05494 05495 pTypeLib = oletypelib_get_typelib(self); 05496 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, 05497 &bstr, NULL, NULL, NULL); 05498 if (FAILED(hr)) { 05499 ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name"); 05500 } 05501 libname = WC2VSTR(bstr); 05502 return libname; 05503 } 05504 05505 05506 /* 05507 * call-seq: 05508 * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library. 05509 * 05510 * Returns the type library file path. 05511 * 05512 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05513 * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...] 05514 */ 05515 static VALUE 05516 foletypelib_ole_types(VALUE self) 05517 { 05518 ITypeLib *pTypeLib = NULL; 05519 VALUE classes = rb_ary_new(); 05520 pTypeLib = oletypelib_get_typelib(self); 05521 ole_types_from_typelib(pTypeLib, classes); 05522 return classes; 05523 } 05524 05525 /* 05526 * call-seq: 05527 * WIN32OLE_TYPELIB#inspect -> String 05528 * 05529 * Returns the type library name with class name. 05530 * 05531 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05532 * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>" 05533 */ 05534 static VALUE 05535 foletypelib_inspect(VALUE self) 05536 { 05537 return default_inspect(self, "WIN32OLE_TYPELIB"); 05538 } 05539 05540 /* 05541 * Document-class: WIN32OLE_TYPE 05542 * 05543 * <code>WIN32OLE_TYPE</code> objects represent OLE type libarary information. 05544 */ 05545 05546 /* 05547 * call-seq: 05548 * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object 05549 * 05550 * Returns a new WIN32OLE_TYPE object. 05551 * The first argument <i>typelib</i> specifies OLE type library name. 05552 * The second argument specifies OLE class name. 05553 * 05554 * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05555 * # => WIN32OLE_TYPE object of Application class of Excel. 05556 */ 05557 static VALUE 05558 foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) 05559 { 05560 VALUE file; 05561 OLECHAR * pbuf; 05562 ITypeLib *pTypeLib; 05563 HRESULT hr; 05564 05565 SafeStringValue(oleclass); 05566 SafeStringValue(typelib); 05567 file = typelib_file(typelib); 05568 if (file == Qnil) { 05569 file = typelib; 05570 } 05571 pbuf = ole_vstr2wc(file); 05572 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); 05573 if (FAILED(hr)) 05574 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); 05575 SysFreeString(pbuf); 05576 if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) { 05577 OLE_RELEASE(pTypeLib); 05578 rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`", 05579 StringValuePtr(oleclass), StringValuePtr(typelib)); 05580 } 05581 OLE_RELEASE(pTypeLib); 05582 return self; 05583 } 05584 05585 /* 05586 * call-seq: 05587 * WIN32OLE_TYPE#name #=> OLE type name 05588 * 05589 * Returns OLE type name. 05590 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05591 * puts tobj.name # => Application 05592 */ 05593 static VALUE 05594 foletype_name(VALUE self) 05595 { 05596 return rb_ivar_get(self, rb_intern("name")); 05597 } 05598 05599 static VALUE 05600 ole_ole_type(ITypeInfo *pTypeInfo) 05601 { 05602 HRESULT hr; 05603 TYPEATTR *pTypeAttr; 05604 VALUE type = Qnil; 05605 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05606 if(FAILED(hr)){ 05607 return type; 05608 } 05609 switch(pTypeAttr->typekind) { 05610 case TKIND_ENUM: 05611 type = rb_str_new2("Enum"); 05612 break; 05613 case TKIND_RECORD: 05614 type = rb_str_new2("Record"); 05615 break; 05616 case TKIND_MODULE: 05617 type = rb_str_new2("Module"); 05618 break; 05619 case TKIND_INTERFACE: 05620 type = rb_str_new2("Interface"); 05621 break; 05622 case TKIND_DISPATCH: 05623 type = rb_str_new2("Dispatch"); 05624 break; 05625 case TKIND_COCLASS: 05626 type = rb_str_new2("Class"); 05627 break; 05628 case TKIND_ALIAS: 05629 type = rb_str_new2("Alias"); 05630 break; 05631 case TKIND_UNION: 05632 type = rb_str_new2("Union"); 05633 break; 05634 case TKIND_MAX: 05635 type = rb_str_new2("Max"); 05636 break; 05637 default: 05638 type = Qnil; 05639 break; 05640 } 05641 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05642 return type; 05643 } 05644 05645 /* 05646 * call-seq: 05647 * WIN32OLE_TYPE#ole_type #=> OLE type string. 05648 * 05649 * returns type of OLE class. 05650 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05651 * puts tobj.ole_type # => Class 05652 */ 05653 static VALUE 05654 foletype_ole_type(VALUE self) 05655 { 05656 struct oletypedata *ptype; 05657 Data_Get_Struct(self, struct oletypedata, ptype); 05658 return ole_ole_type(ptype->pTypeInfo); 05659 } 05660 05661 static VALUE 05662 ole_type_guid(ITypeInfo *pTypeInfo) 05663 { 05664 HRESULT hr; 05665 TYPEATTR *pTypeAttr; 05666 int len; 05667 OLECHAR bstr[80]; 05668 VALUE guid = Qnil; 05669 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05670 if (FAILED(hr)) 05671 return guid; 05672 len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 05673 if (len > 3) { 05674 guid = ole_wc2vstr(bstr, FALSE); 05675 } 05676 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05677 return guid; 05678 } 05679 05680 /* 05681 * call-seq: 05682 * WIN32OLE_TYPE#guid #=> GUID 05683 * 05684 * Returns GUID. 05685 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05686 * puts tobj.guid # => {00024500-0000-0000-C000-000000000046} 05687 */ 05688 static VALUE 05689 foletype_guid(VALUE self) 05690 { 05691 struct oletypedata *ptype; 05692 Data_Get_Struct(self, struct oletypedata, ptype); 05693 return ole_type_guid(ptype->pTypeInfo); 05694 } 05695 05696 static VALUE 05697 ole_type_progid(ITypeInfo *pTypeInfo) 05698 { 05699 HRESULT hr; 05700 TYPEATTR *pTypeAttr; 05701 OLECHAR *pbuf; 05702 VALUE progid = Qnil; 05703 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05704 if (FAILED(hr)) 05705 return progid; 05706 hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf); 05707 if (SUCCEEDED(hr)) { 05708 progid = ole_wc2vstr(pbuf, FALSE); 05709 CoTaskMemFree(pbuf); 05710 } 05711 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05712 return progid; 05713 } 05714 05715 /* 05716 * call-seq: 05717 * WIN32OLE_TYPE#progid #=> ProgID 05718 * 05719 * Returns ProgID if it exists. If not found, then returns nil. 05720 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05721 * puts tobj.progid # => Excel.Application.9 05722 */ 05723 static VALUE 05724 foletype_progid(VALUE self) 05725 { 05726 struct oletypedata *ptype; 05727 Data_Get_Struct(self, struct oletypedata, ptype); 05728 return ole_type_progid(ptype->pTypeInfo); 05729 } 05730 05731 05732 static VALUE 05733 ole_type_visible(ITypeInfo *pTypeInfo) 05734 { 05735 HRESULT hr; 05736 TYPEATTR *pTypeAttr; 05737 VALUE visible; 05738 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05739 if (FAILED(hr)) 05740 return Qtrue; 05741 if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) { 05742 visible = Qfalse; 05743 } else { 05744 visible = Qtrue; 05745 } 05746 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05747 return visible; 05748 } 05749 05750 /* 05751 * call-seq: 05752 * WIN32OLE_TYPE#visible #=> true or false 05753 * 05754 * Returns true if the OLE class is public. 05755 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05756 * puts tobj.visible # => true 05757 */ 05758 static VALUE 05759 foletype_visible(VALUE self) 05760 { 05761 struct oletypedata *ptype; 05762 Data_Get_Struct(self, struct oletypedata, ptype); 05763 return ole_type_visible(ptype->pTypeInfo); 05764 } 05765 05766 static VALUE 05767 ole_type_major_version(ITypeInfo *pTypeInfo) 05768 { 05769 VALUE ver; 05770 TYPEATTR *pTypeAttr; 05771 HRESULT hr; 05772 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05773 if (FAILED(hr)) 05774 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 05775 ver = INT2FIX(pTypeAttr->wMajorVerNum); 05776 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05777 return ver; 05778 } 05779 05780 /* 05781 * call-seq: 05782 * WIN32OLE_TYPE#major_version 05783 * 05784 * Returns major version. 05785 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 05786 * puts tobj.major_version # => 8 05787 */ 05788 static VALUE 05789 foletype_major_version(VALUE self) 05790 { 05791 struct oletypedata *ptype; 05792 Data_Get_Struct(self, struct oletypedata, ptype); 05793 return ole_type_major_version(ptype->pTypeInfo); 05794 } 05795 05796 static VALUE 05797 ole_type_minor_version(ITypeInfo *pTypeInfo) 05798 { 05799 VALUE ver; 05800 TYPEATTR *pTypeAttr; 05801 HRESULT hr; 05802 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05803 if (FAILED(hr)) 05804 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 05805 ver = INT2FIX(pTypeAttr->wMinorVerNum); 05806 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05807 return ver; 05808 } 05809 05810 /* 05811 * call-seq: 05812 * WIN32OLE_TYPE#minor_version #=> OLE minor version 05813 * 05814 * Returns minor version. 05815 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 05816 * puts tobj.minor_version # => 2 05817 */ 05818 static VALUE 05819 foletype_minor_version(VALUE self) 05820 { 05821 struct oletypedata *ptype; 05822 Data_Get_Struct(self, struct oletypedata, ptype); 05823 return ole_type_minor_version(ptype->pTypeInfo); 05824 } 05825 05826 static VALUE 05827 ole_type_typekind(ITypeInfo *pTypeInfo) 05828 { 05829 VALUE typekind; 05830 TYPEATTR *pTypeAttr; 05831 HRESULT hr; 05832 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05833 if (FAILED(hr)) 05834 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 05835 typekind = INT2FIX(pTypeAttr->typekind); 05836 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05837 return typekind; 05838 } 05839 05840 /* 05841 * call-seq: 05842 * WIN32OLE_TYPE#typekind #=> number of type. 05843 * 05844 * Returns number which represents type. 05845 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 05846 * puts tobj.typekind # => 4 05847 * 05848 */ 05849 static VALUE 05850 foletype_typekind(VALUE self) 05851 { 05852 struct oletypedata *ptype; 05853 Data_Get_Struct(self, struct oletypedata, ptype); 05854 return ole_type_typekind(ptype->pTypeInfo); 05855 } 05856 05857 static VALUE 05858 ole_type_helpstring(ITypeInfo *pTypeInfo) 05859 { 05860 HRESULT hr; 05861 BSTR bhelpstr; 05862 hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL); 05863 if(FAILED(hr)) { 05864 return Qnil; 05865 } 05866 return WC2VSTR(bhelpstr); 05867 } 05868 05869 /* 05870 * call-seq: 05871 * WIN32OLE_TYPE#helpstring #=> help string. 05872 * 05873 * Returns help string. 05874 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') 05875 * puts tobj.helpstring # => Web Browser interface 05876 */ 05877 static VALUE 05878 foletype_helpstring(VALUE self) 05879 { 05880 struct oletypedata *ptype; 05881 Data_Get_Struct(self, struct oletypedata, ptype); 05882 return ole_type_helpstring(ptype->pTypeInfo); 05883 } 05884 05885 static VALUE 05886 ole_type_src_type(ITypeInfo *pTypeInfo) 05887 { 05888 HRESULT hr; 05889 TYPEATTR *pTypeAttr; 05890 VALUE alias = Qnil; 05891 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05892 if (FAILED(hr)) 05893 return alias; 05894 if(pTypeAttr->typekind != TKIND_ALIAS) { 05895 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05896 return alias; 05897 } 05898 alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil); 05899 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05900 return alias; 05901 } 05902 05903 /* 05904 * call-seq: 05905 * WIN32OLE_TYPE#src_type #=> OLE source class 05906 * 05907 * Returns source class when the OLE class is 'Alias'. 05908 * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType') 05909 * puts tobj.src_type # => I4 05910 * 05911 */ 05912 static VALUE 05913 foletype_src_type(VALUE self) 05914 { 05915 struct oletypedata *ptype; 05916 Data_Get_Struct(self, struct oletypedata, ptype); 05917 return ole_type_src_type(ptype->pTypeInfo); 05918 } 05919 05920 static VALUE 05921 ole_type_helpfile(ITypeInfo *pTypeInfo) 05922 { 05923 HRESULT hr; 05924 BSTR bhelpfile; 05925 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile); 05926 if(FAILED(hr)) { 05927 return Qnil; 05928 } 05929 return WC2VSTR(bhelpfile); 05930 } 05931 05932 /* 05933 * call-seq: 05934 * WIN32OLE_TYPE#helpfile 05935 * 05936 * Returns helpfile path. If helpfile is not found, then returns nil. 05937 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 05938 * puts tobj.helpfile # => C:\...\VBAXL9.CHM 05939 * 05940 */ 05941 static VALUE 05942 foletype_helpfile(VALUE self) 05943 { 05944 struct oletypedata *ptype; 05945 Data_Get_Struct(self, struct oletypedata, ptype); 05946 return ole_type_helpfile(ptype->pTypeInfo); 05947 } 05948 05949 static VALUE 05950 ole_type_helpcontext(ITypeInfo *pTypeInfo) 05951 { 05952 HRESULT hr; 05953 DWORD helpcontext; 05954 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, 05955 &helpcontext, NULL); 05956 if(FAILED(hr)) 05957 return Qnil; 05958 return INT2FIX(helpcontext); 05959 } 05960 05961 /* 05962 * call-seq: 05963 * WIN32OLE_TYPE#helpcontext 05964 * 05965 * Returns helpcontext. If helpcontext is not found, then returns nil. 05966 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 05967 * puts tobj.helpfile # => 131185 05968 */ 05969 static VALUE 05970 foletype_helpcontext(VALUE self) 05971 { 05972 struct oletypedata *ptype; 05973 Data_Get_Struct(self, struct oletypedata, ptype); 05974 return ole_type_helpcontext(ptype->pTypeInfo); 05975 } 05976 05977 /* 05978 * call-seq: 05979 * WIN32OLE_TYPE#ole_typelib 05980 * 05981 * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE 05982 * object. If it is not found, then returns nil. 05983 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 05984 * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library' 05985 */ 05986 static VALUE 05987 foletype_ole_typelib(VALUE self) 05988 { 05989 struct oletypedata *ptype; 05990 Data_Get_Struct(self, struct oletypedata, ptype); 05991 return ole_typelib_from_itypeinfo(ptype->pTypeInfo); 05992 } 05993 05994 static VALUE 05995 ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) 05996 { 05997 HRESULT hr; 05998 ITypeInfo *pRefTypeInfo; 05999 HREFTYPE href; 06000 WORD i; 06001 VALUE type; 06002 TYPEATTR *pTypeAttr; 06003 int flags; 06004 06005 VALUE types = rb_ary_new(); 06006 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 06007 if (FAILED(hr)) { 06008 return types; 06009 } 06010 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 06011 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 06012 if (FAILED(hr)) 06013 continue; 06014 06015 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 06016 if (FAILED(hr)) 06017 continue; 06018 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 06019 if (FAILED(hr)) 06020 continue; 06021 06022 if ((flags & implflags) == implflags) { 06023 type = ole_type_from_itypeinfo(pRefTypeInfo); 06024 if (type != Qnil) { 06025 rb_ary_push(types, type); 06026 } 06027 } 06028 06029 OLE_RELEASE(pRefTypeInfo); 06030 } 06031 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 06032 return types; 06033 } 06034 06035 /* 06036 * call-seq: 06037 * WIN32OLE_TYPE#implemented_ole_types 06038 * 06039 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06040 * object. 06041 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 06042 * p tobj.implemented_ole_types # => [_Worksheet, DocEvents] 06043 */ 06044 static VALUE 06045 foletype_impl_ole_types(VALUE self) 06046 { 06047 struct oletypedata *ptype; 06048 Data_Get_Struct(self, struct oletypedata, ptype); 06049 return ole_type_impl_ole_types(ptype->pTypeInfo, 0); 06050 } 06051 06052 /* 06053 * call-seq: 06054 * WIN32OLE_TYPE#source_ole_types 06055 * 06056 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06057 * object and having IMPLTYPEFLAG_FSOURCE. 06058 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 06059 * p tobj.source_ole_types 06060 * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>] 06061 */ 06062 static VALUE 06063 foletype_source_ole_types(VALUE self) 06064 { 06065 struct oletypedata *ptype; 06066 Data_Get_Struct(self, struct oletypedata, ptype); 06067 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE); 06068 } 06069 06070 /* 06071 * call-seq: 06072 * WIN32OLE_TYPE#default_event_sources 06073 * 06074 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06075 * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. 06076 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 06077 * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>] 06078 */ 06079 static VALUE 06080 foletype_default_event_sources(VALUE self) 06081 { 06082 struct oletypedata *ptype; 06083 Data_Get_Struct(self, struct oletypedata, ptype); 06084 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT); 06085 } 06086 06087 /* 06088 * call-seq: 06089 * WIN32OLE_TYPE#default_ole_types 06090 * 06091 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06092 * object and having IMPLTYPEFLAG_FDEFAULT. 06093 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 06094 * p tobj.default_ole_types 06095 * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>] 06096 */ 06097 static VALUE 06098 foletype_default_ole_types(VALUE self) 06099 { 06100 struct oletypedata *ptype; 06101 Data_Get_Struct(self, struct oletypedata, ptype); 06102 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT); 06103 } 06104 06105 /* 06106 * call-seq: 06107 * WIN32OLE_TYPE#inspect -> String 06108 * 06109 * Returns the type name with class name. 06110 * 06111 * ie = WIN32OLE.new('InternetExplorer.Application') 06112 * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2> 06113 */ 06114 static VALUE 06115 foletype_inspect(VALUE self) 06116 { 06117 return default_inspect(self, "WIN32OLE_TYPE"); 06118 } 06119 06120 static VALUE 06121 ole_variables(ITypeInfo *pTypeInfo) 06122 { 06123 HRESULT hr; 06124 TYPEATTR *pTypeAttr; 06125 WORD i; 06126 UINT len; 06127 BSTR bstr; 06128 VARDESC *pVarDesc; 06129 struct olevariabledata *pvar; 06130 VALUE var; 06131 VALUE variables = rb_ary_new(); 06132 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 06133 if (FAILED(hr)) { 06134 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 06135 } 06136 06137 for(i = 0; i < pTypeAttr->cVars; i++) { 06138 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc); 06139 if(FAILED(hr)) 06140 continue; 06141 len = 0; 06142 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 06143 1, &len); 06144 if(FAILED(hr) || len == 0 || !bstr) 06145 continue; 06146 06147 var = Data_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata, 06148 0,olevariable_free,pvar); 06149 pvar->pTypeInfo = pTypeInfo; 06150 OLE_ADDREF(pTypeInfo); 06151 pvar->index = i; 06152 rb_ivar_set(var, rb_intern("name"), WC2VSTR(bstr)); 06153 rb_ary_push(variables, var); 06154 06155 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06156 pVarDesc = NULL; 06157 } 06158 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 06159 return variables; 06160 } 06161 06162 /* 06163 * call-seq: 06164 * WIN32OLE_TYPE#variables 06165 * 06166 * Returns array of WIN32OLE_VARIABLE objects which represent variables 06167 * defined in OLE class. 06168 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06169 * vars = tobj.variables 06170 * vars.each do |v| 06171 * puts "#{v.name} = #{v.value}" 06172 * end 06173 * 06174 * The result of above sample script is follows: 06175 * xlChart = -4109 06176 * xlDialogSheet = -4116 06177 * xlExcel4IntlMacroSheet = 4 06178 * xlExcel4MacroSheet = 3 06179 * xlWorksheet = -4167 06180 * 06181 */ 06182 static VALUE 06183 foletype_variables(VALUE self) 06184 { 06185 struct oletypedata *ptype; 06186 Data_Get_Struct(self, struct oletypedata, ptype); 06187 return ole_variables(ptype->pTypeInfo); 06188 } 06189 06190 /* 06191 * call-seq: 06192 * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects. 06193 * 06194 * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in 06195 * OLE type library. 06196 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 06197 * methods = tobj.ole_methods.collect{|m| 06198 * m.name 06199 * } 06200 * # => ['Activate', 'Copy', 'Delete',....] 06201 */ 06202 static VALUE 06203 foletype_methods(VALUE self) 06204 { 06205 struct oletypedata *ptype; 06206 Data_Get_Struct(self, struct oletypedata, ptype); 06207 return ole_methods_from_typeinfo(ptype->pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); 06208 } 06209 06210 /* 06211 * Document-class: WIN32OLE_VARIABLE 06212 * 06213 * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information. 06214 */ 06215 06216 /* 06217 * call-seq: 06218 * WIN32OLE_VARIABLE#name 06219 * 06220 * Returns the name of variable. 06221 * 06222 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06223 * variables = tobj.variables 06224 * variables.each do |variable| 06225 * puts "#{variable.name}" 06226 * end 06227 * 06228 * The result of above script is following: 06229 * xlChart 06230 * xlDialogSheet 06231 * xlExcel4IntlMacroSheet 06232 * xlExcel4MacroSheet 06233 * xlWorksheet 06234 * 06235 */ 06236 static VALUE 06237 folevariable_name(VALUE self) 06238 { 06239 return rb_ivar_get(self, rb_intern("name")); 06240 } 06241 06242 static VALUE 06243 ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index) 06244 { 06245 VARDESC *pVarDesc; 06246 HRESULT hr; 06247 VALUE type; 06248 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06249 if (FAILED(hr)) 06250 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); 06251 type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil); 06252 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06253 return type; 06254 } 06255 06256 /* 06257 * call-seq: 06258 * WIN32OLE_VARIABLE#ole_type 06259 * 06260 * Returns OLE type string. 06261 * 06262 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06263 * variables = tobj.variables 06264 * variables.each do |variable| 06265 * puts "#{variable.ole_type} #{variable.name}" 06266 * end 06267 * 06268 * The result of above script is following: 06269 * INT xlChart 06270 * INT xlDialogSheet 06271 * INT xlExcel4IntlMacroSheet 06272 * INT xlExcel4MacroSheet 06273 * INT xlWorksheet 06274 * 06275 */ 06276 static VALUE 06277 folevariable_ole_type(VALUE self) 06278 { 06279 struct olevariabledata *pvar; 06280 Data_Get_Struct(self, struct olevariabledata, pvar); 06281 return ole_variable_ole_type(pvar->pTypeInfo, pvar->index); 06282 } 06283 06284 static VALUE 06285 ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index) 06286 { 06287 VARDESC *pVarDesc; 06288 HRESULT hr; 06289 VALUE type = rb_ary_new(); 06290 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06291 if (FAILED(hr)) 06292 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); 06293 ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type); 06294 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06295 return type; 06296 } 06297 06298 /* 06299 * call-seq: 06300 * WIN32OLE_VARIABLE#ole_type_detail 06301 * 06302 * Returns detail information of type. The information is array of type. 06303 * 06304 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS') 06305 * variable = tobj.variables.find {|variable| variable.name == 'lFlags'} 06306 * tdetail = variable.ole_type_detail 06307 * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"] 06308 * 06309 */ 06310 static VALUE 06311 folevariable_ole_type_detail(VALUE self) 06312 { 06313 struct olevariabledata *pvar; 06314 Data_Get_Struct(self, struct olevariabledata, pvar); 06315 return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index); 06316 } 06317 06318 static VALUE 06319 ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index) 06320 { 06321 VARDESC *pVarDesc; 06322 HRESULT hr; 06323 VALUE val = Qnil; 06324 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06325 if (FAILED(hr)) 06326 return Qnil; 06327 if(pVarDesc->varkind == VAR_CONST) 06328 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); 06329 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06330 return val; 06331 } 06332 06333 /* 06334 * call-seq: 06335 * WIN32OLE_VARIABLE#value 06336 * 06337 * Returns value if value is exists. If the value does not exist, 06338 * this method returns nil. 06339 * 06340 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06341 * variables = tobj.variables 06342 * variables.each do |variable| 06343 * puts "#{variable.name} #{variable.value}" 06344 * end 06345 * 06346 * The result of above script is following: 06347 * xlChart = -4109 06348 * xlDialogSheet = -4116 06349 * xlExcel4IntlMacroSheet = 4 06350 * xlExcel4MacroSheet = 3 06351 * xlWorksheet = -4167 06352 * 06353 */ 06354 static VALUE 06355 folevariable_value(VALUE self) 06356 { 06357 struct olevariabledata *pvar; 06358 Data_Get_Struct(self, struct olevariabledata, pvar); 06359 return ole_variable_value(pvar->pTypeInfo, pvar->index); 06360 } 06361 06362 static VALUE 06363 ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index) 06364 { 06365 VARDESC *pVarDesc; 06366 HRESULT hr; 06367 VALUE visible = Qfalse; 06368 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06369 if (FAILED(hr)) 06370 return visible; 06371 if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | 06372 VARFLAG_FRESTRICTED | 06373 VARFLAG_FNONBROWSABLE))) { 06374 visible = Qtrue; 06375 } 06376 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06377 return visible; 06378 } 06379 06380 /* 06381 * call-seq: 06382 * WIN32OLE_VARIABLE#visible? 06383 * 06384 * Returns true if the variable is public. 06385 * 06386 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06387 * variables = tobj.variables 06388 * variables.each do |variable| 06389 * puts "#{variable.name} #{variable.visible?}" 06390 * end 06391 * 06392 * The result of above script is following: 06393 * xlChart true 06394 * xlDialogSheet true 06395 * xlExcel4IntlMacroSheet true 06396 * xlExcel4MacroSheet true 06397 * xlWorksheet true 06398 * 06399 */ 06400 static VALUE 06401 folevariable_visible(VALUE self) 06402 { 06403 struct olevariabledata *pvar; 06404 Data_Get_Struct(self, struct olevariabledata, pvar); 06405 return ole_variable_visible(pvar->pTypeInfo, pvar->index); 06406 } 06407 06408 static VALUE 06409 ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index) 06410 { 06411 VARDESC *pVarDesc; 06412 HRESULT hr; 06413 VALUE kind = rb_str_new2("UNKNOWN"); 06414 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06415 if (FAILED(hr)) 06416 return kind; 06417 switch(pVarDesc->varkind) { 06418 case VAR_PERINSTANCE: 06419 kind = rb_str_new2("PERINSTANCE"); 06420 break; 06421 case VAR_STATIC: 06422 kind = rb_str_new2("STATIC"); 06423 break; 06424 case VAR_CONST: 06425 kind = rb_str_new2("CONSTANT"); 06426 break; 06427 case VAR_DISPATCH: 06428 kind = rb_str_new2("DISPATCH"); 06429 break; 06430 default: 06431 break; 06432 } 06433 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06434 return kind; 06435 } 06436 06437 /* 06438 * call-seq: 06439 * WIN32OLE_VARIABLE#variable_kind 06440 * 06441 * Returns variable kind string. 06442 * 06443 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06444 * variables = tobj.variables 06445 * variables.each do |variable| 06446 * puts "#{variable.name} #{variable.variable_kind}" 06447 * end 06448 * 06449 * The result of above script is following: 06450 * xlChart CONSTANT 06451 * xlDialogSheet CONSTANT 06452 * xlExcel4IntlMacroSheet CONSTANT 06453 * xlExcel4MacroSheet CONSTANT 06454 * xlWorksheet CONSTANT 06455 */ 06456 static VALUE 06457 folevariable_variable_kind(VALUE self) 06458 { 06459 struct olevariabledata *pvar; 06460 Data_Get_Struct(self, struct olevariabledata, pvar); 06461 return ole_variable_kind(pvar->pTypeInfo, pvar->index); 06462 } 06463 06464 static VALUE 06465 ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index) 06466 { 06467 VARDESC *pVarDesc; 06468 HRESULT hr; 06469 VALUE kind = Qnil; 06470 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06471 if (FAILED(hr)) 06472 return kind; 06473 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06474 kind = INT2FIX(pVarDesc->varkind); 06475 return kind; 06476 } 06477 06478 /* 06479 * call-seq: 06480 * WIN32OLE_VARIABLE#varkind 06481 * 06482 * Returns the number which represents variable kind. 06483 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06484 * variables = tobj.variables 06485 * variables.each do |variable| 06486 * puts "#{variable.name} #{variable.varkind}" 06487 * end 06488 * 06489 * The result of above script is following: 06490 * xlChart 2 06491 * xlDialogSheet 2 06492 * xlExcel4IntlMacroSheet 2 06493 * xlExcel4MacroSheet 2 06494 * xlWorksheet 2 06495 */ 06496 static VALUE 06497 folevariable_varkind(VALUE self) 06498 { 06499 struct olevariabledata *pvar; 06500 Data_Get_Struct(self, struct olevariabledata, pvar); 06501 return ole_variable_varkind(pvar->pTypeInfo, pvar->index); 06502 } 06503 06504 /* 06505 * call-seq: 06506 * WIN32OLE_VARIABLE#inspect -> String 06507 * 06508 * Returns the OLE variable name and the value with class name. 06509 * 06510 */ 06511 static VALUE 06512 folevariable_inspect(VALUE self) 06513 { 06514 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0); 06515 rb_str_cat2(detail, "="); 06516 rb_str_concat(detail, rb_funcall(rb_funcall(self, rb_intern("value"), 0), rb_intern("inspect"), 0)); 06517 return make_inspect("WIN32OLE_VARIABLE", detail); 06518 } 06519 06520 /* 06521 * Document-class: WIN32OLE_METHOD 06522 * 06523 * <code>WIN32OLE_METHOD</code> objects represent OLE method information. 06524 */ 06525 06526 static VALUE 06527 olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name) 06528 { 06529 struct olemethoddata *pmethod; 06530 Data_Get_Struct(self, struct olemethoddata, pmethod); 06531 pmethod->pTypeInfo = pTypeInfo; 06532 OLE_ADDREF(pTypeInfo); 06533 pmethod->pOwnerTypeInfo = pOwnerTypeInfo; 06534 if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo); 06535 pmethod->index = index; 06536 rb_ivar_set(self, rb_intern("name"), name); 06537 return self; 06538 } 06539 06540 static VALUE 06541 folemethod_s_allocate(VALUE klass) 06542 { 06543 struct olemethoddata *pmethod; 06544 VALUE obj; 06545 obj = Data_Make_Struct(klass, 06546 struct olemethoddata, 06547 0, olemethod_free, pmethod); 06548 pmethod->pTypeInfo = NULL; 06549 pmethod->pOwnerTypeInfo = NULL; 06550 pmethod->index = 0; 06551 return obj; 06552 } 06553 06554 /* 06555 * call-seq: 06556 * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object 06557 * 06558 * Returns a new WIN32OLE_METHOD object which represents the information 06559 * about OLE method. 06560 * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object. 06561 * The second argument <i>method</i> specifies OLE method name defined OLE class 06562 * which represents WIN32OLE_TYPE object. 06563 * 06564 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06565 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 06566 */ 06567 static VALUE 06568 folemethod_initialize(VALUE self, VALUE oletype, VALUE method) 06569 { 06570 struct oletypedata *ptype; 06571 VALUE obj = Qnil; 06572 if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) { 06573 SafeStringValue(method); 06574 Data_Get_Struct(oletype, struct oletypedata, ptype); 06575 obj = olemethod_from_typeinfo(self, ptype->pTypeInfo, method); 06576 if (obj == Qnil) { 06577 rb_raise(eWIN32OLERuntimeError, "not found %s", 06578 StringValuePtr(method)); 06579 } 06580 } 06581 else { 06582 rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); 06583 } 06584 return obj; 06585 } 06586 06587 /* 06588 * call-seq 06589 * WIN32OLE_METHOD#name 06590 * 06591 * Returns the name of the method. 06592 * 06593 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06594 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 06595 * puts method.name # => SaveAs 06596 * 06597 */ 06598 static VALUE 06599 folemethod_name(VALUE self) 06600 { 06601 return rb_ivar_get(self, rb_intern("name")); 06602 } 06603 06604 static VALUE 06605 ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) 06606 { 06607 FUNCDESC *pFuncDesc; 06608 HRESULT hr; 06609 VALUE type; 06610 06611 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06612 if (FAILED(hr)) 06613 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 06614 06615 type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil); 06616 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06617 return type; 06618 } 06619 06620 /* 06621 * call-seq: 06622 * WIN32OLE_METHOD#return_type 06623 * 06624 * Returns string of return value type of method. 06625 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06626 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06627 * puts method.return_type # => Workbook 06628 * 06629 */ 06630 static VALUE 06631 folemethod_return_type(VALUE self) 06632 { 06633 struct olemethoddata *pmethod; 06634 Data_Get_Struct(self, struct olemethoddata, pmethod); 06635 return ole_method_return_type(pmethod->pTypeInfo, pmethod->index); 06636 } 06637 06638 static VALUE 06639 ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) 06640 { 06641 FUNCDESC *pFuncDesc; 06642 HRESULT hr; 06643 VALUE vvt; 06644 06645 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06646 if (FAILED(hr)) 06647 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 06648 06649 vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt); 06650 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06651 return vvt; 06652 } 06653 06654 /* 06655 * call-seq: 06656 * WIN32OLE_METHOD#return_vtype 06657 * 06658 * Returns number of return value type of method. 06659 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06660 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06661 * puts method.return_vtype # => 26 06662 * 06663 */ 06664 static VALUE 06665 folemethod_return_vtype(VALUE self) 06666 { 06667 struct olemethoddata *pmethod; 06668 Data_Get_Struct(self, struct olemethoddata, pmethod); 06669 return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index); 06670 } 06671 06672 static VALUE 06673 ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) 06674 { 06675 FUNCDESC *pFuncDesc; 06676 HRESULT hr; 06677 VALUE type = rb_ary_new(); 06678 06679 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06680 if (FAILED(hr)) 06681 return type; 06682 06683 ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type); 06684 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06685 return type; 06686 } 06687 06688 /* 06689 * call-seq: 06690 * WIN32OLE_METHOD#return_type_detail 06691 * 06692 * Returns detail information of return value type of method. 06693 * The information is array. 06694 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06695 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06696 * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] 06697 */ 06698 static VALUE 06699 folemethod_return_type_detail(VALUE self) 06700 { 06701 struct olemethoddata *pmethod; 06702 Data_Get_Struct(self, struct olemethoddata, pmethod); 06703 return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index); 06704 } 06705 06706 static VALUE 06707 ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index) 06708 { 06709 FUNCDESC *pFuncDesc; 06710 HRESULT hr; 06711 VALUE invkind; 06712 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06713 if(FAILED(hr)) 06714 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 06715 invkind = INT2FIX(pFuncDesc->invkind); 06716 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06717 return invkind; 06718 } 06719 06720 static VALUE 06721 ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) 06722 { 06723 VALUE type = rb_str_new2("UNKNOWN"); 06724 VALUE invkind = ole_method_invkind(pTypeInfo, method_index); 06725 if((FIX2INT(invkind) & INVOKE_PROPERTYGET) && 06726 (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) { 06727 type = rb_str_new2("PROPERTY"); 06728 } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) { 06729 type = rb_str_new2("PROPERTYGET"); 06730 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) { 06731 type = rb_str_new2("PROPERTYPUT"); 06732 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) { 06733 type = rb_str_new2("PROPERTYPUTREF"); 06734 } else if(FIX2INT(invkind) & INVOKE_FUNC) { 06735 type = rb_str_new2("FUNC"); 06736 } 06737 return type; 06738 } 06739 06740 /* 06741 * call-seq: 06742 * WIN32OLE_MTHOD#invkind 06743 * 06744 * Returns the method invoke kind. 06745 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06746 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06747 * puts method.invkind # => 1 06748 * 06749 */ 06750 static VALUE 06751 folemethod_invkind(VALUE self) 06752 { 06753 struct olemethoddata *pmethod; 06754 Data_Get_Struct(self, struct olemethoddata, pmethod); 06755 return ole_method_invkind(pmethod->pTypeInfo, pmethod->index); 06756 } 06757 06758 /* 06759 * call-seq: 06760 * WIN32OLE_METHOD#invoke_kind 06761 * 06762 * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" 06763 * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" 06764 * or "FUNC". 06765 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06766 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06767 * puts method.invoke_kind # => "FUNC" 06768 */ 06769 static VALUE 06770 folemethod_invoke_kind(VALUE self) 06771 { 06772 struct olemethoddata *pmethod; 06773 Data_Get_Struct(self, struct olemethoddata, pmethod); 06774 return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index); 06775 } 06776 06777 static VALUE 06778 ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) 06779 { 06780 FUNCDESC *pFuncDesc; 06781 HRESULT hr; 06782 VALUE visible; 06783 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06784 if(FAILED(hr)) 06785 return Qfalse; 06786 if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED | 06787 FUNCFLAG_FHIDDEN | 06788 FUNCFLAG_FNONBROWSABLE)) { 06789 visible = Qfalse; 06790 } else { 06791 visible = Qtrue; 06792 } 06793 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06794 return visible; 06795 } 06796 06797 /* 06798 * call-seq: 06799 * WIN32OLE_METHOD#visible? 06800 * 06801 * Returns true if the method is public. 06802 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06803 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06804 * puts method.visible? # => true 06805 */ 06806 static VALUE 06807 folemethod_visible(VALUE self) 06808 { 06809 struct olemethoddata *pmethod; 06810 Data_Get_Struct(self, struct olemethoddata, pmethod); 06811 return ole_method_visible(pmethod->pTypeInfo, pmethod->index); 06812 } 06813 06814 static VALUE 06815 ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) 06816 { 06817 TYPEATTR *pTypeAttr; 06818 HRESULT hr; 06819 WORD i; 06820 int flags; 06821 HREFTYPE href; 06822 ITypeInfo *pRefTypeInfo; 06823 FUNCDESC *pFuncDesc; 06824 BSTR bstr; 06825 VALUE name; 06826 VALUE event = Qfalse; 06827 06828 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 06829 if (FAILED(hr)) 06830 return event; 06831 if(pTypeAttr->typekind != TKIND_COCLASS) { 06832 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); 06833 return event; 06834 } 06835 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 06836 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 06837 if (FAILED(hr)) 06838 continue; 06839 06840 if (flags & IMPLTYPEFLAG_FSOURCE) { 06841 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 06842 i, &href); 06843 if (FAILED(hr)) 06844 continue; 06845 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 06846 href, &pRefTypeInfo); 06847 if (FAILED(hr)) 06848 continue; 06849 hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index, 06850 &pFuncDesc); 06851 if (FAILED(hr)) { 06852 OLE_RELEASE(pRefTypeInfo); 06853 continue; 06854 } 06855 06856 hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo, 06857 pFuncDesc->memid, 06858 &bstr, NULL, NULL, NULL); 06859 if (FAILED(hr)) { 06860 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); 06861 OLE_RELEASE(pRefTypeInfo); 06862 continue; 06863 } 06864 06865 name = WC2VSTR(bstr); 06866 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); 06867 OLE_RELEASE(pRefTypeInfo); 06868 if (rb_str_cmp(method_name, name) == 0) { 06869 event = Qtrue; 06870 break; 06871 } 06872 } 06873 } 06874 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 06875 return event; 06876 } 06877 06878 /* 06879 * call-seq: 06880 * WIN32OLE_METHOD#event? 06881 * 06882 * Returns true if the method is event. 06883 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06884 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') 06885 * puts method.event? # => true 06886 * 06887 */ 06888 static VALUE 06889 folemethod_event(VALUE self) 06890 { 06891 struct olemethoddata *pmethod; 06892 Data_Get_Struct(self, struct olemethoddata, pmethod); 06893 if (!pmethod->pOwnerTypeInfo) 06894 return Qfalse; 06895 return ole_method_event(pmethod->pOwnerTypeInfo, 06896 pmethod->index, 06897 rb_ivar_get(self, rb_intern("name"))); 06898 } 06899 06900 /* 06901 * call-seq: 06902 * WIN32OLE_METHOD#event_interface 06903 * 06904 * Returns event interface name if the method is event. 06905 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06906 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') 06907 * puts method.event_interface # => WorkbookEvents 06908 */ 06909 static VALUE 06910 folemethod_event_interface(VALUE self) 06911 { 06912 BSTR name; 06913 struct olemethoddata *pmethod; 06914 HRESULT hr; 06915 Data_Get_Struct(self, struct olemethoddata, pmethod); 06916 if(folemethod_event(self) == Qtrue) { 06917 hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL); 06918 if(SUCCEEDED(hr)) 06919 return WC2VSTR(name); 06920 } 06921 return Qnil; 06922 } 06923 06924 static VALUE 06925 ole_method_docinfo_from_type( 06926 ITypeInfo *pTypeInfo, 06927 UINT method_index, 06928 BSTR *name, 06929 BSTR *helpstr, 06930 DWORD *helpcontext, 06931 BSTR *helpfile 06932 ) 06933 { 06934 FUNCDESC *pFuncDesc; 06935 HRESULT hr; 06936 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06937 if (FAILED(hr)) 06938 return hr; 06939 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 06940 name, helpstr, 06941 helpcontext, helpfile); 06942 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06943 return hr; 06944 } 06945 06946 static VALUE 06947 ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) 06948 { 06949 HRESULT hr; 06950 BSTR bhelpstring; 06951 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring, 06952 NULL, NULL); 06953 if (FAILED(hr)) 06954 return Qnil; 06955 return WC2VSTR(bhelpstring); 06956 } 06957 06958 /* 06959 * call-seq: 06960 * WIN32OLE_METHOD#helpstring 06961 * 06962 * Returns help string of OLE method. If the help string is not found, 06963 * then the method returns nil. 06964 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') 06965 * method = WIN32OLE_METHOD.new(tobj, 'Navigate') 06966 * puts method.helpstring # => Navigates to a URL or file. 06967 * 06968 */ 06969 static VALUE 06970 folemethod_helpstring(VALUE self) 06971 { 06972 struct olemethoddata *pmethod; 06973 Data_Get_Struct(self, struct olemethoddata, pmethod); 06974 return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index); 06975 } 06976 06977 static VALUE 06978 ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index) 06979 { 06980 HRESULT hr; 06981 BSTR bhelpfile; 06982 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, 06983 NULL, &bhelpfile); 06984 if (FAILED(hr)) 06985 return Qnil; 06986 return WC2VSTR(bhelpfile); 06987 } 06988 06989 /* 06990 * call-seq: 06991 * WIN32OLE_METHOD#helpfile 06992 * 06993 * Returns help file. If help file is not found, then 06994 * the method returns nil. 06995 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06996 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06997 * puts method.helpfile # => C:\...\VBAXL9.CHM 06998 */ 06999 static VALUE 07000 folemethod_helpfile(VALUE self) 07001 { 07002 struct olemethoddata *pmethod; 07003 Data_Get_Struct(self, struct olemethoddata, pmethod); 07004 07005 return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index); 07006 } 07007 07008 static VALUE 07009 ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) 07010 { 07011 HRESULT hr; 07012 DWORD helpcontext = 0; 07013 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, 07014 &helpcontext, NULL); 07015 if (FAILED(hr)) 07016 return Qnil; 07017 return INT2FIX(helpcontext); 07018 } 07019 07020 /* 07021 * call-seq: 07022 * WIN32OLE_METHOD#helpcontext 07023 * 07024 * Returns help context. 07025 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 07026 * method = WIN32OLE_METHOD.new(tobj, 'Add') 07027 * puts method.helpcontext # => 65717 07028 */ 07029 static VALUE 07030 folemethod_helpcontext(VALUE self) 07031 { 07032 struct olemethoddata *pmethod; 07033 Data_Get_Struct(self, struct olemethoddata, pmethod); 07034 return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index); 07035 } 07036 07037 static VALUE 07038 ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) 07039 { 07040 FUNCDESC *pFuncDesc; 07041 HRESULT hr; 07042 VALUE dispid = Qnil; 07043 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07044 if (FAILED(hr)) 07045 return dispid; 07046 dispid = INT2NUM(pFuncDesc->memid); 07047 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07048 return dispid; 07049 } 07050 07051 /* 07052 * call-seq: 07053 * WIN32OLE_METHOD#dispid 07054 * 07055 * Returns dispatch ID. 07056 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 07057 * method = WIN32OLE_METHOD.new(tobj, 'Add') 07058 * puts method.dispid # => 181 07059 */ 07060 static VALUE 07061 folemethod_dispid(VALUE self) 07062 { 07063 struct olemethoddata *pmethod; 07064 Data_Get_Struct(self, struct olemethoddata, pmethod); 07065 return ole_method_dispid(pmethod->pTypeInfo, pmethod->index); 07066 } 07067 07068 static VALUE 07069 ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) 07070 { 07071 FUNCDESC *pFuncDesc; 07072 HRESULT hr; 07073 VALUE offset_vtbl = Qnil; 07074 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07075 if (FAILED(hr)) 07076 return offset_vtbl; 07077 offset_vtbl = INT2FIX(pFuncDesc->oVft); 07078 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07079 return offset_vtbl; 07080 } 07081 07082 /* 07083 * call-seq: 07084 * WIN32OLE_METHOD#offset_vtbl 07085 * 07086 * Returns the offset ov VTBL. 07087 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 07088 * method = WIN32OLE_METHOD.new(tobj, 'Add') 07089 * puts method.offset_vtbl # => 40 07090 */ 07091 static VALUE 07092 folemethod_offset_vtbl(VALUE self) 07093 { 07094 struct olemethoddata *pmethod; 07095 Data_Get_Struct(self, struct olemethoddata, pmethod); 07096 return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index); 07097 } 07098 07099 static VALUE 07100 ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) 07101 { 07102 FUNCDESC *pFuncDesc; 07103 HRESULT hr; 07104 VALUE size_params = Qnil; 07105 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07106 if (FAILED(hr)) 07107 return size_params; 07108 size_params = INT2FIX(pFuncDesc->cParams); 07109 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07110 return size_params; 07111 } 07112 07113 /* 07114 * call-seq: 07115 * WIN32OLE_METHOD#size_params 07116 * 07117 * Returns the size of arguments of the method. 07118 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07119 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07120 * puts method.size_params # => 11 07121 * 07122 */ 07123 static VALUE 07124 folemethod_size_params(VALUE self) 07125 { 07126 struct olemethoddata *pmethod; 07127 Data_Get_Struct(self, struct olemethoddata, pmethod); 07128 return ole_method_size_params(pmethod->pTypeInfo, pmethod->index); 07129 } 07130 07131 static VALUE 07132 ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) 07133 { 07134 FUNCDESC *pFuncDesc; 07135 HRESULT hr; 07136 VALUE size_opt_params = Qnil; 07137 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07138 if (FAILED(hr)) 07139 return size_opt_params; 07140 size_opt_params = INT2FIX(pFuncDesc->cParamsOpt); 07141 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07142 return size_opt_params; 07143 } 07144 07145 /* 07146 * call-seq: 07147 * WIN32OLE_METHOD#size_opt_params 07148 * 07149 * Returns the size of optional parameters. 07150 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07151 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07152 * puts method.size_opt_params # => 4 07153 */ 07154 static VALUE 07155 folemethod_size_opt_params(VALUE self) 07156 { 07157 struct olemethoddata *pmethod; 07158 Data_Get_Struct(self, struct olemethoddata, pmethod); 07159 return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index); 07160 } 07161 07162 static VALUE 07163 ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) 07164 { 07165 FUNCDESC *pFuncDesc; 07166 HRESULT hr; 07167 BSTR *bstrs; 07168 UINT len, i; 07169 struct oleparamdata *pparam; 07170 VALUE param; 07171 VALUE params = rb_ary_new(); 07172 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07173 if (FAILED(hr)) 07174 return params; 07175 07176 len = 0; 07177 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); 07178 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, 07179 bstrs, pFuncDesc->cParams + 1, 07180 &len); 07181 if (FAILED(hr)) { 07182 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07183 return params; 07184 } 07185 SysFreeString(bstrs[0]); 07186 if (pFuncDesc->cParams > 0) { 07187 for(i = 1; i < len; i++) { 07188 param = Data_Make_Struct(cWIN32OLE_PARAM, struct oleparamdata, 0, 07189 oleparam_free, pparam); 07190 pparam->pTypeInfo = pTypeInfo; 07191 OLE_ADDREF(pTypeInfo); 07192 pparam->method_index = method_index; 07193 pparam->index = i - 1; 07194 rb_ivar_set(param, rb_intern("name"), WC2VSTR(bstrs[i])); 07195 rb_ary_push(params, param); 07196 } 07197 } 07198 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07199 return params; 07200 } 07201 07202 07203 /* 07204 * call-seq: 07205 * WIN32OLE_METHOD#params 07206 * 07207 * returns array of WIN32OLE_PARAM object corresponding with method parameters. 07208 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07209 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07210 * p method.params # => [Filename, FileFormat, Password, WriteResPassword, 07211 * ReadOnlyRecommended, CreateBackup, AccessMode, 07212 * ConflictResolution, AddToMru, TextCodepage, 07213 * TextVisualLayout] 07214 */ 07215 static VALUE 07216 folemethod_params(VALUE self) 07217 { 07218 struct olemethoddata *pmethod; 07219 Data_Get_Struct(self, struct olemethoddata, pmethod); 07220 return ole_method_params(pmethod->pTypeInfo, pmethod->index); 07221 } 07222 07223 /* 07224 * call-seq: 07225 * WIN32OLE_METHOD#inspect -> String 07226 * 07227 * Returns the method name with class name. 07228 * 07229 */ 07230 static VALUE 07231 folemethod_inspect(VALUE self) 07232 { 07233 return default_inspect(self, "WIN32OLE_METHOD"); 07234 } 07235 07236 /* 07237 * Document-class: WIN32OLE_PARAM 07238 * 07239 * <code>WIN32OLE_PARAM</code> objects represent param information of 07240 * the OLE method. 07241 */ 07242 static VALUE foleparam_s_allocate(VALUE klass) 07243 { 07244 struct oleparamdata *pparam; 07245 VALUE obj; 07246 obj = Data_Make_Struct(klass, 07247 struct oleparamdata, 07248 0, oleparam_free, pparam); 07249 pparam->pTypeInfo = NULL; 07250 pparam->method_index = 0; 07251 pparam->index = 0; 07252 return obj; 07253 } 07254 07255 static VALUE 07256 oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index) 07257 { 07258 FUNCDESC *pFuncDesc; 07259 HRESULT hr; 07260 BSTR *bstrs; 07261 UINT len; 07262 struct oleparamdata *pparam; 07263 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07264 if (FAILED(hr)) 07265 ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc"); 07266 07267 len = 0; 07268 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); 07269 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, 07270 bstrs, pFuncDesc->cParams + 1, 07271 &len); 07272 if (FAILED(hr)) { 07273 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07274 ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames"); 07275 } 07276 SysFreeString(bstrs[0]); 07277 if (param_index < 1 || len <= (UINT)param_index) 07278 { 07279 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07280 rb_raise(rb_eIndexError, "index of param must be in 1..%d", len); 07281 } 07282 07283 Data_Get_Struct(self, struct oleparamdata, pparam); 07284 pparam->pTypeInfo = pTypeInfo; 07285 OLE_ADDREF(pTypeInfo); 07286 pparam->method_index = method_index; 07287 pparam->index = param_index - 1; 07288 rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index])); 07289 07290 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07291 return self; 07292 } 07293 07294 static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n) 07295 { 07296 struct olemethoddata *pmethod; 07297 Data_Get_Struct(olemethod, struct olemethoddata, pmethod); 07298 return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n); 07299 } 07300 07301 static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n) 07302 { 07303 int idx; 07304 if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) { 07305 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object"); 07306 } 07307 idx = FIX2INT(n); 07308 return oleparam_ole_param(self, olemethod, idx); 07309 } 07310 07311 /* 07312 * call-seq: 07313 * WIN32OLE_PARAM#name 07314 * 07315 * Returns name. 07316 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07317 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07318 * param1 = method.params[0] 07319 * puts param1.name # => Filename 07320 */ 07321 static VALUE 07322 foleparam_name(VALUE self) 07323 { 07324 return rb_ivar_get(self, rb_intern("name")); 07325 } 07326 07327 static VALUE 07328 ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 07329 { 07330 FUNCDESC *pFuncDesc; 07331 HRESULT hr; 07332 VALUE type = rb_str_new2("unknown type"); 07333 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07334 if (FAILED(hr)) 07335 return type; 07336 type = ole_typedesc2val(pTypeInfo, 07337 &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil); 07338 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07339 return type; 07340 } 07341 07342 /* 07343 * call-seq: 07344 * WIN32OLE_PARAM#ole_type 07345 * 07346 * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method). 07347 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07348 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07349 * param1 = method.params[0] 07350 * puts param1.ole_type # => VARIANT 07351 */ 07352 static VALUE 07353 foleparam_ole_type(VALUE self) 07354 { 07355 struct oleparamdata *pparam; 07356 Data_Get_Struct(self, struct oleparamdata, pparam); 07357 return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index, 07358 pparam->index); 07359 } 07360 07361 static VALUE 07362 ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 07363 { 07364 FUNCDESC *pFuncDesc; 07365 HRESULT hr; 07366 VALUE typedetail = rb_ary_new(); 07367 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07368 if (FAILED(hr)) 07369 return typedetail; 07370 ole_typedesc2val(pTypeInfo, 07371 &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail); 07372 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07373 return typedetail; 07374 } 07375 07376 /* 07377 * call-seq: 07378 * WIN32OLE_PARAM#ole_type_detail 07379 * 07380 * Returns detail information of type of argument. 07381 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction') 07382 * method = WIN32OLE_METHOD.new(tobj, 'SumIf') 07383 * param1 = method.params[0] 07384 * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"] 07385 */ 07386 static VALUE 07387 foleparam_ole_type_detail(VALUE self) 07388 { 07389 struct oleparamdata *pparam; 07390 Data_Get_Struct(self, struct oleparamdata, pparam); 07391 return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index, 07392 pparam->index); 07393 } 07394 07395 static VALUE 07396 ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask) 07397 { 07398 FUNCDESC *pFuncDesc; 07399 HRESULT hr; 07400 VALUE ret = Qfalse; 07401 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07402 if(FAILED(hr)) 07403 return ret; 07404 if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask) 07405 ret = Qtrue; 07406 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07407 return ret; 07408 } 07409 07410 /* 07411 * call-seq: 07412 * WIN32OLE_PARAM#input? 07413 * 07414 * Returns true if the parameter is input. 07415 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07416 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07417 * param1 = method.params[0] 07418 * puts param1.input? # => true 07419 */ 07420 static VALUE foleparam_input(VALUE self) 07421 { 07422 struct oleparamdata *pparam; 07423 Data_Get_Struct(self, struct oleparamdata, pparam); 07424 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07425 pparam->index, PARAMFLAG_FIN); 07426 } 07427 07428 /* 07429 * call-seq: 07430 * WIN32OLE#output? 07431 * 07432 * Returns true if argument is output. 07433 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents') 07434 * method = WIN32OLE_METHOD.new(tobj, 'NewWindow') 07435 * method.params.each do |param| 07436 * puts "#{param.name} #{param.output?}" 07437 * end 07438 * 07439 * The result of above script is following: 07440 * URL false 07441 * Flags false 07442 * TargetFrameName false 07443 * PostData false 07444 * Headers false 07445 * Processed true 07446 */ 07447 static VALUE foleparam_output(VALUE self) 07448 { 07449 struct oleparamdata *pparam; 07450 Data_Get_Struct(self, struct oleparamdata, pparam); 07451 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07452 pparam->index, PARAMFLAG_FOUT); 07453 } 07454 07455 /* 07456 * call-seq: 07457 * WIN32OLE_PARAM#optional? 07458 * 07459 * Returns true if argument is optional. 07460 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07461 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07462 * param1 = method.params[0] 07463 * puts "#{param1.name} #{param1.optional?}" # => Filename true 07464 */ 07465 static VALUE foleparam_optional(VALUE self) 07466 { 07467 struct oleparamdata *pparam; 07468 Data_Get_Struct(self, struct oleparamdata, pparam); 07469 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07470 pparam->index, PARAMFLAG_FOPT); 07471 } 07472 07473 /* 07474 * call-seq: 07475 * WIN32OLE_PARAM#retval? 07476 * 07477 * Returns true if argument is return value. 07478 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 07479 * 'DirectPlayLobbyConnection') 07480 * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName') 07481 * param = method.params[0] 07482 * puts "#{param.name} #{param.retval?}" # => name true 07483 */ 07484 static VALUE foleparam_retval(VALUE self) 07485 { 07486 struct oleparamdata *pparam; 07487 Data_Get_Struct(self, struct oleparamdata, pparam); 07488 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07489 pparam->index, PARAMFLAG_FRETVAL); 07490 } 07491 07492 static VALUE 07493 ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 07494 { 07495 FUNCDESC *pFuncDesc; 07496 ELEMDESC *pElemDesc; 07497 PARAMDESCEX * pParamDescEx; 07498 HRESULT hr; 07499 USHORT wParamFlags; 07500 USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT; 07501 VALUE defval = Qnil; 07502 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07503 if (FAILED(hr)) 07504 return defval; 07505 pElemDesc = &pFuncDesc->lprgelemdescParam[index]; 07506 wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags; 07507 if ((wParamFlags & mask) == mask) { 07508 pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex; 07509 defval = ole_variant2val(&pParamDescEx->varDefaultValue); 07510 } 07511 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07512 return defval; 07513 } 07514 07515 /* 07516 * call-seq: 07517 * WIN32OLE_PARAM#default 07518 * 07519 * Returns default value. If the default value does not exist, 07520 * this method returns nil. 07521 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07522 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07523 * method.params.each do |param| 07524 * if param.default 07525 * puts "#{param.name} (= #{param.default})" 07526 * else 07527 * puts "#{param}" 07528 * end 07529 * end 07530 * 07531 * The above script result is following: 07532 * Filename 07533 * FileFormat 07534 * Password 07535 * WriteResPassword 07536 * ReadOnlyRecommended 07537 * CreateBackup 07538 * AccessMode (= 1) 07539 * ConflictResolution 07540 * AddToMru 07541 * TextCodepage 07542 * TextVisualLayout 07543 */ 07544 static VALUE foleparam_default(VALUE self) 07545 { 07546 struct oleparamdata *pparam; 07547 Data_Get_Struct(self, struct oleparamdata, pparam); 07548 return ole_param_default(pparam->pTypeInfo, pparam->method_index, 07549 pparam->index); 07550 } 07551 07552 /* 07553 * call-seq: 07554 * WIN32OLE_PARAM#inspect -> String 07555 * 07556 * Returns the parameter name with class name. If the parameter has default value, 07557 * then returns name=value string with class name. 07558 * 07559 */ 07560 static VALUE 07561 foleparam_inspect(VALUE self) 07562 { 07563 VALUE detail = foleparam_name(self); 07564 VALUE defval = foleparam_default(self); 07565 if (defval != Qnil) { 07566 rb_str_cat2(detail, "="); 07567 rb_str_concat(detail, rb_funcall(defval, rb_intern("inspect"), 0)); 07568 } 07569 return make_inspect("WIN32OLE_PARAM", detail); 07570 } 07571 07572 /* 07573 * Document-class: WIN32OLE_EVENT 07574 * 07575 * <code>WIN32OLE_EVENT</code> objects controls OLE event. 07576 */ 07577 07578 static IEventSinkVtbl vtEventSink; 07579 static BOOL g_IsEventSinkVtblInitialized = FALSE; 07580 07581 void EVENTSINK_Destructor(PIEVENTSINKOBJ); 07582 07583 STDMETHODIMP 07584 EVENTSINK_QueryInterface( 07585 PEVENTSINK pEV, 07586 REFIID iid, 07587 LPVOID* ppv 07588 ) { 07589 if (IsEqualIID(iid, &IID_IUnknown) || 07590 IsEqualIID(iid, &IID_IDispatch) || 07591 IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) { 07592 *ppv = pEV; 07593 } 07594 else { 07595 *ppv = NULL; 07596 return E_NOINTERFACE; 07597 } 07598 ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv); 07599 return NOERROR; 07600 } 07601 07602 STDMETHODIMP_(ULONG) 07603 EVENTSINK_AddRef( 07604 PEVENTSINK pEV 07605 ){ 07606 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; 07607 return ++pEVObj->m_cRef; 07608 } 07609 07610 STDMETHODIMP_(ULONG) EVENTSINK_Release( 07611 PEVENTSINK pEV 07612 ) { 07613 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; 07614 --pEVObj->m_cRef; 07615 if(pEVObj->m_cRef != 0) 07616 return pEVObj->m_cRef; 07617 EVENTSINK_Destructor(pEVObj); 07618 return 0; 07619 } 07620 07621 STDMETHODIMP EVENTSINK_GetTypeInfoCount( 07622 PEVENTSINK pEV, 07623 UINT *pct 07624 ) { 07625 *pct = 0; 07626 return NOERROR; 07627 } 07628 07629 STDMETHODIMP EVENTSINK_GetTypeInfo( 07630 PEVENTSINK pEV, 07631 UINT info, 07632 LCID lcid, 07633 ITypeInfo **pInfo 07634 ) { 07635 *pInfo = NULL; 07636 return DISP_E_BADINDEX; 07637 } 07638 07639 STDMETHODIMP EVENTSINK_GetIDsOfNames( 07640 PEVENTSINK pEventSink, 07641 REFIID riid, 07642 OLECHAR **szNames, 07643 UINT cNames, 07644 LCID lcid, 07645 DISPID *pDispID 07646 ) { 07647 ITypeInfo *pTypeInfo; 07648 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; 07649 pTypeInfo = pEV->pTypeInfo; 07650 if (pTypeInfo) { 07651 return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID); 07652 } 07653 return DISP_E_UNKNOWNNAME; 07654 } 07655 07656 static long 07657 ole_search_event_at(VALUE ary, VALUE ev) 07658 { 07659 VALUE event; 07660 VALUE event_name; 07661 long i, len; 07662 long ret = -1; 07663 len = RARRAY_LEN(ary); 07664 for(i = 0; i < len; i++) { 07665 event = rb_ary_entry(ary, i); 07666 event_name = rb_ary_entry(event, 1); 07667 if(NIL_P(event_name) && NIL_P(ev)) { 07668 ret = i; 07669 break; 07670 } 07671 else if (TYPE(ev) == T_STRING && 07672 TYPE(event_name) == T_STRING && 07673 rb_str_cmp(ev, event_name) == 0) { 07674 ret = i; 07675 break; 07676 } 07677 } 07678 return ret; 07679 } 07680 07681 static VALUE 07682 ole_search_event(VALUE ary, VALUE ev, BOOL *is_default) 07683 { 07684 VALUE event; 07685 VALUE def_event; 07686 VALUE event_name; 07687 int i, len; 07688 *is_default = FALSE; 07689 def_event = Qnil; 07690 len = RARRAY_LEN(ary); 07691 for(i = 0; i < len; i++) { 07692 event = rb_ary_entry(ary, i); 07693 event_name = rb_ary_entry(event, 1); 07694 if(NIL_P(event_name)) { 07695 *is_default = TRUE; 07696 def_event = event; 07697 } 07698 else if (rb_str_cmp(ev, event_name) == 0) { 07699 *is_default = FALSE; 07700 return event; 07701 } 07702 } 07703 return def_event; 07704 } 07705 static VALUE 07706 ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler) 07707 { 07708 VALUE mid; 07709 07710 *is_default_handler = FALSE; 07711 mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev))); 07712 if (rb_respond_to(handler, mid)) { 07713 return mid; 07714 } 07715 mid = rb_intern("method_missing"); 07716 if (rb_respond_to(handler, mid)) { 07717 *is_default_handler = TRUE; 07718 return mid; 07719 } 07720 return Qnil; 07721 } 07722 07723 static void 07724 ole_delete_event(VALUE ary, VALUE ev) 07725 { 07726 long at = -1; 07727 at = ole_search_event_at(ary, ev); 07728 if (at >= 0) { 07729 rb_ary_delete_at(ary, at); 07730 } 07731 } 07732 07733 static void 07734 hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams) 07735 { 07736 BSTR *bstrs; 07737 HRESULT hr; 07738 UINT len, i; 07739 VARIANT *pvar; 07740 VALUE val; 07741 VALUE key; 07742 len = 0; 07743 bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1); 07744 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 07745 bstrs, pdispparams->cArgs + 1, 07746 &len); 07747 if (FAILED(hr)) 07748 return; 07749 07750 for (i = 0; i < len - 1; i++) { 07751 key = WC2VSTR(bstrs[i + 1]); 07752 val = rb_hash_aref(hash, INT2FIX(i)); 07753 if (val == Qnil) 07754 val = rb_hash_aref(hash, key); 07755 if (val == Qnil) 07756 val = rb_hash_aref(hash, rb_str_intern(key)); 07757 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 07758 ole_val2ptr_variant(val, pvar); 07759 } 07760 } 07761 07762 static VALUE 07763 hash2result(VALUE hash) 07764 { 07765 VALUE ret = Qnil; 07766 ret = rb_hash_aref(hash, rb_str_new2("return")); 07767 if (ret == Qnil) 07768 ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return"))); 07769 return ret; 07770 } 07771 07772 static void 07773 ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams) 07774 { 07775 int i; 07776 VALUE v; 07777 VARIANT *pvar; 07778 for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) { 07779 v = rb_ary_entry(ary, i); 07780 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 07781 ole_val2ptr_variant(v, pvar); 07782 } 07783 } 07784 07785 static VALUE 07786 exec_callback(VALUE arg) 07787 { 07788 VALUE *parg = (VALUE *)arg; 07789 VALUE handler = parg[0]; 07790 VALUE mid = parg[1]; 07791 VALUE args = parg[2]; 07792 return rb_apply(handler, mid, args); 07793 } 07794 07795 static VALUE 07796 rescue_callback(VALUE arg) 07797 { 07798 07799 VALUE error; 07800 VALUE e = rb_errinfo(); 07801 VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0); 07802 VALUE msg = rb_funcall(e, rb_intern("message"), 0); 07803 bt = rb_ary_entry(bt, 0); 07804 error = rb_sprintf("%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e)); 07805 rb_write_error(StringValuePtr(error)); 07806 rb_backtrace(); 07807 ruby_finalize(); 07808 exit(-1); 07809 07810 return Qnil; 07811 } 07812 07813 STDMETHODIMP EVENTSINK_Invoke( 07814 PEVENTSINK pEventSink, 07815 DISPID dispid, 07816 REFIID riid, 07817 LCID lcid, 07818 WORD wFlags, 07819 DISPPARAMS *pdispparams, 07820 VARIANT *pvarResult, 07821 EXCEPINFO *pexcepinfo, 07822 UINT *puArgErr 07823 ) { 07824 07825 HRESULT hr; 07826 BSTR bstr; 07827 unsigned int count; 07828 unsigned int i; 07829 ITypeInfo *pTypeInfo; 07830 VARIANT *pvar; 07831 VALUE ary, obj, event, args, outargv, ev, result; 07832 VALUE handler = Qnil; 07833 VALUE arg[3]; 07834 VALUE mid; 07835 VALUE is_outarg = Qfalse; 07836 BOOL is_default_handler = FALSE; 07837 int state; 07838 07839 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; 07840 pTypeInfo = pEV->pTypeInfo; 07841 obj = evs_entry(pEV->m_event_id); 07842 if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) { 07843 return NOERROR; 07844 } 07845 07846 ary = rb_ivar_get(obj, id_events); 07847 if (NIL_P(ary) || TYPE(ary) != T_ARRAY) { 07848 return NOERROR; 07849 } 07850 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 07851 &bstr, 1, &count); 07852 if (FAILED(hr)) { 07853 return NOERROR; 07854 } 07855 ev = WC2VSTR(bstr); 07856 event = ole_search_event(ary, ev, &is_default_handler); 07857 if (TYPE(event) == T_ARRAY) { 07858 handler = rb_ary_entry(event, 0); 07859 mid = rb_intern("call"); 07860 is_outarg = rb_ary_entry(event, 3); 07861 } else { 07862 handler = rb_ivar_get(obj, rb_intern("handler")); 07863 if (handler == Qnil) { 07864 return NOERROR; 07865 } 07866 mid = ole_search_handler_method(handler, ev, &is_default_handler); 07867 } 07868 if (handler == Qnil || mid == Qnil) { 07869 return NOERROR; 07870 } 07871 07872 args = rb_ary_new(); 07873 if (is_default_handler) { 07874 rb_ary_push(args, ev); 07875 } 07876 07877 /* make argument of event handler */ 07878 for (i = 0; i < pdispparams->cArgs; ++i) { 07879 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 07880 rb_ary_push(args, ole_variant2val(pvar)); 07881 } 07882 outargv = Qnil; 07883 if (is_outarg == Qtrue) { 07884 outargv = rb_ary_new(); 07885 rb_ary_push(args, outargv); 07886 } 07887 07888 /* 07889 * if exception raised in event callback, 07890 * then you receive cfp consistency error. 07891 * to avoid this error we use begin rescue end. 07892 * and the exception raised then error message print 07893 * and exit ruby process by Win32OLE itself. 07894 */ 07895 arg[0] = handler; 07896 arg[1] = mid; 07897 arg[2] = args; 07898 result = rb_protect(exec_callback, (VALUE)arg, &state); 07899 if (state != 0) { 07900 rescue_callback(Qnil); 07901 } 07902 if(TYPE(result) == T_HASH) { 07903 hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); 07904 result = hash2result(result); 07905 }else if (is_outarg == Qtrue && TYPE(outargv) == T_ARRAY) { 07906 ary2ptr_dispparams(outargv, pdispparams); 07907 } 07908 07909 if (pvarResult) { 07910 VariantInit(pvarResult); 07911 ole_val2variant(result, pvarResult); 07912 } 07913 07914 return NOERROR; 07915 } 07916 07917 PIEVENTSINKOBJ 07918 EVENTSINK_Constructor() { 07919 PIEVENTSINKOBJ pEv; 07920 if (!g_IsEventSinkVtblInitialized) { 07921 vtEventSink.QueryInterface=EVENTSINK_QueryInterface; 07922 vtEventSink.AddRef = EVENTSINK_AddRef; 07923 vtEventSink.Release = EVENTSINK_Release; 07924 vtEventSink.Invoke = EVENTSINK_Invoke; 07925 vtEventSink.GetIDsOfNames = EVENTSINK_GetIDsOfNames; 07926 vtEventSink.GetTypeInfoCount = EVENTSINK_GetTypeInfoCount; 07927 vtEventSink.GetTypeInfo = EVENTSINK_GetTypeInfo; 07928 07929 g_IsEventSinkVtblInitialized = TRUE; 07930 } 07931 pEv = ALLOC_N(IEVENTSINKOBJ, 1); 07932 if(pEv == NULL) return NULL; 07933 pEv->lpVtbl = &vtEventSink; 07934 pEv->m_cRef = 0; 07935 pEv->m_event_id = 0; 07936 pEv->pTypeInfo = NULL; 07937 return pEv; 07938 } 07939 07940 void EVENTSINK_Destructor( 07941 PIEVENTSINKOBJ pEVObj 07942 ) { 07943 if(pEVObj != NULL) { 07944 OLE_RELEASE(pEVObj->pTypeInfo); 07945 free(pEVObj); 07946 pEVObj = NULL; 07947 } 07948 } 07949 07950 static HRESULT 07951 find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) 07952 { 07953 HRESULT hr; 07954 IDispatch *pDispatch; 07955 ITypeInfo *pTypeInfo; 07956 ITypeLib *pTypeLib; 07957 TYPEATTR *pTypeAttr; 07958 HREFTYPE RefType; 07959 ITypeInfo *pImplTypeInfo; 07960 TYPEATTR *pImplTypeAttr; 07961 07962 struct oledata *pole; 07963 unsigned int index; 07964 unsigned int count; 07965 int type; 07966 BSTR bstr; 07967 char *pstr; 07968 07969 BOOL is_found = FALSE; 07970 LCID lcid = cWIN32OLE_lcid; 07971 07972 OLEData_Get_Struct(ole, pole); 07973 07974 pDispatch = pole->pDispatch; 07975 07976 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo); 07977 if (FAILED(hr)) 07978 return hr; 07979 07980 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, 07981 &pTypeLib, 07982 &index); 07983 OLE_RELEASE(pTypeInfo); 07984 if (FAILED(hr)) 07985 return hr; 07986 07987 if (!pitf) { 07988 hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, 07989 piid, 07990 ppTypeInfo); 07991 OLE_RELEASE(pTypeLib); 07992 return hr; 07993 } 07994 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 07995 for (index = 0; index < count; index++) { 07996 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, 07997 index, 07998 &pTypeInfo); 07999 if (FAILED(hr)) 08000 break; 08001 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 08002 08003 if(FAILED(hr)) { 08004 OLE_RELEASE(pTypeInfo); 08005 break; 08006 } 08007 if(pTypeAttr->typekind == TKIND_COCLASS) { 08008 for (type = 0; type < pTypeAttr->cImplTypes; type++) { 08009 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 08010 type, 08011 &RefType); 08012 if (FAILED(hr)) 08013 break; 08014 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 08015 RefType, 08016 &pImplTypeInfo); 08017 if (FAILED(hr)) 08018 break; 08019 08020 hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo, 08021 -1, 08022 &bstr, 08023 NULL, NULL, NULL); 08024 if (FAILED(hr)) { 08025 OLE_RELEASE(pImplTypeInfo); 08026 break; 08027 } 08028 pstr = ole_wc2mb(bstr); 08029 if (strcmp(pitf, pstr) == 0) { 08030 hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo, 08031 &pImplTypeAttr); 08032 if (SUCCEEDED(hr)) { 08033 is_found = TRUE; 08034 *piid = pImplTypeAttr->guid; 08035 if (ppTypeInfo) { 08036 *ppTypeInfo = pImplTypeInfo; 08037 (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo)); 08038 } 08039 pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo, 08040 pImplTypeAttr); 08041 } 08042 } 08043 free(pstr); 08044 OLE_RELEASE(pImplTypeInfo); 08045 if (is_found || FAILED(hr)) 08046 break; 08047 } 08048 } 08049 08050 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 08051 OLE_RELEASE(pTypeInfo); 08052 if (is_found || FAILED(hr)) 08053 break; 08054 } 08055 OLE_RELEASE(pTypeLib); 08056 if(!is_found) 08057 return E_NOINTERFACE; 08058 return hr; 08059 } 08060 08061 static HRESULT 08062 find_coclass( 08063 ITypeInfo *pTypeInfo, 08064 TYPEATTR *pTypeAttr, 08065 ITypeInfo **pCOTypeInfo, 08066 TYPEATTR **pCOTypeAttr) 08067 { 08068 HRESULT hr = E_NOINTERFACE; 08069 ITypeLib *pTypeLib; 08070 int count; 08071 BOOL found = FALSE; 08072 ITypeInfo *pTypeInfo2; 08073 TYPEATTR *pTypeAttr2; 08074 int flags; 08075 int i,j; 08076 HREFTYPE href; 08077 ITypeInfo *pRefTypeInfo; 08078 TYPEATTR *pRefTypeAttr; 08079 08080 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); 08081 if (FAILED(hr)) { 08082 return hr; 08083 } 08084 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 08085 for (i = 0; i < count && !found; i++) { 08086 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2); 08087 if (FAILED(hr)) 08088 continue; 08089 hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2); 08090 if (FAILED(hr)) { 08091 OLE_RELEASE(pTypeInfo2); 08092 continue; 08093 } 08094 if (pTypeAttr2->typekind != TKIND_COCLASS) { 08095 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 08096 OLE_RELEASE(pTypeInfo2); 08097 continue; 08098 } 08099 for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) { 08100 hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags); 08101 if (FAILED(hr)) 08102 continue; 08103 if (!(flags & IMPLTYPEFLAG_FDEFAULT)) 08104 continue; 08105 hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href); 08106 if (FAILED(hr)) 08107 continue; 08108 hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo); 08109 if (FAILED(hr)) 08110 continue; 08111 hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr); 08112 if (FAILED(hr)) { 08113 OLE_RELEASE(pRefTypeInfo); 08114 continue; 08115 } 08116 if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) { 08117 found = TRUE; 08118 } 08119 } 08120 if (!found) { 08121 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 08122 OLE_RELEASE(pTypeInfo2); 08123 } 08124 } 08125 OLE_RELEASE(pTypeLib); 08126 if (found) { 08127 *pCOTypeInfo = pTypeInfo2; 08128 *pCOTypeAttr = pTypeAttr2; 08129 hr = S_OK; 08130 } else { 08131 hr = E_NOINTERFACE; 08132 } 08133 return hr; 08134 } 08135 08136 static HRESULT 08137 find_default_source_from_typeinfo( 08138 ITypeInfo *pTypeInfo, 08139 TYPEATTR *pTypeAttr, 08140 ITypeInfo **ppTypeInfo) 08141 { 08142 int i = 0; 08143 HRESULT hr = E_NOINTERFACE; 08144 int flags; 08145 HREFTYPE hRefType; 08146 /* Enumerate all implemented types of the COCLASS */ 08147 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 08148 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 08149 if (FAILED(hr)) 08150 continue; 08151 08152 /* 08153 looking for the [default] [source] 08154 we just hope that it is a dispinterface :-) 08155 */ 08156 if ((flags & IMPLTYPEFLAG_FDEFAULT) && 08157 (flags & IMPLTYPEFLAG_FSOURCE)) { 08158 08159 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 08160 i, &hRefType); 08161 if (FAILED(hr)) 08162 continue; 08163 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 08164 hRefType, ppTypeInfo); 08165 if (SUCCEEDED(hr)) 08166 break; 08167 } 08168 } 08169 return hr; 08170 } 08171 08172 static HRESULT 08173 find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) 08174 { 08175 HRESULT hr; 08176 IProvideClassInfo2 *pProvideClassInfo2; 08177 IProvideClassInfo *pProvideClassInfo; 08178 void *p; 08179 08180 IDispatch *pDispatch; 08181 ITypeInfo *pTypeInfo; 08182 ITypeInfo *pTypeInfo2 = NULL; 08183 TYPEATTR *pTypeAttr; 08184 TYPEATTR *pTypeAttr2 = NULL; 08185 08186 struct oledata *pole; 08187 08188 OLEData_Get_Struct(ole, pole); 08189 pDispatch = pole->pDispatch; 08190 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 08191 &IID_IProvideClassInfo2, 08192 &p); 08193 if (SUCCEEDED(hr)) { 08194 pProvideClassInfo2 = p; 08195 hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2, 08196 GUIDKIND_DEFAULT_SOURCE_DISP_IID, 08197 piid); 08198 OLE_RELEASE(pProvideClassInfo2); 08199 if (SUCCEEDED(hr)) { 08200 hr = find_iid(ole, NULL, piid, ppTypeInfo); 08201 } 08202 } 08203 if (SUCCEEDED(hr)) { 08204 return hr; 08205 } 08206 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 08207 &IID_IProvideClassInfo, 08208 &p); 08209 if (SUCCEEDED(hr)) { 08210 pProvideClassInfo = p; 08211 hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo, 08212 &pTypeInfo); 08213 OLE_RELEASE(pProvideClassInfo); 08214 } 08215 if (FAILED(hr)) { 08216 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo ); 08217 } 08218 if (FAILED(hr)) 08219 return hr; 08220 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 08221 if (FAILED(hr)) { 08222 OLE_RELEASE(pTypeInfo); 08223 return hr; 08224 } 08225 08226 *ppTypeInfo = 0; 08227 hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo); 08228 if (!*ppTypeInfo) { 08229 hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2); 08230 if (SUCCEEDED(hr)) { 08231 hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo); 08232 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 08233 OLE_RELEASE(pTypeInfo2); 08234 } 08235 } 08236 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 08237 OLE_RELEASE(pTypeInfo); 08238 /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */ 08239 if (!*ppTypeInfo) { 08240 if (SUCCEEDED(hr)) 08241 hr = E_UNEXPECTED; 08242 return hr; 08243 } 08244 08245 /* Determine IID of default source interface */ 08246 hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr); 08247 if (SUCCEEDED(hr)) { 08248 *piid = pTypeAttr->guid; 08249 (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr); 08250 } 08251 else 08252 OLE_RELEASE(*ppTypeInfo); 08253 08254 return hr; 08255 08256 } 08257 08258 static void 08259 ole_event_free(struct oleeventdata *poleev) 08260 { 08261 if (poleev->pConnectionPoint) { 08262 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); 08263 OLE_RELEASE(poleev->pConnectionPoint); 08264 poleev->pConnectionPoint = NULL; 08265 } 08266 free(poleev); 08267 } 08268 08269 static VALUE 08270 fev_s_allocate(VALUE klass) 08271 { 08272 VALUE obj; 08273 struct oleeventdata *poleev; 08274 obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev); 08275 poleev->dwCookie = 0; 08276 poleev->pConnectionPoint = NULL; 08277 poleev->event_id = 0; 08278 return obj; 08279 } 08280 08281 static VALUE 08282 ev_advise(int argc, VALUE *argv, VALUE self) 08283 { 08284 08285 VALUE ole, itf; 08286 struct oledata *pole; 08287 char *pitf; 08288 HRESULT hr; 08289 IID iid; 08290 ITypeInfo *pTypeInfo = 0; 08291 IDispatch *pDispatch; 08292 IConnectionPointContainer *pContainer; 08293 IConnectionPoint *pConnectionPoint; 08294 IEVENTSINKOBJ *pIEV; 08295 DWORD dwCookie; 08296 struct oleeventdata *poleev; 08297 void *p; 08298 08299 rb_secure(4); 08300 rb_scan_args(argc, argv, "11", &ole, &itf); 08301 08302 if (!rb_obj_is_kind_of(ole, cWIN32OLE)) { 08303 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object"); 08304 } 08305 08306 if(TYPE(itf) != T_NIL) { 08307 if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) { 08308 rb_raise(rb_eSecurityError, "Insecure Event Creation - %s", 08309 StringValuePtr(itf)); 08310 } 08311 SafeStringValue(itf); 08312 pitf = StringValuePtr(itf); 08313 hr = find_iid(ole, pitf, &iid, &pTypeInfo); 08314 } 08315 else { 08316 hr = find_default_source(ole, &iid, &pTypeInfo); 08317 } 08318 if (FAILED(hr)) { 08319 ole_raise(hr, rb_eRuntimeError, "interface not found"); 08320 } 08321 08322 OLEData_Get_Struct(ole, pole); 08323 pDispatch = pole->pDispatch; 08324 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 08325 &IID_IConnectionPointContainer, 08326 &p); 08327 if (FAILED(hr)) { 08328 OLE_RELEASE(pTypeInfo); 08329 ole_raise(hr, rb_eRuntimeError, 08330 "failed to query IConnectionPointContainer"); 08331 } 08332 pContainer = p; 08333 08334 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer, 08335 &iid, 08336 &pConnectionPoint); 08337 OLE_RELEASE(pContainer); 08338 if (FAILED(hr)) { 08339 OLE_RELEASE(pTypeInfo); 08340 ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint"); 08341 } 08342 pIEV = EVENTSINK_Constructor(); 08343 pIEV->m_iid = iid; 08344 hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint, 08345 (IUnknown*)pIEV, 08346 &dwCookie); 08347 if (FAILED(hr)) { 08348 ole_raise(hr, rb_eRuntimeError, "Advise Error"); 08349 } 08350 08351 Data_Get_Struct(self, struct oleeventdata, poleev); 08352 pIEV->m_event_id 08353 = NUM2INT(evs_length()); 08354 pIEV->pTypeInfo = pTypeInfo; 08355 poleev->dwCookie = dwCookie; 08356 poleev->pConnectionPoint = pConnectionPoint; 08357 poleev->event_id = pIEV->m_event_id; 08358 08359 return self; 08360 } 08361 08362 /* 08363 * call-seq: 08364 * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object. 08365 * 08366 * Returns OLE event object. 08367 * The first argument specifies WIN32OLE object. 08368 * The second argument specifies OLE event name. 08369 * ie = WIN32OLE.new('InternetExplorer.Application') 08370 * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') 08371 */ 08372 static VALUE 08373 fev_initialize(int argc, VALUE *argv, VALUE self) 08374 { 08375 ev_advise(argc, argv, self); 08376 evs_push(self); 08377 rb_ivar_set(self, id_events, rb_ary_new()); 08378 fev_set_handler(self, Qnil); 08379 return self; 08380 } 08381 08382 /* 08383 * call-seq: 08384 * WIN32OLE_EVENT.message_loop 08385 * 08386 * Translates and dispatches Windows message. 08387 */ 08388 static VALUE 08389 fev_s_msg_loop(VALUE klass) 08390 { 08391 ole_msg_loop(); 08392 return Qnil; 08393 } 08394 08395 08396 static void 08397 add_event_call_back(VALUE obj, VALUE event, VALUE data) 08398 { 08399 VALUE events = rb_ivar_get(obj, id_events); 08400 if (NIL_P(events) || TYPE(events) != T_ARRAY) { 08401 events = rb_ary_new(); 08402 rb_ivar_set(obj, id_events, events); 08403 } 08404 ole_delete_event(events, event); 08405 rb_ary_push(events, data); 08406 } 08407 08408 static VALUE 08409 ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) 08410 { 08411 struct oleeventdata *poleev; 08412 VALUE event, args, data; 08413 Data_Get_Struct(self, struct oleeventdata, poleev); 08414 if (poleev->pConnectionPoint == NULL) { 08415 rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first."); 08416 } 08417 rb_scan_args(argc, argv, "01*", &event, &args); 08418 if(!NIL_P(event)) { 08419 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) { 08420 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 08421 } 08422 if (TYPE(event) == T_SYMBOL) { 08423 event = rb_sym_to_s(event); 08424 } 08425 } 08426 data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg); 08427 add_event_call_back(self, event, data); 08428 return Qnil; 08429 } 08430 08431 /* 08432 * call-seq: 08433 * WIN32OLE_EVENT#on_event([event]){...} 08434 * 08435 * Defines the callback event. 08436 * If argument is omitted, this method defines the callback of all events. 08437 * If you want to modify reference argument in callback, return hash in 08438 * callback. If you want to return value to OLE server as result of callback 08439 * use `return' or :return. 08440 * 08441 * ie = WIN32OLE.new('InternetExplorer.Application') 08442 * ev = WIN32OLE_EVENT.new(ie) 08443 * ev.on_event("NavigateComplete") {|url| puts url} 08444 * ev.on_event() {|ev, *args| puts "#{ev} fired"} 08445 * 08446 * ev.on_event("BeforeNavigate2") {|*args| 08447 * ... 08448 * # set true to BeforeNavigate reference argument `Cancel'. 08449 * # Cancel is 7-th argument of BeforeNavigate, 08450 * # so you can use 6 as key of hash instead of 'Cancel'. 08451 * # The argument is counted from 0. 08452 * # The hash key of 0 means first argument.) 08453 * {:Cancel => true} # or {'Cancel' => true} or {6 => true} 08454 * } 08455 * 08456 * ev.on_event(...) {|*args| 08457 * {:return => 1, :xxx => yyy} 08458 * } 08459 */ 08460 static VALUE 08461 fev_on_event(int argc, VALUE *argv, VALUE self) 08462 { 08463 return ev_on_event(argc, argv, self, Qfalse); 08464 } 08465 08466 /* 08467 * call-seq: 08468 * WIN32OLE_EVENT#on_event_with_outargs([event]){...} 08469 * 08470 * Defines the callback of event. 08471 * If you want modify argument in callback, 08472 * you could use this method instead of WIN32OLE_EVENT#on_event. 08473 * 08474 * ie = WIN32OLE.new('InternetExplorer.Application') 08475 * ev = WIN32OLE_EVENT.new(ie) 08476 * ev.on_event_with_outargs('BeforeNavigate2') {|*args| 08477 * args.last[6] = true 08478 * } 08479 */ 08480 static VALUE 08481 fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self) 08482 { 08483 return ev_on_event(argc, argv, self, Qtrue); 08484 } 08485 08486 /* 08487 * call-seq: 08488 * WIN32OLE_EVENT#off_event([event]) 08489 * 08490 * removes the callback of event. 08491 * 08492 * ie = WIN32OLE.new('InternetExplorer.Application') 08493 * ev = WIN32OLE_EVENT.new(ie) 08494 * ev.on_event('BeforeNavigate2') {|*args| 08495 * args.last[6] = true 08496 * } 08497 * ... 08498 * ev.off_event('BeforeNavigate2') 08499 * ... 08500 */ 08501 static VALUE 08502 fev_off_event(int argc, VALUE *argv, VALUE self) 08503 { 08504 VALUE event = Qnil; 08505 VALUE events; 08506 08507 rb_secure(4); 08508 rb_scan_args(argc, argv, "01", &event); 08509 if(!NIL_P(event)) { 08510 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) { 08511 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 08512 } 08513 if (TYPE(event) == T_SYMBOL) { 08514 event = rb_sym_to_s(event); 08515 } 08516 } 08517 events = rb_ivar_get(self, id_events); 08518 if (NIL_P(events)) { 08519 return Qnil; 08520 } 08521 ole_delete_event(events, event); 08522 return Qnil; 08523 } 08524 08525 /* 08526 * call-seq: 08527 * WIN32OLE_EVENT#unadvise -> nil 08528 * 08529 * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object 08530 * does not receive the OLE server event any more. 08531 * This method is trial implementation. 08532 * 08533 * ie = WIN32OLE.new('InternetExplorer.Application') 08534 * ev = WIN32OLE_EVENT.new(ie) 08535 * ev.on_event() {...} 08536 * ... 08537 * ev.unadvise 08538 * 08539 */ 08540 static VALUE 08541 fev_unadvise(VALUE self) 08542 { 08543 struct oleeventdata *poleev; 08544 Data_Get_Struct(self, struct oleeventdata, poleev); 08545 if (poleev->pConnectionPoint) { 08546 ole_msg_loop(); 08547 evs_delete(poleev->event_id); 08548 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); 08549 OLE_RELEASE(poleev->pConnectionPoint); 08550 poleev->pConnectionPoint = NULL; 08551 } 08552 return Qnil; 08553 } 08554 08555 static VALUE 08556 evs_push(VALUE ev) 08557 { 08558 return rb_ary_push(ary_ole_event, ev); 08559 } 08560 08561 static VALUE 08562 evs_delete(long i) 08563 { 08564 rb_ary_store(ary_ole_event, i, Qnil); 08565 return Qnil; 08566 } 08567 08568 static VALUE 08569 evs_entry(long i) 08570 { 08571 return rb_ary_entry(ary_ole_event, i); 08572 } 08573 08574 static VALUE 08575 evs_length(void) 08576 { 08577 return rb_funcall(ary_ole_event, rb_intern("length"), 0); 08578 } 08579 08580 /* 08581 * call-seq: 08582 * WIN32OLE_EVENT#handler= 08583 * 08584 * sets event handler object. If handler object has onXXX 08585 * method according to XXX event, then onXXX method is called 08586 * when XXX event occurs. 08587 * 08588 * If handler object has method_missing and there is no 08589 * method according to the event, then method_missing 08590 * called and 1-st argument is event name. 08591 * 08592 * If handler object has onXXX method and there is block 08593 * defined by WIN32OLE_EVENT#on_event('XXX'){}, 08594 * then block is executed but handler object method is not called 08595 * when XXX event occurs. 08596 * 08597 * class Handler 08598 * def onStatusTextChange(text) 08599 * puts "StatusTextChanged" 08600 * end 08601 * def onPropertyChange(prop) 08602 * puts "PropertyChanged" 08603 * end 08604 * def method_missing(ev, *arg) 08605 * puts "other event #{ev}" 08606 * end 08607 * end 08608 * 08609 * handler = Handler.new 08610 * ie = WIN32OLE.new('InternetExplorer.Application') 08611 * ev = WIN32OLE_EVENT.new(ie) 08612 * ev.on_event("StatusTextChange") {|*args| 08613 * puts "this block executed." 08614 * puts "handler.onStatusTextChange method is not called." 08615 * } 08616 * ev.handler = handler 08617 * 08618 */ 08619 static VALUE 08620 fev_set_handler(VALUE self, VALUE val) 08621 { 08622 return rb_ivar_set(self, rb_intern("handler"), val); 08623 } 08624 08625 /* 08626 * call-seq: 08627 * WIN32OLE_EVENT#handler 08628 * 08629 * returns handler object. 08630 * 08631 */ 08632 static VALUE 08633 fev_get_handler(VALUE self) 08634 { 08635 return rb_ivar_get(self, rb_intern("handler")); 08636 } 08637 08638 static void 08639 olevariant_free(struct olevariantdata *pvar) 08640 { 08641 VariantClear(&(pvar->realvar)); 08642 VariantClear(&(pvar->var)); 08643 free(pvar); 08644 } 08645 08646 static VALUE 08647 folevariant_s_allocate(VALUE klass) 08648 { 08649 struct olevariantdata *pvar; 08650 VALUE obj; 08651 ole_initialize(); 08652 obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar); 08653 VariantInit(&(pvar->var)); 08654 VariantInit(&(pvar->realvar)); 08655 return obj; 08656 } 08657 08658 /* 08659 * call-seq: 08660 * WIN32OLE_VARIANT.array(ary, vt) 08661 * 08662 * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. 08663 * The first argument should be Array object which specifies dimensions 08664 * and each size of dimensions of OLE array. 08665 * The second argument specifies variant type of the element of OLE array. 08666 * 08667 * The following create 2 dimensions OLE array. The first dimensions size 08668 * is 3, and the second is 4. 08669 * 08670 * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4) 08671 * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 08672 * 08673 */ 08674 static VALUE 08675 folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt) 08676 { 08677 VALUE obj = Qnil; 08678 VARTYPE vt; 08679 struct olevariantdata *pvar; 08680 SAFEARRAYBOUND *psab = NULL; 08681 SAFEARRAY *psa = NULL; 08682 UINT dim = 0; 08683 UINT i = 0; 08684 08685 ole_initialize(); 08686 08687 vt = NUM2UINT(vvt); 08688 vt = (vt | VT_ARRAY); 08689 Check_Type(elems, T_ARRAY); 08690 obj = folevariant_s_allocate(klass); 08691 08692 Data_Get_Struct(obj, struct olevariantdata, pvar); 08693 dim = RARRAY_LEN(elems); 08694 08695 psab = ALLOC_N(SAFEARRAYBOUND, dim); 08696 08697 if(!psab) { 08698 rb_raise(rb_eRuntimeError, "memory allocation error"); 08699 } 08700 08701 for (i = 0; i < dim; i++) { 08702 psab[i].cElements = FIX2INT(rb_ary_entry(elems, i)); 08703 psab[i].lLbound = 0; 08704 } 08705 08706 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); 08707 if (psa == NULL) { 08708 if (psab) free(psab); 08709 rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)"); 08710 } 08711 08712 V_VT(&(pvar->var)) = vt; 08713 if (vt & VT_BYREF) { 08714 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); 08715 V_ARRAY(&(pvar->realvar)) = psa; 08716 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 08717 } else { 08718 V_ARRAY(&(pvar->var)) = psa; 08719 } 08720 if (psab) free(psab); 08721 return obj; 08722 } 08723 08724 /* 08725 * call-seq: 08726 * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object. 08727 * 08728 * Returns Ruby object wrapping OLE variant. 08729 * The first argument specifies Ruby object to convert OLE variant variable. 08730 * The second argument specifies VARIANT type. 08731 * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method 08732 * 08733 * shell = WIN32OLE.new("Shell.Application") 08734 * folder = shell.NameSpace("C:\\Windows") 08735 * item = folder.ParseName("tmp.txt") 08736 * # You can't use Ruby String object to call FolderItem.InvokeVerb. 08737 * # Instead, you have to use WIN32OLE_VARIANT object to call the method. 08738 * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)") 08739 * item.invokeVerb(shortcut) 08740 * 08741 */ 08742 static VALUE 08743 folevariant_initialize(VALUE self, VALUE args) 08744 { 08745 int len = 0; 08746 VARIANT var; 08747 VALUE val; 08748 VALUE vvt; 08749 VARTYPE vt; 08750 struct olevariantdata *pvar; 08751 08752 len = RARRAY_LEN(args); 08753 if (len < 1 || len > 3) { 08754 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); 08755 } 08756 VariantInit(&var); 08757 val = rb_ary_entry(args, 0); 08758 08759 if(!rb_obj_is_kind_of(val, cWIN32OLE) && 08760 !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) && 08761 !rb_obj_is_kind_of(val, rb_cTime)) { 08762 switch (TYPE(val)) { 08763 case T_ARRAY: 08764 case T_STRING: 08765 case T_FIXNUM: 08766 case T_BIGNUM: 08767 case T_FLOAT: 08768 case T_TRUE: 08769 case T_FALSE: 08770 case T_NIL: 08771 break; 08772 default: 08773 rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s", 08774 rb_obj_classname(val)); 08775 } 08776 } 08777 08778 Data_Get_Struct(self, struct olevariantdata, pvar); 08779 if (len == 1) { 08780 ole_val2variant(val, &(pvar->var)); 08781 } else { 08782 vvt = rb_ary_entry(args, 1); 08783 vt = NUM2INT(vvt); 08784 ole_val2olevariantdata(val, vt, pvar); 08785 } 08786 vt = V_VT(&pvar->var); 08787 return self; 08788 } 08789 08790 static SAFEARRAY * 08791 get_locked_safe_array(VALUE val) 08792 { 08793 struct olevariantdata *pvar; 08794 SAFEARRAY *psa = NULL; 08795 HRESULT hr; 08796 Data_Get_Struct(val, struct olevariantdata, pvar); 08797 if (!(V_VT(&(pvar->var)) & VT_ARRAY)) { 08798 rb_raise(rb_eTypeError, "variant type is not VT_ARRAY."); 08799 } 08800 psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var)); 08801 if (psa == NULL) { 08802 return psa; 08803 } 08804 hr = SafeArrayLock(psa); 08805 if (FAILED(hr)) { 08806 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock"); 08807 } 08808 return psa; 08809 } 08810 08811 static long * 08812 ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa) 08813 { 08814 long dim; 08815 long *pid; 08816 long i; 08817 dim = SafeArrayGetDim(psa); 08818 if (dim != ary_size) { 08819 rb_raise(rb_eArgError, "unmatch number of indices"); 08820 } 08821 pid = ALLOC_N(long, dim); 08822 if (pid == NULL) { 08823 rb_raise(rb_eRuntimeError, "failed to allocate memory for indices"); 08824 } 08825 for (i = 0; i < dim; i++) { 08826 pid[i] = NUM2INT(ary[i]); 08827 } 08828 return pid; 08829 } 08830 08831 static void 08832 unlock_safe_array(SAFEARRAY *psa) 08833 { 08834 HRESULT hr; 08835 hr = SafeArrayUnlock(psa); 08836 if (FAILED(hr)) { 08837 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock"); 08838 } 08839 } 08840 08841 /* 08842 * call-seq: 08843 * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array. 08844 * 08845 * Returns the element of WIN32OLE_VARIANT object(OLE array). 08846 * This method is available only when the variant type of 08847 * WIN32OLE_VARIANT object is VT_ARRAY. 08848 * 08849 * REMARK: 08850 * The all indicies should be 0 or natural number and 08851 * lower than or equal to max indicies. 08852 * (This point is different with Ruby Array indicies.) 08853 * 08854 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) 08855 * p obj[0,0] # => 1 08856 * p obj[1,0] # => 4 08857 * p obj[2,0] # => WIN32OLERuntimeError 08858 * p obj[0, -1] # => WIN32OLERuntimeError 08859 * 08860 */ 08861 static VALUE 08862 folevariant_ary_aref(int argc, VALUE *argv, VALUE self) 08863 { 08864 struct olevariantdata *pvar; 08865 SAFEARRAY *psa; 08866 VALUE val = Qnil; 08867 VARIANT variant; 08868 long *pid; 08869 HRESULT hr; 08870 08871 Data_Get_Struct(self, struct olevariantdata, pvar); 08872 if (!V_ISARRAY(&(pvar->var))) { 08873 rb_raise(eWIN32OLERuntimeError, 08874 "`[]' is not available for this variant type object"); 08875 } 08876 psa = get_locked_safe_array(self); 08877 if (psa == NULL) { 08878 return val; 08879 } 08880 08881 pid = ary2safe_array_index(argc, argv, psa); 08882 08883 VariantInit(&variant); 08884 V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF; 08885 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); 08886 if (FAILED(hr)) { 08887 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex"); 08888 } 08889 val = ole_variant2val(&variant); 08890 08891 unlock_safe_array(psa); 08892 if (pid) free(pid); 08893 return val; 08894 } 08895 08896 static VOID * 08897 val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt) 08898 { 08899 VOID *p = NULL; 08900 HRESULT hr = S_OK; 08901 ole_val2variant_ex(val, var, vt); 08902 if ((vt & ~VT_BYREF) == VT_VARIANT) { 08903 p = var; 08904 } else { 08905 if ( (vt & ~VT_BYREF) != V_VT(var)) { 08906 hr = VariantChangeTypeEx(var, var, 08907 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); 08908 if (FAILED(hr)) { 08909 ole_raise(hr, rb_eRuntimeError, "failed to change type"); 08910 } 08911 } 08912 p = get_ptr_of_variant(var); 08913 } 08914 if (p == NULL) { 08915 rb_raise(rb_eRuntimeError, "failed to get pointer of variant"); 08916 } 08917 return p; 08918 } 08919 08920 /* 08921 * call-seq: 08922 * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array 08923 * 08924 * Set the element of WIN32OLE_VARIANT object(OLE array) to val. 08925 * This method is available only when the variant type of 08926 * WIN32OLE_VARIANT object is VT_ARRAY. 08927 * 08928 * REMARK: 08929 * The all indicies should be 0 or natural number and 08930 * lower than or equal to max indicies. 08931 * (This point is different with Ruby Array indicies.) 08932 * 08933 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) 08934 * obj[0,0] = 7 08935 * obj[1,0] = 8 08936 * p obj.value # => [[7,2,3], [8,5,6]] 08937 * obj[2,0] = 9 # => WIN32OLERuntimeError 08938 * obj[0, -1] = 9 # => WIN32OLERuntimeError 08939 * 08940 */ 08941 static VALUE 08942 folevariant_ary_aset(int argc, VALUE *argv, VALUE self) 08943 { 08944 struct olevariantdata *pvar; 08945 SAFEARRAY *psa; 08946 VARIANT var; 08947 VARTYPE vt; 08948 long *pid; 08949 HRESULT hr; 08950 VOID *p = NULL; 08951 08952 Data_Get_Struct(self, struct olevariantdata, pvar); 08953 if (!V_ISARRAY(&(pvar->var))) { 08954 rb_raise(eWIN32OLERuntimeError, 08955 "`[]' is not available for this variant type object"); 08956 } 08957 psa = get_locked_safe_array(self); 08958 if (psa == NULL) { 08959 rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer"); 08960 } 08961 08962 pid = ary2safe_array_index(argc-1, argv, psa); 08963 08964 VariantInit(&var); 08965 vt = (V_VT(&(pvar->var)) & ~VT_ARRAY); 08966 p = val2variant_ptr(argv[argc-1], &var, vt); 08967 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || 08968 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { 08969 rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface"); 08970 } 08971 hr = SafeArrayPutElement(psa, pid, p); 08972 if (FAILED(hr)) { 08973 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement"); 08974 } 08975 08976 unlock_safe_array(psa); 08977 if (pid) free(pid); 08978 return argv[argc-1]; 08979 } 08980 08981 /* 08982 * call-seq: 08983 * WIN32OLE_VARIANT.value #=> Ruby object. 08984 * 08985 * Returns Ruby object value from OLE variant. 08986 * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) 08987 * obj.value # => "1" (not Fixnum object, but String object "1") 08988 * 08989 */ 08990 static VALUE 08991 folevariant_value(VALUE self) 08992 { 08993 struct olevariantdata *pvar; 08994 VALUE val = Qnil; 08995 VARTYPE vt; 08996 int dim; 08997 SAFEARRAY *psa; 08998 Data_Get_Struct(self, struct olevariantdata, pvar); 08999 09000 val = ole_variant2val(&(pvar->var)); 09001 vt = V_VT(&(pvar->var)); 09002 09003 if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) { 09004 if (vt & VT_BYREF) { 09005 psa = *V_ARRAYREF(&(pvar->var)); 09006 } else { 09007 psa = V_ARRAY(&(pvar->var)); 09008 } 09009 if (!psa) { 09010 return val; 09011 } 09012 dim = SafeArrayGetDim(psa); 09013 if (dim == 1) { 09014 val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*")); 09015 } 09016 } 09017 return val; 09018 } 09019 09020 /* 09021 * call-seq: 09022 * WIN32OLE_VARIANT.vartype #=> OLE variant type. 09023 * 09024 * Returns OLE variant type. 09025 * obj = WIN32OLE_VARIANT.new("string") 09026 * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR 09027 * 09028 */ 09029 static VALUE 09030 folevariant_vartype(VALUE self) 09031 { 09032 struct olevariantdata *pvar; 09033 Data_Get_Struct(self, struct olevariantdata, pvar); 09034 return INT2FIX(V_VT(&pvar->var)); 09035 } 09036 09037 /* 09038 * call-seq: 09039 * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val. 09040 * 09041 * Sets variant value to val. If the val type does not match variant value 09042 * type(vartype), then val is changed to match variant value type(vartype) 09043 * before setting val. 09044 * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY). 09045 * If the vartype is VT_UI1|VT_ARRAY, the val should be String object. 09046 * 09047 * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4 09048 * obj.value = 3.2 # 3.2 is changed to 3 when setting value. 09049 * p obj.value # => 3 09050 */ 09051 static VALUE 09052 folevariant_set_value(VALUE self, VALUE val) 09053 { 09054 struct olevariantdata *pvar; 09055 VARTYPE vt; 09056 Data_Get_Struct(self, struct olevariantdata, pvar); 09057 vt = V_VT(&(pvar->var)); 09058 if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) { 09059 rb_raise(eWIN32OLERuntimeError, 09060 "`value=' is not available for this variant type object"); 09061 } 09062 ole_val2olevariantdata(val, vt, pvar); 09063 return Qnil; 09064 } 09065 09066 static void 09067 init_enc2cp(void) 09068 { 09069 enc2cp_table = st_init_numtable(); 09070 } 09071 09072 static void 09073 free_enc2cp(void) 09074 { 09075 st_free_table(enc2cp_table); 09076 } 09077 09078 void 09079 Init_win32ole(void) 09080 { 09081 g_ole_initialized_init(); 09082 ary_ole_event = rb_ary_new(); 09083 rb_gc_register_mark_object(ary_ole_event); 09084 id_events = rb_intern("events"); 09085 09086 com_vtbl.QueryInterface = QueryInterface; 09087 com_vtbl.AddRef = AddRef; 09088 com_vtbl.Release = Release; 09089 com_vtbl.GetTypeInfoCount = GetTypeInfoCount; 09090 com_vtbl.GetTypeInfo = GetTypeInfo; 09091 com_vtbl.GetIDsOfNames = GetIDsOfNames; 09092 com_vtbl.Invoke = Invoke; 09093 09094 message_filter.QueryInterface = mf_QueryInterface; 09095 message_filter.AddRef = mf_AddRef; 09096 message_filter.Release = mf_Release; 09097 message_filter.HandleInComingCall = mf_HandleInComingCall; 09098 message_filter.RetryRejectedCall = mf_RetryRejectedCall; 09099 message_filter.MessagePending = mf_MessagePending; 09100 09101 com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); 09102 rb_gc_register_mark_object(com_hash); 09103 09104 cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); 09105 09106 rb_define_alloc_func(cWIN32OLE, fole_s_allocate); 09107 09108 rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1); 09109 09110 rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1); 09111 rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1); 09112 09113 rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1); 09114 rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1); 09115 rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1); 09116 rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0); 09117 rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1); 09118 rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0); 09119 rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1); 09120 rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0); 09121 rb_define_singleton_method(cWIN32OLE, "ole_initialize", fole_s_ole_initialize, 0); 09122 rb_define_singleton_method(cWIN32OLE, "ole_uninitialize", fole_s_ole_uninitialize, 0); 09123 09124 rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1); 09125 rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1); 09126 rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3); 09127 rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3); 09128 rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3); 09129 09130 /* support propput method that takes an argument */ 09131 rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1); 09132 09133 rb_define_method(cWIN32OLE, "ole_free", fole_free, 0); 09134 09135 rb_define_method(cWIN32OLE, "each", fole_each, 0); 09136 rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1); 09137 09138 /* support setproperty method much like Perl ;-) */ 09139 rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1); 09140 09141 rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0); 09142 rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0); 09143 rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0); 09144 rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0); 09145 09146 rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1); 09147 rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method"); 09148 rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0); 09149 rb_define_method(cWIN32OLE, "ole_type", fole_type, 0); 09150 rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type"); 09151 rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0); 09152 rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1); 09153 rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1); 09154 09155 rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION)); 09156 rb_define_const(cWIN32OLE, "ARGV", rb_ary_new()); 09157 09158 rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP)); 09159 rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP)); 09160 rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP)); 09161 rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP)); 09162 rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL)); 09163 rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7)); 09164 rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8)); 09165 09166 rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT)); 09167 rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT)); 09168 09169 mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT"); 09170 rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY)); 09171 rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL)); 09172 rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2)); 09173 rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4)); 09174 rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4)); 09175 rb_define_const(mWIN32OLE_VARIANT, "VT_R8", INT2FIX(VT_R8)); 09176 rb_define_const(mWIN32OLE_VARIANT, "VT_CY", INT2FIX(VT_CY)); 09177 rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", INT2FIX(VT_DATE)); 09178 rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", INT2FIX(VT_BSTR)); 09179 rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", INT2FIX(VT_USERDEFINED)); 09180 rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", INT2FIX(VT_PTR)); 09181 rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", INT2FIX(VT_DISPATCH)); 09182 rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", INT2FIX(VT_ERROR)); 09183 rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", INT2FIX(VT_BOOL)); 09184 rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", INT2FIX(VT_VARIANT)); 09185 rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", INT2FIX(VT_UNKNOWN)); 09186 rb_define_const(mWIN32OLE_VARIANT, "VT_I1", INT2FIX(VT_I1)); 09187 rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1)); 09188 rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2)); 09189 rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4)); 09190 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 09191 rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8)); 09192 rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8)); 09193 #endif 09194 rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT)); 09195 rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT)); 09196 rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY)); 09197 rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF)); 09198 09199 cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject); 09200 rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0); 09201 rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate); 09202 rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2); 09203 rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0); 09204 rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0); 09205 rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0); 09206 rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0); 09207 rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0); 09208 rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0); 09209 rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0); 09210 rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types"); 09211 rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0); 09212 rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0); 09213 rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name"); 09214 rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0); 09215 09216 cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject); 09217 rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1); 09218 rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0); 09219 rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0); 09220 rb_define_alloc_func(cWIN32OLE_TYPE, foletype_s_allocate); 09221 rb_define_method(cWIN32OLE_TYPE, "initialize", foletype_initialize, 2); 09222 rb_define_method(cWIN32OLE_TYPE, "name", foletype_name, 0); 09223 rb_define_method(cWIN32OLE_TYPE, "ole_type", foletype_ole_type, 0); 09224 rb_define_method(cWIN32OLE_TYPE, "guid", foletype_guid, 0); 09225 rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0); 09226 rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0); 09227 rb_define_alias(cWIN32OLE_TYPE, "to_s", "name"); 09228 rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0); 09229 rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0); 09230 rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0); 09231 rb_define_method(cWIN32OLE_TYPE, "helpstring", foletype_helpstring, 0); 09232 rb_define_method(cWIN32OLE_TYPE, "src_type", foletype_src_type, 0); 09233 rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0); 09234 rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0); 09235 rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0); 09236 rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0); 09237 rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0); 09238 rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0); 09239 rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0); 09240 rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0); 09241 rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0); 09242 rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0); 09243 09244 cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject); 09245 rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0); 09246 rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0); 09247 rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0); 09248 rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0); 09249 rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0); 09250 rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0); 09251 rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0); 09252 rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0); 09253 rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name"); 09254 09255 cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); 09256 rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); 09257 rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); 09258 rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0); 09259 rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0); 09260 rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0); 09261 rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0); 09262 rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0); 09263 rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0); 09264 rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0); 09265 rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0); 09266 rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0); 09267 rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0); 09268 rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0); 09269 rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0); 09270 rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0); 09271 rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0); 09272 rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0); 09273 rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0); 09274 rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0); 09275 rb_define_alias(cWIN32OLE_METHOD, "to_s", "name"); 09276 rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0); 09277 09278 cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject); 09279 rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate); 09280 rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2); 09281 rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0); 09282 rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0); 09283 rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0); 09284 rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0); 09285 rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0); 09286 rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0); 09287 rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0); 09288 rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0); 09289 rb_define_alias(cWIN32OLE_PARAM, "to_s", "name"); 09290 rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0); 09291 09292 cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject); 09293 rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0); 09294 rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate); 09295 rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1); 09296 rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1); 09297 rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1); 09298 rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1); 09299 rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0); 09300 rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1); 09301 rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0); 09302 09303 cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject); 09304 rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate); 09305 rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2); 09306 rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2); 09307 rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0); 09308 rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1); 09309 rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0); 09310 rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1); 09311 rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1); 09312 rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY))); 09313 rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL))); 09314 rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH))); 09315 09316 eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); 09317 09318 init_enc2cp(); 09319 atexit((void (*)(void))free_enc2cp); 09320 ole_init_cp(); 09321 } 09322
1.7.6.1