|
Ruby
2.0.0p594(2014-10-27revision48167)
|
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(VALUE self, VALUE ole, VALUE host, VALUE others); 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(VALUE self, VALUE ole, VALUE host, VALUE others) 02616 { 02617 HRESULT hr; 02618 CLSID clsid; 02619 OLECHAR *pbuf; 02620 02621 COSERVERINFO serverinfo; 02622 MULTI_QI multi_qi; 02623 DWORD clsctx = CLSCTX_REMOTE_SERVER; 02624 02625 if (!gole32) 02626 gole32 = LoadLibrary("OLE32"); 02627 if (!gole32) 02628 rb_raise(rb_eRuntimeError, "failed to load OLE32"); 02629 if (!gCoCreateInstanceEx) 02630 gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*) 02631 GetProcAddress(gole32, "CoCreateInstanceEx"); 02632 if (!gCoCreateInstanceEx) 02633 rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment"); 02634 02635 pbuf = ole_vstr2wc(ole); 02636 hr = CLSIDFromProgID(pbuf, &clsid); 02637 if (FAILED(hr)) 02638 hr = clsid_from_remote(host, ole, &clsid); 02639 if (FAILED(hr)) 02640 hr = CLSIDFromString(pbuf, &clsid); 02641 SysFreeString(pbuf); 02642 if (FAILED(hr)) 02643 ole_raise(hr, eWIN32OLERuntimeError, 02644 "unknown OLE server: `%s'", 02645 StringValuePtr(ole)); 02646 memset(&serverinfo, 0, sizeof(COSERVERINFO)); 02647 serverinfo.pwszName = ole_vstr2wc(host); 02648 memset(&multi_qi, 0, sizeof(MULTI_QI)); 02649 multi_qi.pIID = &IID_IDispatch; 02650 hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi); 02651 SysFreeString(serverinfo.pwszName); 02652 if (FAILED(hr)) 02653 ole_raise(hr, eWIN32OLERuntimeError, 02654 "failed to create DCOM server `%s' in `%s'", 02655 StringValuePtr(ole), 02656 StringValuePtr(host)); 02657 02658 ole_set_member(self, (IDispatch*)multi_qi.pItf); 02659 return self; 02660 } 02661 02662 static VALUE 02663 ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self) 02664 { 02665 IBindCtx *pBindCtx; 02666 IMoniker *pMoniker; 02667 IDispatch *pDispatch; 02668 void *p; 02669 HRESULT hr; 02670 OLECHAR *pbuf; 02671 ULONG eaten = 0; 02672 02673 ole_initialize(); 02674 02675 hr = CreateBindCtx(0, &pBindCtx); 02676 if(FAILED(hr)) { 02677 ole_raise(hr, eWIN32OLERuntimeError, 02678 "failed to create bind context"); 02679 } 02680 02681 pbuf = ole_vstr2wc(moniker); 02682 hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker); 02683 SysFreeString(pbuf); 02684 if(FAILED(hr)) { 02685 OLE_RELEASE(pBindCtx); 02686 ole_raise(hr, eWIN32OLERuntimeError, 02687 "failed to parse display name of moniker `%s'", 02688 StringValuePtr(moniker)); 02689 } 02690 hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, 02691 &IID_IDispatch, &p); 02692 pDispatch = p; 02693 OLE_RELEASE(pMoniker); 02694 OLE_RELEASE(pBindCtx); 02695 02696 if(FAILED(hr)) { 02697 ole_raise(hr, eWIN32OLERuntimeError, 02698 "failed to bind moniker `%s'", 02699 StringValuePtr(moniker)); 02700 } 02701 return create_win32ole_object(self, pDispatch, argc, argv); 02702 } 02703 02704 /* 02705 * call-seq: 02706 * WIN32OLE.connect( ole ) --> aWIN32OLE 02707 * 02708 * Returns running OLE Automation object or WIN32OLE object from moniker. 02709 * 1st argument should be OLE program id or class id or moniker. 02710 * 02711 * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel. 02712 */ 02713 static VALUE 02714 fole_s_connect(int argc, VALUE *argv, VALUE self) 02715 { 02716 VALUE svr_name; 02717 VALUE others; 02718 HRESULT hr; 02719 CLSID clsid; 02720 OLECHAR *pBuf; 02721 IDispatch *pDispatch; 02722 void *p; 02723 IUnknown *pUnknown; 02724 02725 rb_secure(4); 02726 /* initialize to use OLE */ 02727 ole_initialize(); 02728 02729 rb_scan_args(argc, argv, "1*", &svr_name, &others); 02730 SafeStringValue(svr_name); 02731 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { 02732 rb_raise(rb_eSecurityError, "Insecure Object Connection - %s", 02733 StringValuePtr(svr_name)); 02734 } 02735 02736 /* get CLSID from OLE server name */ 02737 pBuf = ole_vstr2wc(svr_name); 02738 hr = CLSIDFromProgID(pBuf, &clsid); 02739 if(FAILED(hr)) { 02740 hr = CLSIDFromString(pBuf, &clsid); 02741 } 02742 SysFreeString(pBuf); 02743 if(FAILED(hr)) { 02744 return ole_bind_obj(svr_name, argc, argv, self); 02745 } 02746 02747 hr = GetActiveObject(&clsid, 0, &pUnknown); 02748 if (FAILED(hr)) { 02749 ole_raise(hr, eWIN32OLERuntimeError, 02750 "OLE server `%s' not running", StringValuePtr(svr_name)); 02751 } 02752 hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p); 02753 pDispatch = p; 02754 if(FAILED(hr)) { 02755 OLE_RELEASE(pUnknown); 02756 ole_raise(hr, eWIN32OLERuntimeError, 02757 "failed to create WIN32OLE server `%s'", 02758 StringValuePtr(svr_name)); 02759 } 02760 02761 OLE_RELEASE(pUnknown); 02762 02763 return create_win32ole_object(self, pDispatch, argc, argv); 02764 } 02765 02766 /* 02767 * call-seq: 02768 * WIN32OLE.const_load( ole, mod = WIN32OLE) 02769 * 02770 * Defines the constants of OLE Automation server as mod's constants. 02771 * The first argument is WIN32OLE object or type library name. 02772 * If 2nd argument is omitted, the default is WIN32OLE. 02773 * The first letter of Ruby's constant variable name is upper case, 02774 * so constant variable name of WIN32OLE object is capitalized. 02775 * For example, the 'xlTop' constant of Excel is changed to 'XlTop' 02776 * in WIN32OLE. 02777 * If the first letter of constant variabl is not [A-Z], then 02778 * the constant is defined as CONSTANTS hash element. 02779 * 02780 * module EXCEL_CONST 02781 * end 02782 * excel = WIN32OLE.new('Excel.Application') 02783 * WIN32OLE.const_load(excel, EXCEL_CONST) 02784 * puts EXCEL_CONST::XlTop # => -4160 02785 * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541 02786 * 02787 * WIN32OLE.const_load(excel) 02788 * puts WIN32OLE::XlTop # => -4160 02789 * 02790 * module MSO 02791 * end 02792 * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO) 02793 * puts MSO::MsoLineSingle # => 1 02794 */ 02795 static VALUE 02796 fole_s_const_load(int argc, VALUE *argv, VALUE self) 02797 { 02798 VALUE ole; 02799 VALUE klass; 02800 struct oledata *pole; 02801 ITypeInfo *pTypeInfo; 02802 ITypeLib *pTypeLib; 02803 unsigned int index; 02804 HRESULT hr; 02805 OLECHAR *pBuf; 02806 VALUE file; 02807 LCID lcid = cWIN32OLE_lcid; 02808 02809 rb_secure(4); 02810 rb_scan_args(argc, argv, "11", &ole, &klass); 02811 if (TYPE(klass) != T_CLASS && 02812 TYPE(klass) != T_MODULE && 02813 TYPE(klass) != T_NIL) { 02814 rb_raise(rb_eTypeError, "2nd parameter must be Class or Module"); 02815 } 02816 if (rb_obj_is_kind_of(ole, cWIN32OLE)) { 02817 OLEData_Get_Struct(ole, pole); 02818 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 02819 0, lcid, &pTypeInfo); 02820 if(FAILED(hr)) { 02821 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 02822 } 02823 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); 02824 if(FAILED(hr)) { 02825 OLE_RELEASE(pTypeInfo); 02826 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); 02827 } 02828 OLE_RELEASE(pTypeInfo); 02829 if(TYPE(klass) != T_NIL) { 02830 ole_const_load(pTypeLib, klass, self); 02831 } 02832 else { 02833 ole_const_load(pTypeLib, cWIN32OLE, self); 02834 } 02835 OLE_RELEASE(pTypeLib); 02836 } 02837 else if(TYPE(ole) == T_STRING) { 02838 file = typelib_file(ole); 02839 if (file == Qnil) { 02840 file = ole; 02841 } 02842 pBuf = ole_vstr2wc(file); 02843 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib); 02844 SysFreeString(pBuf); 02845 if (FAILED(hr)) 02846 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); 02847 if(TYPE(klass) != T_NIL) { 02848 ole_const_load(pTypeLib, klass, self); 02849 } 02850 else { 02851 ole_const_load(pTypeLib, cWIN32OLE, self); 02852 } 02853 OLE_RELEASE(pTypeLib); 02854 } 02855 else { 02856 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance"); 02857 } 02858 return Qnil; 02859 } 02860 02861 static VALUE 02862 ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes) 02863 { 02864 02865 long count; 02866 int i; 02867 HRESULT hr; 02868 BSTR bstr; 02869 ITypeInfo *pTypeInfo; 02870 VALUE type; 02871 02872 rb_secure(4); 02873 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 02874 for (i = 0; i < count; i++) { 02875 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 02876 &bstr, NULL, NULL, NULL); 02877 if (FAILED(hr)) 02878 continue; 02879 02880 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 02881 if (FAILED(hr)) 02882 continue; 02883 02884 type = foletype_s_allocate(cWIN32OLE_TYPE); 02885 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr)); 02886 02887 rb_ary_push(classes, type); 02888 OLE_RELEASE(pTypeInfo); 02889 } 02890 return classes; 02891 } 02892 02893 static ULONG 02894 reference_count(struct oledata * pole) 02895 { 02896 ULONG n = 0; 02897 if(pole->pDispatch) { 02898 OLE_ADDREF(pole->pDispatch); 02899 n = OLE_RELEASE(pole->pDispatch); 02900 } 02901 return n; 02902 } 02903 02904 /* 02905 * call-seq: 02906 * WIN32OLE.ole_reference_count(aWIN32OLE) --> number 02907 * 02908 * Returns reference counter of Dispatch interface of WIN32OLE object. 02909 * You should not use this method because this method 02910 * exists only for debugging WIN32OLE. 02911 */ 02912 static VALUE 02913 fole_s_reference_count(VALUE self, VALUE obj) 02914 { 02915 struct oledata * pole; 02916 OLEData_Get_Struct(obj, pole); 02917 return INT2NUM(reference_count(pole)); 02918 } 02919 02920 /* 02921 * call-seq: 02922 * WIN32OLE.ole_free(aWIN32OLE) --> number 02923 * 02924 * Invokes Release method of Dispatch interface of WIN32OLE object. 02925 * You should not use this method because this method 02926 * exists only for debugging WIN32OLE. 02927 * The return value is reference counter of OLE object. 02928 */ 02929 static VALUE 02930 fole_s_free(VALUE self, VALUE obj) 02931 { 02932 ULONG n = 0; 02933 struct oledata * pole; 02934 OLEData_Get_Struct(obj, pole); 02935 if(pole->pDispatch) { 02936 if (reference_count(pole) > 0) { 02937 n = OLE_RELEASE(pole->pDispatch); 02938 } 02939 } 02940 return INT2NUM(n); 02941 } 02942 02943 static HWND 02944 ole_show_help(VALUE helpfile, VALUE helpcontext) 02945 { 02946 FNHTMLHELP *pfnHtmlHelp; 02947 HWND hwnd = 0; 02948 02949 if(!ghhctrl) 02950 ghhctrl = LoadLibrary("HHCTRL.OCX"); 02951 if (!ghhctrl) 02952 return hwnd; 02953 pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA"); 02954 if (!pfnHtmlHelp) 02955 return hwnd; 02956 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), 02957 0x0f, NUM2INT(helpcontext)); 02958 if (hwnd == 0) 02959 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), 02960 0, NUM2INT(helpcontext)); 02961 return hwnd; 02962 } 02963 02964 /* 02965 * call-seq: 02966 * WIN32OLE.ole_show_help(obj [,helpcontext]) 02967 * 02968 * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE 02969 * object or WIN32OLE_METHOD object or helpfile. 02970 * 02971 * excel = WIN32OLE.new('Excel.Application') 02972 * typeobj = excel.ole_type 02973 * WIN32OLE.ole_show_help(typeobj) 02974 */ 02975 static VALUE 02976 fole_s_show_help(int argc, VALUE *argv, VALUE self) 02977 { 02978 VALUE target; 02979 VALUE helpcontext; 02980 VALUE helpfile; 02981 VALUE name; 02982 HWND hwnd; 02983 rb_scan_args(argc, argv, "11", &target, &helpcontext); 02984 if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) || 02985 rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) { 02986 helpfile = rb_funcall(target, rb_intern("helpfile"), 0); 02987 if(strlen(StringValuePtr(helpfile)) == 0) { 02988 name = rb_ivar_get(target, rb_intern("name")); 02989 rb_raise(rb_eRuntimeError, "no helpfile of `%s'", 02990 StringValuePtr(name)); 02991 } 02992 helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0); 02993 } else { 02994 helpfile = target; 02995 } 02996 if (TYPE(helpfile) != T_STRING) { 02997 rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)"); 02998 } 02999 hwnd = ole_show_help(helpfile, helpcontext); 03000 if(hwnd == 0) { 03001 rb_raise(rb_eRuntimeError, "failed to open help file `%s'", 03002 StringValuePtr(helpfile)); 03003 } 03004 return Qnil; 03005 } 03006 03007 /* 03008 * call-seq: 03009 * WIN32OLE.codepage 03010 * 03011 * Returns current codepage. 03012 * WIN32OLE.codepage # => WIN32OLE::CP_ACP 03013 */ 03014 static VALUE 03015 fole_s_get_code_page(VALUE self) 03016 { 03017 return INT2FIX(cWIN32OLE_cp); 03018 } 03019 03020 static BOOL CALLBACK 03021 installed_code_page_proc(LPTSTR str) { 03022 if (strtoul(str, NULL, 10) == g_cp_to_check) { 03023 g_cp_installed = TRUE; 03024 return FALSE; 03025 } 03026 return TRUE; 03027 } 03028 03029 static BOOL 03030 code_page_installed(UINT cp) 03031 { 03032 g_cp_installed = FALSE; 03033 g_cp_to_check = cp; 03034 EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED); 03035 return g_cp_installed; 03036 } 03037 03038 /* 03039 * call-seq: 03040 * WIN32OLE.codepage = CP 03041 * 03042 * Sets current codepage. 03043 * The WIN32OLE.codepage is initialized according to 03044 * Encoding.default_internal. 03045 * If Encoding.default_internal is nil then WIN32OLE.codepage 03046 * is initialized according to Encoding.default_external. 03047 * 03048 * WIN32OLE.codepage = WIN32OLE::CP_UTF8 03049 * WIN32OLE.codepage = 65001 03050 */ 03051 static VALUE 03052 fole_s_set_code_page(VALUE self, VALUE vcp) 03053 { 03054 UINT cp = FIX2INT(vcp); 03055 set_ole_codepage(cp); 03056 /* 03057 * Should this method return old codepage? 03058 */ 03059 return Qnil; 03060 } 03061 03062 /* 03063 * call-seq: 03064 * WIN32OLE.locale -> locale id. 03065 * 03066 * Returns current locale id (lcid). The default locale is 03067 * LOCALE_SYSTEM_DEFAULT. 03068 * 03069 * lcid = WIN32OLE.locale 03070 */ 03071 static VALUE 03072 fole_s_get_locale(VALUE self) 03073 { 03074 return INT2FIX(cWIN32OLE_lcid); 03075 } 03076 03077 static BOOL 03078 CALLBACK installed_lcid_proc(LPTSTR str) 03079 { 03080 if (strcmp(str, g_lcid_to_check) == 0) { 03081 g_lcid_installed = TRUE; 03082 return FALSE; 03083 } 03084 return TRUE; 03085 } 03086 03087 static BOOL 03088 lcid_installed(LCID lcid) 03089 { 03090 g_lcid_installed = FALSE; 03091 snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", lcid); 03092 EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED); 03093 return g_lcid_installed; 03094 } 03095 03096 /* 03097 * call-seq: 03098 * WIN32OLE.locale = lcid 03099 * 03100 * Sets current locale id (lcid). 03101 * 03102 * WIN32OLE.locale = 1033 # set locale English(U.S) 03103 * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY) 03104 * 03105 */ 03106 static VALUE 03107 fole_s_set_locale(VALUE self, VALUE vlcid) 03108 { 03109 LCID lcid = FIX2INT(vlcid); 03110 if (lcid_installed(lcid)) { 03111 cWIN32OLE_lcid = lcid; 03112 } else { 03113 switch (lcid) { 03114 case LOCALE_SYSTEM_DEFAULT: 03115 case LOCALE_USER_DEFAULT: 03116 cWIN32OLE_lcid = lcid; 03117 break; 03118 default: 03119 rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid); 03120 } 03121 } 03122 return Qnil; 03123 } 03124 03125 /* 03126 * call-seq: 03127 * WIN32OLE.create_guid 03128 * 03129 * Creates GUID. 03130 * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8} 03131 */ 03132 static VALUE 03133 fole_s_create_guid(VALUE self) 03134 { 03135 GUID guid; 03136 HRESULT hr; 03137 OLECHAR bstr[80]; 03138 int len = 0; 03139 hr = CoCreateGuid(&guid); 03140 if (FAILED(hr)) { 03141 ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID"); 03142 } 03143 len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 03144 if (len == 0) { 03145 rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)"); 03146 } 03147 return ole_wc2vstr(bstr, FALSE); 03148 } 03149 03150 /* 03151 * WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize 03152 * are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634). 03153 * You must not use thease method. 03154 */ 03155 03156 /* :nodoc */ 03157 static VALUE 03158 fole_s_ole_initialize(VALUE self) 03159 { 03160 ole_initialize(); 03161 return Qnil; 03162 } 03163 03164 /* :nodoc */ 03165 static VALUE 03166 fole_s_ole_uninitialize(VALUE self) 03167 { 03168 ole_uninitialize(); 03169 return Qnil; 03170 } 03171 03172 /* 03173 * Document-class: WIN32OLE 03174 * 03175 * <code>WIN32OLE</code> objects represent OLE Automation object in Ruby. 03176 * 03177 * By using WIN32OLE, you can access OLE server like VBScript. 03178 * 03179 * Here is sample script. 03180 * 03181 * require 'win32ole' 03182 * 03183 * excel = WIN32OLE.new('Excel.Application') 03184 * excel.visible = true 03185 * workbook = excel.Workbooks.Add(); 03186 * worksheet = workbook.Worksheets(1); 03187 * worksheet.Range("A1:D1").value = ["North","South","East","West"]; 03188 * worksheet.Range("A2:B2").value = [5.2, 10]; 03189 * worksheet.Range("C2").value = 8; 03190 * worksheet.Range("D2").value = 20; 03191 * 03192 * range = worksheet.Range("A1:D2"); 03193 * range.select 03194 * chart = workbook.Charts.Add; 03195 * 03196 * workbook.saved = true; 03197 * 03198 * excel.ActiveWorkbook.Close(0); 03199 * excel.Quit(); 03200 * 03201 * Unfortunately, Win32OLE doesn't support the argument passed by 03202 * reference directly. 03203 * Instead, Win32OLE provides WIN32OLE::ARGV. 03204 * If you want to get the result value of argument passed by reference, 03205 * you can use WIN32OLE::ARGV. 03206 * 03207 * oleobj.method(arg1, arg2, refargv3) 03208 * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method 03209 * 03210 */ 03211 03212 /* 03213 * call-seq: 03214 * WIN32OLE.new(server, [host]) -> WIN32OLE object 03215 * 03216 * Returns a new WIN32OLE object(OLE Automation object). 03217 * The first argument server specifies OLE Automation server. 03218 * The first argument should be CLSID or PROGID. 03219 * If second argument host specified, then returns OLE Automation 03220 * object on host. 03221 * 03222 * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object. 03223 * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object. 03224 */ 03225 static VALUE 03226 fole_initialize(int argc, VALUE *argv, VALUE self) 03227 { 03228 VALUE svr_name; 03229 VALUE host; 03230 VALUE others; 03231 HRESULT hr; 03232 CLSID clsid; 03233 OLECHAR *pBuf; 03234 IDispatch *pDispatch; 03235 void *p; 03236 rb_secure(4); 03237 rb_call_super(0, 0); 03238 rb_scan_args(argc, argv, "11*", &svr_name, &host, &others); 03239 03240 SafeStringValue(svr_name); 03241 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { 03242 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s", 03243 StringValuePtr(svr_name)); 03244 } 03245 if (!NIL_P(host)) { 03246 SafeStringValue(host); 03247 if (rb_safe_level() > 0 && OBJ_TAINTED(host)) { 03248 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s", 03249 StringValuePtr(svr_name)); 03250 } 03251 return ole_create_dcom(self, svr_name, host, others); 03252 } 03253 03254 /* get CLSID from OLE server name */ 03255 pBuf = ole_vstr2wc(svr_name); 03256 hr = CLSIDFromProgID(pBuf, &clsid); 03257 if(FAILED(hr)) { 03258 hr = CLSIDFromString(pBuf, &clsid); 03259 } 03260 SysFreeString(pBuf); 03261 if(FAILED(hr)) { 03262 ole_raise(hr, eWIN32OLERuntimeError, 03263 "unknown OLE server: `%s'", 03264 StringValuePtr(svr_name)); 03265 } 03266 03267 /* get IDispatch interface */ 03268 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 03269 &IID_IDispatch, &p); 03270 pDispatch = p; 03271 if(FAILED(hr)) { 03272 ole_raise(hr, eWIN32OLERuntimeError, 03273 "failed to create WIN32OLE object from `%s'", 03274 StringValuePtr(svr_name)); 03275 } 03276 03277 ole_set_member(self, pDispatch); 03278 return self; 03279 } 03280 03281 static VALUE 03282 hash2named_arg(VALUE pair, struct oleparam* pOp) 03283 { 03284 unsigned int index, i; 03285 VALUE key, value; 03286 index = pOp->dp.cNamedArgs; 03287 03288 /*--------------------------------------------- 03289 the data-type of key must be String or Symbol 03290 -----------------------------------------------*/ 03291 key = rb_ary_entry(pair, 0); 03292 if(TYPE(key) != T_STRING && TYPE(key) != T_SYMBOL) { 03293 /* clear name of dispatch parameters */ 03294 for(i = 1; i < index + 1; i++) { 03295 SysFreeString(pOp->pNamedArgs[i]); 03296 } 03297 /* clear dispatch parameters */ 03298 for(i = 0; i < index; i++ ) { 03299 VariantClear(&(pOp->dp.rgvarg[i])); 03300 } 03301 /* raise an exception */ 03302 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 03303 } 03304 if (TYPE(key) == T_SYMBOL) { 03305 key = rb_sym_to_s(key); 03306 } 03307 03308 /* pNamedArgs[0] is <method name>, so "index + 1" */ 03309 pOp->pNamedArgs[index + 1] = ole_vstr2wc(key); 03310 03311 value = rb_ary_entry(pair, 1); 03312 VariantInit(&(pOp->dp.rgvarg[index])); 03313 ole_val2variant(value, &(pOp->dp.rgvarg[index])); 03314 03315 pOp->dp.cNamedArgs += 1; 03316 return Qnil; 03317 } 03318 03319 static VALUE 03320 set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end) 03321 { 03322 VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV")); 03323 03324 Check_Type(argv, T_ARRAY); 03325 rb_ary_clear(argv); 03326 while (end-- > beg) { 03327 rb_ary_push(argv, ole_variant2val(&realargs[end])); 03328 VariantClear(&realargs[end]); 03329 } 03330 return argv; 03331 } 03332 03333 static VALUE 03334 ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket) 03335 { 03336 LCID lcid = cWIN32OLE_lcid; 03337 struct oledata *pole; 03338 HRESULT hr; 03339 VALUE cmd; 03340 VALUE paramS; 03341 VALUE param; 03342 VALUE obj; 03343 VALUE v; 03344 03345 BSTR wcmdname; 03346 03347 DISPID DispID; 03348 DISPID* pDispID; 03349 EXCEPINFO excepinfo; 03350 VARIANT result; 03351 VARIANTARG* realargs = NULL; 03352 unsigned int argErr = 0; 03353 unsigned int i; 03354 unsigned int cNamedArgs; 03355 int n; 03356 struct oleparam op; 03357 struct olevariantdata *pvar; 03358 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03359 03360 VariantInit(&result); 03361 03362 op.dp.rgvarg = NULL; 03363 op.dp.rgdispidNamedArgs = NULL; 03364 op.dp.cNamedArgs = 0; 03365 op.dp.cArgs = 0; 03366 03367 rb_scan_args(argc, argv, "1*", &cmd, ¶mS); 03368 if(TYPE(cmd) != T_STRING && TYPE(cmd) != T_SYMBOL && !is_bracket) { 03369 rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)"); 03370 } 03371 if (TYPE(cmd) == T_SYMBOL) { 03372 cmd = rb_sym_to_s(cmd); 03373 } 03374 OLEData_Get_Struct(self, pole); 03375 if(!pole->pDispatch) { 03376 rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); 03377 } 03378 if (is_bracket) { 03379 DispID = DISPID_VALUE; 03380 argc += 1; 03381 rb_ary_unshift(paramS, cmd); 03382 } else { 03383 wcmdname = ole_vstr2wc(cmd); 03384 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, 03385 &wcmdname, 1, lcid, &DispID); 03386 SysFreeString(wcmdname); 03387 if(FAILED(hr)) { 03388 ole_raise(hr, rb_eNoMethodError, 03389 "unknown property or method: `%s'", 03390 StringValuePtr(cmd)); 03391 } 03392 } 03393 03394 /* pick up last argument of method */ 03395 param = rb_ary_entry(paramS, argc-2); 03396 03397 op.dp.cNamedArgs = 0; 03398 03399 /* if last arg is hash object */ 03400 if(TYPE(param) == T_HASH) { 03401 /*------------------------------------------ 03402 hash object ==> named dispatch parameters 03403 --------------------------------------------*/ 03404 cNamedArgs = NUM2INT(rb_funcall(param, rb_intern("length"), 0)); 03405 op.dp.cArgs = cNamedArgs + argc - 2; 03406 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); 03407 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); 03408 rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op); 03409 03410 pDispID = ALLOCA_N(DISPID, cNamedArgs + 1); 03411 op.pNamedArgs[0] = ole_vstr2wc(cmd); 03412 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, 03413 &IID_NULL, 03414 op.pNamedArgs, 03415 op.dp.cNamedArgs + 1, 03416 lcid, pDispID); 03417 for(i = 0; i < op.dp.cNamedArgs + 1; i++) { 03418 SysFreeString(op.pNamedArgs[i]); 03419 op.pNamedArgs[i] = NULL; 03420 } 03421 if(FAILED(hr)) { 03422 /* clear dispatch parameters */ 03423 for(i = 0; i < op.dp.cArgs; i++ ) { 03424 VariantClear(&op.dp.rgvarg[i]); 03425 } 03426 ole_raise(hr, eWIN32OLERuntimeError, 03427 "failed to get named argument info: `%s'", 03428 StringValuePtr(cmd)); 03429 } 03430 op.dp.rgdispidNamedArgs = &(pDispID[1]); 03431 } 03432 else { 03433 cNamedArgs = 0; 03434 op.dp.cArgs = argc - 1; 03435 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); 03436 if (op.dp.cArgs > 0) { 03437 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); 03438 } 03439 } 03440 /*-------------------------------------- 03441 non hash args ==> dispatch parameters 03442 ----------------------------------------*/ 03443 if(op.dp.cArgs > cNamedArgs) { 03444 realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1); 03445 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03446 n = op.dp.cArgs - i + cNamedArgs - 1; 03447 VariantInit(&realargs[n]); 03448 VariantInit(&op.dp.rgvarg[n]); 03449 param = rb_ary_entry(paramS, i-cNamedArgs); 03450 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { 03451 Data_Get_Struct(param, struct olevariantdata, pvar); 03452 VariantCopy(&op.dp.rgvarg[n], &(pvar->var)); 03453 } else { 03454 ole_val2variant(param, &realargs[n]); 03455 V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF; 03456 V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n]; 03457 } 03458 } 03459 } 03460 /* apparent you need to call propput, you need this */ 03461 if (wFlags & DISPATCH_PROPERTYPUT) { 03462 if (op.dp.cArgs == 0) 03463 ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error"); 03464 03465 op.dp.cNamedArgs = 1; 03466 op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); 03467 op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; 03468 } 03469 03470 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03471 &IID_NULL, lcid, wFlags, &op.dp, 03472 &result, &excepinfo, &argErr); 03473 03474 if (FAILED(hr)) { 03475 /* retry to call args by value */ 03476 if(op.dp.cArgs >= cNamedArgs) { 03477 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03478 n = op.dp.cArgs - i + cNamedArgs - 1; 03479 param = rb_ary_entry(paramS, i-cNamedArgs); 03480 ole_val2variant(param, &op.dp.rgvarg[n]); 03481 } 03482 if (hr == DISP_E_EXCEPTION) { 03483 ole_freeexceptinfo(&excepinfo); 03484 } 03485 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03486 VariantInit(&result); 03487 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03488 &IID_NULL, lcid, wFlags, 03489 &op.dp, &result, 03490 &excepinfo, &argErr); 03491 03492 /* mega kludge. if a method in WORD is called and we ask 03493 * for a result when one is not returned then 03494 * hResult == DISP_E_EXCEPTION. this only happens on 03495 * functions whose DISPID > 0x8000 */ 03496 if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) { 03497 if (hr == DISP_E_EXCEPTION) { 03498 ole_freeexceptinfo(&excepinfo); 03499 } 03500 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03501 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03502 &IID_NULL, lcid, wFlags, 03503 &op.dp, NULL, 03504 &excepinfo, &argErr); 03505 03506 } 03507 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03508 n = op.dp.cArgs - i + cNamedArgs - 1; 03509 VariantClear(&op.dp.rgvarg[n]); 03510 } 03511 } 03512 03513 if (FAILED(hr)) { 03514 /* retry after converting nil to VT_EMPTY */ 03515 if (op.dp.cArgs > cNamedArgs) { 03516 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03517 n = op.dp.cArgs - i + cNamedArgs - 1; 03518 param = rb_ary_entry(paramS, i-cNamedArgs); 03519 ole_val2variant2(param, &op.dp.rgvarg[n]); 03520 } 03521 if (hr == DISP_E_EXCEPTION) { 03522 ole_freeexceptinfo(&excepinfo); 03523 } 03524 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03525 VariantInit(&result); 03526 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, 03527 &IID_NULL, lcid, wFlags, 03528 &op.dp, &result, 03529 &excepinfo, &argErr); 03530 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03531 n = op.dp.cArgs - i + cNamedArgs - 1; 03532 VariantClear(&op.dp.rgvarg[n]); 03533 } 03534 } 03535 } 03536 03537 } 03538 /* clear dispatch parameter */ 03539 if(op.dp.cArgs > cNamedArgs) { 03540 for(i = cNamedArgs; i < op.dp.cArgs; i++) { 03541 n = op.dp.cArgs - i + cNamedArgs - 1; 03542 param = rb_ary_entry(paramS, i-cNamedArgs); 03543 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { 03544 ole_val2variant(param, &realargs[n]); 03545 } 03546 } 03547 set_argv(realargs, cNamedArgs, op.dp.cArgs); 03548 } 03549 else { 03550 for(i = 0; i < op.dp.cArgs; i++) { 03551 VariantClear(&op.dp.rgvarg[i]); 03552 } 03553 } 03554 03555 if (FAILED(hr)) { 03556 v = ole_excepinfo2msg(&excepinfo); 03557 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s", 03558 StringValuePtr(cmd), 03559 StringValuePtr(v)); 03560 } 03561 obj = ole_variant2val(&result); 03562 VariantClear(&result); 03563 return obj; 03564 } 03565 03566 /* 03567 * call-seq: 03568 * WIN32OLE#invoke(method, [arg1,...]) => return value of method. 03569 * 03570 * Runs OLE method. 03571 * The first argument specifies the method name of OLE Automation object. 03572 * The others specify argument of the <i>method</i>. 03573 * If you can not execute <i>method</i> directly, then use this method instead. 03574 * 03575 * excel = WIN32OLE.new('Excel.Application') 03576 * excel.invoke('Quit') # => same as excel.Quit 03577 * 03578 */ 03579 static VALUE 03580 fole_invoke(int argc, VALUE *argv, VALUE self) 03581 { 03582 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); 03583 } 03584 03585 static VALUE 03586 ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind) 03587 { 03588 HRESULT hr; 03589 struct oledata *pole; 03590 unsigned int argErr = 0; 03591 EXCEPINFO excepinfo; 03592 VARIANT result; 03593 DISPPARAMS dispParams; 03594 VARIANTARG* realargs = NULL; 03595 int i, j; 03596 VALUE obj = Qnil; 03597 VALUE tp, param; 03598 VALUE v; 03599 VARTYPE vt; 03600 03601 Check_Type(args, T_ARRAY); 03602 Check_Type(types, T_ARRAY); 03603 03604 memset(&excepinfo, 0, sizeof(EXCEPINFO)); 03605 memset(&dispParams, 0, sizeof(DISPPARAMS)); 03606 VariantInit(&result); 03607 OLEData_Get_Struct(self, pole); 03608 03609 dispParams.cArgs = RARRAY_LEN(args); 03610 dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs); 03611 realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs); 03612 for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--) 03613 { 03614 VariantInit(&realargs[i]); 03615 VariantInit(&dispParams.rgvarg[i]); 03616 tp = rb_ary_entry(types, j); 03617 vt = (VARTYPE)FIX2INT(tp); 03618 V_VT(&dispParams.rgvarg[i]) = vt; 03619 param = rb_ary_entry(args, j); 03620 if (param == Qnil) 03621 { 03622 03623 V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR; 03624 V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND; 03625 } 03626 else 03627 { 03628 if (vt & VT_ARRAY) 03629 { 03630 int ent; 03631 LPBYTE pb; 03632 short* ps; 03633 LPLONG pl; 03634 VARIANT* pv; 03635 CY *py; 03636 VARTYPE v; 03637 SAFEARRAYBOUND rgsabound[1]; 03638 Check_Type(param, T_ARRAY); 03639 rgsabound[0].lLbound = 0; 03640 rgsabound[0].cElements = RARRAY_LEN(param); 03641 v = vt & ~(VT_ARRAY | VT_BYREF); 03642 V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound); 03643 V_VT(&realargs[i]) = VT_ARRAY | v; 03644 SafeArrayLock(V_ARRAY(&realargs[i])); 03645 pb = V_ARRAY(&realargs[i])->pvData; 03646 ps = V_ARRAY(&realargs[i])->pvData; 03647 pl = V_ARRAY(&realargs[i])->pvData; 03648 py = V_ARRAY(&realargs[i])->pvData; 03649 pv = V_ARRAY(&realargs[i])->pvData; 03650 for (ent = 0; ent < (int)rgsabound[0].cElements; ent++) 03651 { 03652 VARIANT velem; 03653 VALUE elem = rb_ary_entry(param, ent); 03654 ole_val2variant(elem, &velem); 03655 if (v != VT_VARIANT) 03656 { 03657 VariantChangeTypeEx(&velem, &velem, 03658 cWIN32OLE_lcid, 0, v); 03659 } 03660 switch (v) 03661 { 03662 /* 128 bits */ 03663 case VT_VARIANT: 03664 *pv++ = velem; 03665 break; 03666 /* 64 bits */ 03667 case VT_R8: 03668 case VT_CY: 03669 case VT_DATE: 03670 *py++ = V_CY(&velem); 03671 break; 03672 /* 16 bits */ 03673 case VT_BOOL: 03674 case VT_I2: 03675 case VT_UI2: 03676 *ps++ = V_I2(&velem); 03677 break; 03678 /* 8 bites */ 03679 case VT_UI1: 03680 case VT_I1: 03681 *pb++ = V_UI1(&velem); 03682 break; 03683 /* 32 bits */ 03684 default: 03685 *pl++ = V_I4(&velem); 03686 break; 03687 } 03688 } 03689 SafeArrayUnlock(V_ARRAY(&realargs[i])); 03690 } 03691 else 03692 { 03693 ole_val2variant(param, &realargs[i]); 03694 if ((vt & (~VT_BYREF)) != VT_VARIANT) 03695 { 03696 hr = VariantChangeTypeEx(&realargs[i], &realargs[i], 03697 cWIN32OLE_lcid, 0, 03698 (VARTYPE)(vt & (~VT_BYREF))); 03699 if (hr != S_OK) 03700 { 03701 rb_raise(rb_eTypeError, "not valid value"); 03702 } 03703 } 03704 } 03705 if ((vt & VT_BYREF) || vt == VT_VARIANT) 03706 { 03707 if (vt == VT_VARIANT) 03708 V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF; 03709 switch (vt & (~VT_BYREF)) 03710 { 03711 /* 128 bits */ 03712 case VT_VARIANT: 03713 V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i]; 03714 break; 03715 /* 64 bits */ 03716 case VT_R8: 03717 case VT_CY: 03718 case VT_DATE: 03719 V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]); 03720 break; 03721 /* 16 bits */ 03722 case VT_BOOL: 03723 case VT_I2: 03724 case VT_UI2: 03725 V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]); 03726 break; 03727 /* 8 bites */ 03728 case VT_UI1: 03729 case VT_I1: 03730 V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]); 03731 break; 03732 /* 32 bits */ 03733 default: 03734 V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]); 03735 break; 03736 } 03737 } 03738 else 03739 { 03740 /* copy 64 bits of data */ 03741 V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]); 03742 } 03743 } 03744 } 03745 03746 if (dispkind & DISPATCH_PROPERTYPUT) { 03747 dispParams.cNamedArgs = 1; 03748 dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); 03749 dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; 03750 } 03751 03752 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid), 03753 &IID_NULL, cWIN32OLE_lcid, 03754 dispkind, 03755 &dispParams, &result, 03756 &excepinfo, &argErr); 03757 03758 if (FAILED(hr)) { 03759 v = ole_excepinfo2msg(&excepinfo); 03760 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s", 03761 NUM2INT(dispid), 03762 StringValuePtr(v)); 03763 } 03764 03765 /* clear dispatch parameter */ 03766 if(dispParams.cArgs > 0) { 03767 set_argv(realargs, 0, dispParams.cArgs); 03768 } 03769 03770 obj = ole_variant2val(&result); 03771 VariantClear(&result); 03772 return obj; 03773 } 03774 03775 /* 03776 * call-seq: 03777 * WIN32OLE#_invoke(dispid, args, types) 03778 * 03779 * Runs the early binding method. 03780 * The 1st argument specifies dispatch ID, 03781 * the 2nd argument specifies the array of arguments, 03782 * the 3rd argument specifies the array of the type of arguments. 03783 * 03784 * excel = WIN32OLE.new('Excel.Application') 03785 * excel._invoke(302, [], []) # same effect as excel.Quit 03786 */ 03787 static VALUE 03788 fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types) 03789 { 03790 return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD); 03791 } 03792 03793 /* 03794 * call-seq: 03795 * WIN32OLE#_getproperty(dispid, args, types) 03796 * 03797 * Runs the early binding method to get property. 03798 * The 1st argument specifies dispatch ID, 03799 * the 2nd argument specifies the array of arguments, 03800 * the 3rd argument specifies the array of the type of arguments. 03801 * 03802 * excel = WIN32OLE.new('Excel.Application') 03803 * puts excel._getproperty(558, [], []) # same effect as puts excel.visible 03804 */ 03805 static VALUE 03806 fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) 03807 { 03808 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET); 03809 } 03810 03811 /* 03812 * call-seq: 03813 * WIN32OLE#_setproperty(dispid, args, types) 03814 * 03815 * Runs the early binding method to set property. 03816 * The 1st argument specifies dispatch ID, 03817 * the 2nd argument specifies the array of arguments, 03818 * the 3rd argument specifies the array of the type of arguments. 03819 * 03820 * excel = WIN32OLE.new('Excel.Application') 03821 * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true 03822 */ 03823 static VALUE 03824 fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) 03825 { 03826 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT); 03827 } 03828 03829 /* 03830 * call-seq: 03831 * WIN32OLE[a1, a2, ...]=val 03832 * 03833 * Sets the value to WIN32OLE object specified by a1, a2, ... 03834 * 03835 * dict = WIN32OLE.new('Scripting.Dictionary') 03836 * dict.add('ruby', 'RUBY') 03837 * dict['ruby'] = 'Ruby' 03838 * puts dict['ruby'] # => 'Ruby' 03839 * 03840 * Remark: You can not use this method to set the property value. 03841 * 03842 * excel = WIN32OLE.new('Excel.Application') 03843 * # excel['Visible'] = true # This is error !!! 03844 * excel.Visible = true # You should to use this style to set the property. 03845 * 03846 */ 03847 static VALUE 03848 fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self) 03849 { 03850 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE); 03851 } 03852 03853 /* 03854 * call-seq: 03855 * WIN32OLE.setproperty('property', [arg1, arg2,...] val) 03856 * 03857 * Sets property of OLE object. 03858 * When you want to set property with argument, you can use this method. 03859 * 03860 * excel = WIN32OLE.new('Excel.Application') 03861 * excel.Visible = true 03862 * book = excel.workbooks.add 03863 * sheet = book.worksheets(1) 03864 * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10. 03865 */ 03866 static VALUE 03867 fole_setproperty(int argc, VALUE *argv, VALUE self) 03868 { 03869 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE); 03870 } 03871 03872 /* 03873 * call-seq: 03874 * WIN32OLE[a1,a2,...] 03875 * 03876 * Returns the value of Collection specified by a1, a2,.... 03877 * 03878 * dict = WIN32OLE.new('Scripting.Dictionary') 03879 * dict.add('ruby', 'Ruby') 03880 * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')') 03881 * 03882 * Remark: You can not use this method to get the property. 03883 * excel = WIN32OLE.new('Excel.Application') 03884 * # puts excel['Visible'] This is error !!! 03885 * puts excel.Visible # You should to use this style to get the property. 03886 * 03887 */ 03888 static VALUE 03889 fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self) 03890 { 03891 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE); 03892 } 03893 03894 static VALUE 03895 ole_propertyput(VALUE self, VALUE property, VALUE value) 03896 { 03897 struct oledata *pole; 03898 unsigned argErr; 03899 unsigned int index; 03900 HRESULT hr; 03901 EXCEPINFO excepinfo; 03902 DISPID dispID = DISPID_VALUE; 03903 DISPID dispIDParam = DISPID_PROPERTYPUT; 03904 USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF; 03905 DISPPARAMS dispParams; 03906 VARIANTARG propertyValue[2]; 03907 OLECHAR* pBuf[1]; 03908 VALUE v; 03909 LCID lcid = cWIN32OLE_lcid; 03910 dispParams.rgdispidNamedArgs = &dispIDParam; 03911 dispParams.rgvarg = propertyValue; 03912 dispParams.cNamedArgs = 1; 03913 dispParams.cArgs = 1; 03914 03915 VariantInit(&propertyValue[0]); 03916 VariantInit(&propertyValue[1]); 03917 memset(&excepinfo, 0, sizeof(excepinfo)); 03918 03919 OLEData_Get_Struct(self, pole); 03920 03921 /* get ID from property name */ 03922 pBuf[0] = ole_vstr2wc(property); 03923 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL, 03924 pBuf, 1, lcid, &dispID); 03925 SysFreeString(pBuf[0]); 03926 pBuf[0] = NULL; 03927 03928 if(FAILED(hr)) { 03929 ole_raise(hr, eWIN32OLERuntimeError, 03930 "unknown property or method: `%s'", 03931 StringValuePtr(property)); 03932 } 03933 /* set property value */ 03934 ole_val2variant(value, &propertyValue[0]); 03935 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL, 03936 lcid, wFlags, &dispParams, 03937 NULL, &excepinfo, &argErr); 03938 03939 for(index = 0; index < dispParams.cArgs; ++index) { 03940 VariantClear(&propertyValue[index]); 03941 } 03942 if (FAILED(hr)) { 03943 v = ole_excepinfo2msg(&excepinfo); 03944 ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s", 03945 StringValuePtr(property), 03946 StringValuePtr(v)); 03947 } 03948 return Qnil; 03949 } 03950 03951 /* 03952 * call-seq: 03953 * WIN32OLE#ole_free 03954 * 03955 * invokes Release method of Dispatch interface of WIN32OLE object. 03956 * Usually, you do not need to call this method because Release method 03957 * called automatically when WIN32OLE object garbaged. 03958 * 03959 */ 03960 static VALUE 03961 fole_free(VALUE self) 03962 { 03963 struct oledata *pole; 03964 rb_secure(4); 03965 OLEData_Get_Struct(self, pole); 03966 OLE_FREE(pole->pDispatch); 03967 pole->pDispatch = NULL; 03968 return Qnil; 03969 } 03970 03971 static VALUE 03972 ole_each_sub(VALUE pEnumV) 03973 { 03974 VARIANT variant; 03975 VALUE obj = Qnil; 03976 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; 03977 VariantInit(&variant); 03978 while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) { 03979 obj = ole_variant2val(&variant); 03980 VariantClear(&variant); 03981 VariantInit(&variant); 03982 rb_yield(obj); 03983 } 03984 return Qnil; 03985 } 03986 03987 static VALUE 03988 ole_ienum_free(VALUE pEnumV) 03989 { 03990 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; 03991 OLE_RELEASE(pEnum); 03992 return Qnil; 03993 } 03994 03995 /* 03996 * call-seq: 03997 * WIN32OLE#each {|i|...} 03998 * 03999 * Iterates over each item of OLE collection which has IEnumVARIANT interface. 04000 * 04001 * excel = WIN32OLE.new('Excel.Application') 04002 * book = excel.workbooks.add 04003 * sheets = book.worksheets(1) 04004 * cells = sheets.cells("A1:A5") 04005 * cells.each do |cell| 04006 * cell.value = 10 04007 * end 04008 */ 04009 static VALUE 04010 fole_each(VALUE self) 04011 { 04012 LCID lcid = cWIN32OLE_lcid; 04013 04014 struct oledata *pole; 04015 04016 unsigned int argErr; 04017 EXCEPINFO excepinfo; 04018 DISPPARAMS dispParams; 04019 VARIANT result; 04020 HRESULT hr; 04021 IEnumVARIANT *pEnum = NULL; 04022 void *p; 04023 04024 RETURN_ENUMERATOR(self, 0, 0); 04025 04026 VariantInit(&result); 04027 dispParams.rgvarg = NULL; 04028 dispParams.rgdispidNamedArgs = NULL; 04029 dispParams.cNamedArgs = 0; 04030 dispParams.cArgs = 0; 04031 memset(&excepinfo, 0, sizeof(excepinfo)); 04032 04033 OLEData_Get_Struct(self, pole); 04034 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM, 04035 &IID_NULL, lcid, 04036 DISPATCH_METHOD | DISPATCH_PROPERTYGET, 04037 &dispParams, &result, 04038 &excepinfo, &argErr); 04039 04040 if (FAILED(hr)) { 04041 VariantClear(&result); 04042 ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface"); 04043 } 04044 04045 if (V_VT(&result) == VT_UNKNOWN) { 04046 hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result), 04047 &IID_IEnumVARIANT, 04048 &p); 04049 pEnum = p; 04050 } else if (V_VT(&result) == VT_DISPATCH) { 04051 hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result), 04052 &IID_IEnumVARIANT, 04053 &p); 04054 pEnum = p; 04055 } 04056 if (FAILED(hr) || !pEnum) { 04057 VariantClear(&result); 04058 ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface"); 04059 } 04060 04061 VariantClear(&result); 04062 rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum); 04063 return Qnil; 04064 } 04065 04066 /* 04067 * call-seq: 04068 * WIN32OLE#method_missing(id [,arg1, arg2, ...]) 04069 * 04070 * Calls WIN32OLE#invoke method. 04071 */ 04072 static VALUE 04073 fole_missing(int argc, VALUE *argv, VALUE self) 04074 { 04075 ID id; 04076 const char* mname; 04077 int n; 04078 id = rb_to_id(argv[0]); 04079 mname = rb_id2name(id); 04080 if(!mname) { 04081 rb_raise(rb_eRuntimeError, "fail: unknown method or property"); 04082 } 04083 n = strlen(mname); 04084 if(mname[n-1] == '=') { 04085 argv[0] = rb_enc_str_new(mname, n-1, cWIN32OLE_enc); 04086 04087 return ole_propertyput(self, argv[0], argv[1]); 04088 } 04089 else { 04090 argv[0] = rb_enc_str_new(mname, n, cWIN32OLE_enc); 04091 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); 04092 } 04093 } 04094 04095 static VALUE 04096 ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name) 04097 { 04098 HRESULT hr; 04099 TYPEATTR *pTypeAttr; 04100 BSTR bstr; 04101 FUNCDESC *pFuncDesc; 04102 WORD i; 04103 VALUE fname; 04104 VALUE method = Qnil; 04105 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04106 if (FAILED(hr)) { 04107 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04108 } 04109 for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) { 04110 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); 04111 if (FAILED(hr)) 04112 continue; 04113 04114 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 04115 &bstr, NULL, NULL, NULL); 04116 if (FAILED(hr)) { 04117 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04118 continue; 04119 } 04120 fname = WC2VSTR(bstr); 04121 if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) { 04122 olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname); 04123 method = self; 04124 } 04125 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04126 pFuncDesc=NULL; 04127 } 04128 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04129 return method; 04130 } 04131 04132 static VALUE 04133 olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name) 04134 { 04135 HRESULT hr; 04136 TYPEATTR *pTypeAttr; 04137 WORD i; 04138 HREFTYPE href; 04139 ITypeInfo *pRefTypeInfo; 04140 VALUE method = Qnil; 04141 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04142 if (FAILED(hr)) { 04143 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04144 } 04145 method = ole_method_sub(self, 0, pTypeInfo, name); 04146 if (method != Qnil) { 04147 return method; 04148 } 04149 for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){ 04150 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 04151 if(FAILED(hr)) 04152 continue; 04153 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 04154 if (FAILED(hr)) 04155 continue; 04156 method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name); 04157 OLE_RELEASE(pRefTypeInfo); 04158 } 04159 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04160 return method; 04161 } 04162 04163 static VALUE 04164 ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask) 04165 { 04166 HRESULT hr; 04167 TYPEATTR *pTypeAttr; 04168 BSTR bstr; 04169 FUNCDESC *pFuncDesc; 04170 VALUE method; 04171 WORD i; 04172 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04173 if (FAILED(hr)) { 04174 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04175 } 04176 for(i = 0; i < pTypeAttr->cFuncs; i++) { 04177 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); 04178 if (FAILED(hr)) 04179 continue; 04180 04181 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 04182 &bstr, NULL, NULL, NULL); 04183 if (FAILED(hr)) { 04184 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04185 continue; 04186 } 04187 if(pFuncDesc->invkind & mask) { 04188 method = folemethod_s_allocate(cWIN32OLE_METHOD); 04189 olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo, 04190 i, WC2VSTR(bstr)); 04191 rb_ary_push(methods, method); 04192 } 04193 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 04194 pFuncDesc=NULL; 04195 } 04196 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04197 04198 return methods; 04199 } 04200 04201 static VALUE 04202 ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) 04203 { 04204 HRESULT hr; 04205 TYPEATTR *pTypeAttr; 04206 WORD i; 04207 HREFTYPE href; 04208 ITypeInfo *pRefTypeInfo; 04209 VALUE methods = rb_ary_new(); 04210 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 04211 if (FAILED(hr)) { 04212 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 04213 } 04214 04215 ole_methods_sub(0, pTypeInfo, methods, mask); 04216 for(i=0; i < pTypeAttr->cImplTypes; i++){ 04217 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 04218 if(FAILED(hr)) 04219 continue; 04220 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 04221 if (FAILED(hr)) 04222 continue; 04223 ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask); 04224 OLE_RELEASE(pRefTypeInfo); 04225 } 04226 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 04227 return methods; 04228 } 04229 04230 static HRESULT 04231 typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti) 04232 { 04233 ITypeInfo *pTypeInfo; 04234 ITypeLib *pTypeLib; 04235 BSTR bstr; 04236 VALUE type; 04237 UINT i; 04238 UINT count; 04239 LCID lcid = cWIN32OLE_lcid; 04240 HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 04241 0, lcid, &pTypeInfo); 04242 if(FAILED(hr)) { 04243 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 04244 } 04245 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, 04246 -1, 04247 &bstr, 04248 NULL, NULL, NULL); 04249 type = WC2VSTR(bstr); 04250 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); 04251 OLE_RELEASE(pTypeInfo); 04252 if (FAILED(hr)) { 04253 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); 04254 } 04255 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 04256 for (i = 0; i < count; i++) { 04257 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 04258 &bstr, NULL, NULL, NULL); 04259 if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) { 04260 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 04261 if (SUCCEEDED(hr)) { 04262 *ppti = pTypeInfo; 04263 break; 04264 } 04265 } 04266 } 04267 OLE_RELEASE(pTypeLib); 04268 return hr; 04269 } 04270 04271 static VALUE 04272 ole_methods(VALUE self, int mask) 04273 { 04274 ITypeInfo *pTypeInfo; 04275 HRESULT hr; 04276 VALUE methods; 04277 struct oledata *pole; 04278 04279 OLEData_Get_Struct(self, pole); 04280 methods = rb_ary_new(); 04281 04282 hr = typeinfo_from_ole(pole, &pTypeInfo); 04283 if(FAILED(hr)) 04284 return methods; 04285 rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask)); 04286 OLE_RELEASE(pTypeInfo); 04287 return methods; 04288 } 04289 04290 /* 04291 * call-seq: 04292 * WIN32OLE#ole_methods 04293 * 04294 * Returns the array of WIN32OLE_METHOD object. 04295 * The element is OLE method of WIN32OLE object. 04296 * 04297 * excel = WIN32OLE.new('Excel.Application') 04298 * methods = excel.ole_methods 04299 * 04300 */ 04301 static VALUE 04302 fole_methods(VALUE self) 04303 { 04304 return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); 04305 } 04306 04307 /* 04308 * call-seq: 04309 * WIN32OLE#ole_get_methods 04310 * 04311 * Returns the array of WIN32OLE_METHOD object . 04312 * The element of the array is property (gettable) of WIN32OLE object. 04313 * 04314 * excel = WIN32OLE.new('Excel.Application') 04315 * properties = excel.ole_get_methods 04316 */ 04317 static VALUE 04318 fole_get_methods(VALUE self) 04319 { 04320 return ole_methods( self, INVOKE_PROPERTYGET); 04321 } 04322 04323 /* 04324 * call-seq: 04325 * WIN32OLE#ole_put_methods 04326 * 04327 * Returns the array of WIN32OLE_METHOD object . 04328 * The element of the array is property (settable) of WIN32OLE object. 04329 * 04330 * excel = WIN32OLE.new('Excel.Application') 04331 * properties = excel.ole_put_methods 04332 */ 04333 static VALUE 04334 fole_put_methods(VALUE self) 04335 { 04336 return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF); 04337 } 04338 04339 /* 04340 * call-seq: 04341 * WIN32OLE#ole_func_methods 04342 * 04343 * Returns the array of WIN32OLE_METHOD object . 04344 * The element of the array is property (settable) of WIN32OLE object. 04345 * 04346 * excel = WIN32OLE.new('Excel.Application') 04347 * properties = excel.ole_func_methods 04348 * 04349 */ 04350 static VALUE 04351 fole_func_methods(VALUE self) 04352 { 04353 return ole_methods( self, INVOKE_FUNC); 04354 } 04355 04356 static VALUE 04357 ole_type_from_itypeinfo(ITypeInfo *pTypeInfo) 04358 { 04359 ITypeLib *pTypeLib; 04360 VALUE type = Qnil; 04361 HRESULT hr; 04362 unsigned int index; 04363 BSTR bstr; 04364 04365 hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index ); 04366 if(FAILED(hr)) { 04367 return Qnil; 04368 } 04369 hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index, 04370 &bstr, NULL, NULL, NULL); 04371 OLE_RELEASE(pTypeLib); 04372 if (FAILED(hr)) { 04373 return Qnil; 04374 } 04375 type = foletype_s_allocate(cWIN32OLE_TYPE); 04376 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr)); 04377 return type; 04378 } 04379 04380 /* 04381 * call-seq: 04382 * WIN32OLE#ole_type 04383 * 04384 * Returns WIN32OLE_TYPE object. 04385 * 04386 * excel = WIN32OLE.new('Excel.Application') 04387 * tobj = excel.ole_type 04388 */ 04389 static VALUE 04390 fole_type(VALUE self) 04391 { 04392 ITypeInfo *pTypeInfo; 04393 HRESULT hr; 04394 struct oledata *pole; 04395 LCID lcid = cWIN32OLE_lcid; 04396 VALUE type = Qnil; 04397 04398 OLEData_Get_Struct(self, pole); 04399 04400 hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo ); 04401 if(FAILED(hr)) { 04402 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 04403 } 04404 type = ole_type_from_itypeinfo(pTypeInfo); 04405 OLE_RELEASE(pTypeInfo); 04406 if (type == Qnil) { 04407 rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo"); 04408 } 04409 return type; 04410 } 04411 04412 static VALUE 04413 ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo) 04414 { 04415 HRESULT hr; 04416 ITypeLib *pTypeLib; 04417 unsigned int index; 04418 VALUE retval = Qnil; 04419 04420 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); 04421 if(FAILED(hr)) { 04422 return Qnil; 04423 } 04424 retval = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0); 04425 oletypelib_set_member(retval, pTypeLib); 04426 return retval; 04427 } 04428 04429 /* 04430 * call-seq: 04431 * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object 04432 * 04433 * Returns the WIN32OLE_TYPELIB object. The object represents the 04434 * type library which contains the WIN32OLE object. 04435 * 04436 * excel = WIN32OLE.new('Excel.Application') 04437 * tlib = excel.ole_typelib 04438 * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library' 04439 */ 04440 static VALUE 04441 fole_typelib(VALUE self) 04442 { 04443 struct oledata *pole; 04444 HRESULT hr; 04445 ITypeInfo *pTypeInfo; 04446 LCID lcid = cWIN32OLE_lcid; 04447 VALUE vtlib = Qnil; 04448 04449 OLEData_Get_Struct(self, pole); 04450 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, 04451 0, lcid, &pTypeInfo); 04452 if(FAILED(hr)) { 04453 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); 04454 } 04455 vtlib = ole_typelib_from_itypeinfo(pTypeInfo); 04456 OLE_RELEASE(pTypeInfo); 04457 if (vtlib == Qnil) { 04458 rb_raise(rb_eRuntimeError, "failed to get type library info."); 04459 } 04460 return vtlib; 04461 } 04462 04463 /* 04464 * call-seq: 04465 * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object 04466 * 04467 * Returns WIN32OLE object for a specific dispatch or dual 04468 * interface specified by iid. 04469 * 04470 * ie = WIN32OLE.new('InternetExplorer.Application') 04471 * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp 04472 */ 04473 static VALUE 04474 fole_query_interface(VALUE self, VALUE str_iid) 04475 { 04476 HRESULT hr; 04477 OLECHAR *pBuf; 04478 IID iid; 04479 struct oledata *pole; 04480 IDispatch *pDispatch; 04481 void *p; 04482 04483 pBuf = ole_vstr2wc(str_iid); 04484 hr = CLSIDFromString(pBuf, &iid); 04485 SysFreeString(pBuf); 04486 if(FAILED(hr)) { 04487 ole_raise(hr, eWIN32OLERuntimeError, 04488 "invalid iid: `%s'", 04489 StringValuePtr(str_iid)); 04490 } 04491 04492 OLEData_Get_Struct(self, pole); 04493 if(!pole->pDispatch) { 04494 rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); 04495 } 04496 04497 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid, 04498 &p); 04499 if(FAILED(hr)) { 04500 ole_raise(hr, eWIN32OLERuntimeError, 04501 "failed to get interface `%s'", 04502 StringValuePtr(str_iid)); 04503 } 04504 04505 pDispatch = p; 04506 return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); 04507 } 04508 04509 /* 04510 * call-seq: 04511 * WIN32OLE#ole_respond_to?(method) -> true or false 04512 * 04513 * Returns true when OLE object has OLE method, otherwise returns false. 04514 * 04515 * ie = WIN32OLE.new('InternetExplorer.Application') 04516 * ie.ole_respond_to?("gohome") => true 04517 */ 04518 static VALUE 04519 fole_respond_to(VALUE self, VALUE method) 04520 { 04521 struct oledata *pole; 04522 BSTR wcmdname; 04523 DISPID DispID; 04524 HRESULT hr; 04525 rb_secure(4); 04526 if(TYPE(method) != T_STRING && TYPE(method) != T_SYMBOL) { 04527 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 04528 } 04529 if (TYPE(method) == T_SYMBOL) { 04530 method = rb_sym_to_s(method); 04531 } 04532 OLEData_Get_Struct(self, pole); 04533 wcmdname = ole_vstr2wc(method); 04534 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, 04535 &wcmdname, 1, cWIN32OLE_lcid, &DispID); 04536 SysFreeString(wcmdname); 04537 return SUCCEEDED(hr) ? Qtrue : Qfalse; 04538 } 04539 04540 static HRESULT 04541 ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile) 04542 { 04543 HRESULT hr; 04544 ITypeLib *pTypeLib; 04545 UINT i; 04546 04547 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); 04548 if (FAILED(hr)) { 04549 return hr; 04550 } 04551 04552 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 04553 name, helpstr, 04554 helpcontext, helpfile); 04555 if (FAILED(hr)) { 04556 OLE_RELEASE(pTypeLib); 04557 return hr; 04558 } 04559 OLE_RELEASE(pTypeLib); 04560 return hr; 04561 } 04562 04563 static VALUE 04564 ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 04565 { 04566 HRESULT hr; 04567 BSTR bstr; 04568 ITypeInfo *pRefTypeInfo; 04569 VALUE type = Qnil; 04570 04571 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 04572 V_UNION1(pTypeDesc, hreftype), 04573 &pRefTypeInfo); 04574 if(FAILED(hr)) 04575 return Qnil; 04576 hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL); 04577 if(FAILED(hr)) { 04578 OLE_RELEASE(pRefTypeInfo); 04579 return Qnil; 04580 } 04581 OLE_RELEASE(pRefTypeInfo); 04582 type = WC2VSTR(bstr); 04583 if(typedetails != Qnil) 04584 rb_ary_push(typedetails, type); 04585 return type; 04586 } 04587 04588 static VALUE 04589 ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 04590 { 04591 TYPEDESC *p = pTypeDesc; 04592 VALUE type = rb_str_new2(""); 04593 04594 if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) { 04595 p = V_UNION1(p, lptdesc); 04596 type = ole_typedesc2val(pTypeInfo, p, typedetails); 04597 } 04598 return type; 04599 } 04600 04601 static VALUE 04602 ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) 04603 { 04604 VALUE str; 04605 VALUE typestr = Qnil; 04606 switch(pTypeDesc->vt) { 04607 case VT_I2: 04608 typestr = rb_str_new2("I2"); 04609 break; 04610 case VT_I4: 04611 typestr = rb_str_new2("I4"); 04612 break; 04613 case VT_R4: 04614 typestr = rb_str_new2("R4"); 04615 break; 04616 case VT_R8: 04617 typestr = rb_str_new2("R8"); 04618 break; 04619 case VT_CY: 04620 typestr = rb_str_new2("CY"); 04621 break; 04622 case VT_DATE: 04623 typestr = rb_str_new2("DATE"); 04624 break; 04625 case VT_BSTR: 04626 typestr = rb_str_new2("BSTR"); 04627 break; 04628 case VT_BOOL: 04629 typestr = rb_str_new2("BOOL"); 04630 break; 04631 case VT_VARIANT: 04632 typestr = rb_str_new2("VARIANT"); 04633 break; 04634 case VT_DECIMAL: 04635 typestr = rb_str_new2("DECIMAL"); 04636 break; 04637 case VT_I1: 04638 typestr = rb_str_new2("I1"); 04639 break; 04640 case VT_UI1: 04641 typestr = rb_str_new2("UI1"); 04642 break; 04643 case VT_UI2: 04644 typestr = rb_str_new2("UI2"); 04645 break; 04646 case VT_UI4: 04647 typestr = rb_str_new2("UI4"); 04648 break; 04649 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 04650 case VT_I8: 04651 typestr = rb_str_new2("I8"); 04652 break; 04653 case VT_UI8: 04654 typestr = rb_str_new2("UI8"); 04655 break; 04656 #endif 04657 case VT_INT: 04658 typestr = rb_str_new2("INT"); 04659 break; 04660 case VT_UINT: 04661 typestr = rb_str_new2("UINT"); 04662 break; 04663 case VT_VOID: 04664 typestr = rb_str_new2("VOID"); 04665 break; 04666 case VT_HRESULT: 04667 typestr = rb_str_new2("HRESULT"); 04668 break; 04669 case VT_PTR: 04670 typestr = rb_str_new2("PTR"); 04671 if(typedetails != Qnil) 04672 rb_ary_push(typedetails, typestr); 04673 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); 04674 case VT_SAFEARRAY: 04675 typestr = rb_str_new2("SAFEARRAY"); 04676 if(typedetails != Qnil) 04677 rb_ary_push(typedetails, typestr); 04678 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); 04679 case VT_CARRAY: 04680 typestr = rb_str_new2("CARRAY"); 04681 break; 04682 case VT_USERDEFINED: 04683 typestr = rb_str_new2("USERDEFINED"); 04684 if (typedetails != Qnil) 04685 rb_ary_push(typedetails, typestr); 04686 str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails); 04687 if (str != Qnil) { 04688 return str; 04689 } 04690 return typestr; 04691 case VT_UNKNOWN: 04692 typestr = rb_str_new2("UNKNOWN"); 04693 break; 04694 case VT_DISPATCH: 04695 typestr = rb_str_new2("DISPATCH"); 04696 break; 04697 case VT_ERROR: 04698 typestr = rb_str_new2("ERROR"); 04699 break; 04700 case VT_LPWSTR: 04701 typestr = rb_str_new2("LPWSTR"); 04702 break; 04703 case VT_LPSTR: 04704 typestr = rb_str_new2("LPSTR"); 04705 break; 04706 default: 04707 typestr = rb_str_new2("Unknown Type "); 04708 rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10)); 04709 break; 04710 } 04711 if (typedetails != Qnil) 04712 rb_ary_push(typedetails, typestr); 04713 return typestr; 04714 } 04715 04716 /* 04717 * call-seq: 04718 * WIN32OLE#ole_method_help(method) 04719 * 04720 * Returns WIN32OLE_METHOD object corresponding with method 04721 * specified by 1st argument. 04722 * 04723 * excel = WIN32OLE.new('Excel.Application') 04724 * method = excel.ole_method_help('Quit') 04725 * 04726 */ 04727 static VALUE 04728 fole_method_help(VALUE self, VALUE cmdname) 04729 { 04730 ITypeInfo *pTypeInfo; 04731 HRESULT hr; 04732 struct oledata *pole; 04733 VALUE method, obj; 04734 04735 SafeStringValue(cmdname); 04736 OLEData_Get_Struct(self, pole); 04737 hr = typeinfo_from_ole(pole, &pTypeInfo); 04738 if(FAILED(hr)) 04739 ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo"); 04740 method = folemethod_s_allocate(cWIN32OLE_METHOD); 04741 obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname); 04742 OLE_RELEASE(pTypeInfo); 04743 if (obj == Qnil) 04744 rb_raise(eWIN32OLERuntimeError, "not found %s", 04745 StringValuePtr(cmdname)); 04746 return obj; 04747 } 04748 04749 /* 04750 * call-seq: 04751 * WIN32OLE#ole_activex_initialize() -> Qnil 04752 * 04753 * Initialize WIN32OLE object(ActiveX Control) by calling 04754 * IPersistMemory::InitNew. 04755 * 04756 * Before calling OLE method, some kind of the ActiveX controls 04757 * created with MFC should be initialized by calling 04758 * IPersistXXX::InitNew. 04759 * 04760 * If and only if you received the exception "HRESULT error code: 04761 * 0x8000ffff catastrophic failure", try this method before 04762 * invoking any ole_method. 04763 * 04764 * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control") 04765 * obj.ole_activex_initialize 04766 * obj.method(...) 04767 * 04768 */ 04769 static VALUE 04770 fole_activex_initialize(VALUE self) 04771 { 04772 struct oledata *pole; 04773 IPersistMemory *pPersistMemory; 04774 void *p; 04775 04776 HRESULT hr = S_OK; 04777 04778 OLEData_Get_Struct(self, pole); 04779 04780 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p); 04781 pPersistMemory = p; 04782 if (SUCCEEDED(hr)) { 04783 hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory); 04784 OLE_RELEASE(pPersistMemory); 04785 if (SUCCEEDED(hr)) { 04786 return Qnil; 04787 } 04788 } 04789 04790 if (FAILED(hr)) { 04791 ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control"); 04792 } 04793 04794 return Qnil; 04795 } 04796 04797 /* 04798 * call-seq: 04799 * WIN32OLE_TYPE.ole_classes(typelib) 04800 * 04801 * Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library. 04802 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead. 04803 */ 04804 static VALUE 04805 foletype_s_ole_classes(VALUE self, VALUE typelib) 04806 { 04807 VALUE obj; 04808 04809 /* 04810 rb_warn("%s is obsolete; use %s instead.", 04811 "WIN32OLE_TYPE.ole_classes", 04812 "WIN32OLE_TYPELIB.new(typelib).ole_types"); 04813 */ 04814 obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib); 04815 return rb_funcall(obj, rb_intern("ole_types"), 0); 04816 } 04817 04818 /* 04819 * call-seq: 04820 * WIN32OLE_TYPE.typelibs 04821 * 04822 * Returns array of type libraries. 04823 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead. 04824 * 04825 */ 04826 static VALUE 04827 foletype_s_typelibs(VALUE self) 04828 { 04829 /* 04830 rb_warn("%s is obsolete. use %s instead.", 04831 "WIN32OLE_TYPE.typelibs", 04832 "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}"); 04833 */ 04834 return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}"); 04835 } 04836 04837 /* 04838 * call-seq: 04839 * WIN32OLE_TYPE.progids 04840 * 04841 * Returns array of ProgID. 04842 */ 04843 static VALUE 04844 foletype_s_progids(VALUE self) 04845 { 04846 HKEY hclsids, hclsid; 04847 DWORD i; 04848 LONG err; 04849 VALUE clsid; 04850 VALUE v = rb_str_new2(""); 04851 VALUE progids = rb_ary_new(); 04852 04853 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids); 04854 if(err != ERROR_SUCCESS) { 04855 return progids; 04856 } 04857 for(i = 0; ; i++) { 04858 clsid = reg_enum_key(hclsids, i); 04859 if (clsid == Qnil) 04860 break; 04861 err = reg_open_vkey(hclsids, clsid, &hclsid); 04862 if (err != ERROR_SUCCESS) 04863 continue; 04864 if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil) 04865 rb_ary_push(progids, v); 04866 if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil) 04867 rb_ary_push(progids, v); 04868 RegCloseKey(hclsid); 04869 } 04870 RegCloseKey(hclsids); 04871 return progids; 04872 } 04873 04874 static VALUE 04875 foletype_s_allocate(VALUE klass) 04876 { 04877 struct oletypedata *poletype; 04878 VALUE obj; 04879 ole_initialize(); 04880 obj = Data_Make_Struct(klass,struct oletypedata,0,oletype_free,poletype); 04881 poletype->pTypeInfo = NULL; 04882 return obj; 04883 } 04884 04885 static VALUE 04886 oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name) 04887 { 04888 struct oletypedata *ptype; 04889 Data_Get_Struct(self, struct oletypedata, ptype); 04890 rb_ivar_set(self, rb_intern("name"), name); 04891 ptype->pTypeInfo = pTypeInfo; 04892 if(pTypeInfo) OLE_ADDREF(pTypeInfo); 04893 return self; 04894 } 04895 04896 static VALUE 04897 oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) 04898 { 04899 04900 long count; 04901 int i; 04902 HRESULT hr; 04903 BSTR bstr; 04904 VALUE typelib; 04905 ITypeInfo *pTypeInfo; 04906 04907 VALUE found = Qfalse; 04908 04909 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 04910 for (i = 0; i < count && found == Qfalse; i++) { 04911 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); 04912 if (FAILED(hr)) 04913 continue; 04914 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, 04915 &bstr, NULL, NULL, NULL); 04916 if (FAILED(hr)) 04917 continue; 04918 typelib = WC2VSTR(bstr); 04919 if (rb_str_cmp(oleclass, typelib) == 0) { 04920 oletype_set_member(self, pTypeInfo, typelib); 04921 found = Qtrue; 04922 } 04923 OLE_RELEASE(pTypeInfo); 04924 } 04925 return found; 04926 } 04927 04928 /* 04929 * Document-class: WIN32OLE_TYPELIB 04930 * 04931 * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information. 04932 */ 04933 04934 static VALUE 04935 oletypelib_set_member(VALUE self, ITypeLib *pTypeLib) 04936 { 04937 struct oletypelibdata *ptlib; 04938 Data_Get_Struct(self, struct oletypelibdata, ptlib); 04939 ptlib->pTypeLib = pTypeLib; 04940 return self; 04941 } 04942 04943 static ITypeLib * 04944 oletypelib_get_typelib(VALUE self) 04945 { 04946 struct oletypelibdata *ptlib; 04947 Data_Get_Struct(self, struct oletypelibdata, ptlib); 04948 return ptlib->pTypeLib; 04949 } 04950 04951 static void 04952 oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr) 04953 { 04954 HRESULT hr; 04955 hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr); 04956 if (FAILED(hr)) { 04957 ole_raise(hr, eWIN32OLERuntimeError, 04958 "failed to get library attribute(TLIBATTR) from ITypeLib"); 04959 } 04960 } 04961 04962 /* 04963 * call-seq: 04964 * 04965 * WIN32OLE_TYPELIB.typelibs 04966 * 04967 * Returns the array of WIN32OLE_TYPELIB object. 04968 * 04969 * tlibs = WIN32OLE_TYPELIB.typelibs 04970 * 04971 */ 04972 static VALUE 04973 foletypelib_s_typelibs(VALUE self) 04974 { 04975 HKEY htypelib, hguid; 04976 DWORD i, j; 04977 LONG err; 04978 VALUE guid; 04979 VALUE version; 04980 VALUE name = Qnil; 04981 VALUE typelibs = rb_ary_new(); 04982 VALUE typelib = Qnil; 04983 HRESULT hr; 04984 ITypeLib *pTypeLib; 04985 04986 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 04987 if(err != ERROR_SUCCESS) { 04988 return typelibs; 04989 } 04990 for(i = 0; ; i++) { 04991 guid = reg_enum_key(htypelib, i); 04992 if (guid == Qnil) 04993 break; 04994 err = reg_open_vkey(htypelib, guid, &hguid); 04995 if (err != ERROR_SUCCESS) 04996 continue; 04997 for(j = 0; ; j++) { 04998 version = reg_enum_key(hguid, j); 04999 if (version == Qnil) 05000 break; 05001 if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) { 05002 hr = oletypelib_from_guid(guid, version, &pTypeLib); 05003 if (SUCCEEDED(hr)) { 05004 typelib = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0); 05005 oletypelib_set_member(typelib, pTypeLib); 05006 rb_ary_push(typelibs, typelib); 05007 } 05008 } 05009 } 05010 RegCloseKey(hguid); 05011 } 05012 RegCloseKey(htypelib); 05013 return typelibs; 05014 } 05015 05016 static VALUE 05017 make_version_str(VALUE major, VALUE minor) 05018 { 05019 VALUE version_str = Qnil; 05020 VALUE minor_str = Qnil; 05021 if (major == Qnil) { 05022 return Qnil; 05023 } 05024 version_str = rb_String(major); 05025 if (minor != Qnil) { 05026 minor_str = rb_String(minor); 05027 rb_str_cat2(version_str, "."); 05028 rb_str_append(version_str, minor_str); 05029 } 05030 return version_str; 05031 } 05032 05033 static VALUE 05034 oletypelib_search_registry2(VALUE self, VALUE args) 05035 { 05036 HKEY htypelib, hguid, hversion; 05037 double fver; 05038 DWORD j; 05039 LONG err; 05040 VALUE found = Qfalse; 05041 VALUE tlib; 05042 VALUE ver; 05043 VALUE version_str; 05044 VALUE version = Qnil; 05045 VALUE typelib = Qnil; 05046 HRESULT hr; 05047 ITypeLib *pTypeLib; 05048 05049 VALUE guid = rb_ary_entry(args, 0); 05050 version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2)); 05051 05052 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 05053 if(err != ERROR_SUCCESS) { 05054 return Qfalse; 05055 } 05056 err = reg_open_vkey(htypelib, guid, &hguid); 05057 if (err != ERROR_SUCCESS) { 05058 RegCloseKey(htypelib); 05059 return Qfalse; 05060 } 05061 if (version_str != Qnil) { 05062 err = reg_open_vkey(hguid, version_str, &hversion); 05063 if (err == ERROR_SUCCESS) { 05064 tlib = reg_get_val(hversion, NULL); 05065 if (tlib != Qnil) { 05066 typelib = tlib; 05067 version = version_str; 05068 } 05069 } 05070 RegCloseKey(hversion); 05071 } else { 05072 fver = 0.0; 05073 for(j = 0; ;j++) { 05074 ver = reg_enum_key(hguid, j); 05075 if (ver == Qnil) 05076 break; 05077 err = reg_open_vkey(hguid, ver, &hversion); 05078 if (err != ERROR_SUCCESS) 05079 continue; 05080 tlib = reg_get_val(hversion, NULL); 05081 if (tlib == Qnil) { 05082 RegCloseKey(hversion); 05083 continue; 05084 } 05085 if (fver < atof(StringValuePtr(ver))) { 05086 fver = atof(StringValuePtr(ver)); 05087 version = ver; 05088 typelib = tlib; 05089 } 05090 RegCloseKey(hversion); 05091 } 05092 } 05093 RegCloseKey(hguid); 05094 RegCloseKey(htypelib); 05095 if (typelib != Qnil) { 05096 hr = oletypelib_from_guid(guid, version, &pTypeLib); 05097 if (SUCCEEDED(hr)) { 05098 found = Qtrue; 05099 oletypelib_set_member(self, pTypeLib); 05100 } 05101 } 05102 return found; 05103 } 05104 05105 static VALUE 05106 oletypelib_search_registry(VALUE self, VALUE typelib) 05107 { 05108 HKEY htypelib, hguid, hversion; 05109 DWORD i, j; 05110 LONG err; 05111 VALUE found = Qfalse; 05112 VALUE tlib; 05113 VALUE guid; 05114 VALUE ver; 05115 HRESULT hr; 05116 ITypeLib *pTypeLib; 05117 05118 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); 05119 if(err != ERROR_SUCCESS) { 05120 return Qfalse; 05121 } 05122 for(i = 0; !found; i++) { 05123 guid = reg_enum_key(htypelib, i); 05124 if (guid == Qnil) 05125 break; 05126 err = reg_open_vkey(htypelib, guid, &hguid); 05127 if (err != ERROR_SUCCESS) 05128 continue; 05129 for(j = 0; found == Qfalse; j++) { 05130 ver = reg_enum_key(hguid, j); 05131 if (ver == Qnil) 05132 break; 05133 err = reg_open_vkey(hguid, ver, &hversion); 05134 if (err != ERROR_SUCCESS) 05135 continue; 05136 tlib = reg_get_val(hversion, NULL); 05137 if (tlib == Qnil) { 05138 RegCloseKey(hversion); 05139 continue; 05140 } 05141 if (rb_str_cmp(typelib, tlib) == 0) { 05142 hr = oletypelib_from_guid(guid, ver, &pTypeLib); 05143 if (SUCCEEDED(hr)) { 05144 oletypelib_set_member(self, pTypeLib); 05145 found = Qtrue; 05146 } 05147 } 05148 RegCloseKey(hversion); 05149 } 05150 RegCloseKey(hguid); 05151 } 05152 RegCloseKey(htypelib); 05153 return found; 05154 } 05155 05156 static VALUE 05157 foletypelib_s_allocate(VALUE klass) 05158 { 05159 struct oletypelibdata *poletypelib; 05160 VALUE obj; 05161 ole_initialize(); 05162 obj = Data_Make_Struct(klass, struct oletypelibdata, 0, oletypelib_free, poletypelib); 05163 poletypelib->pTypeLib = NULL; 05164 return obj; 05165 } 05166 05167 /* 05168 * call-seq: 05169 * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object 05170 * 05171 * Returns a new WIN32OLE_TYPELIB object. 05172 * 05173 * The first argument <i>typelib</i> specifies OLE type library name or GUID or 05174 * OLE library file. 05175 * The second argument is major version or version of the type library. 05176 * The third argument is minor version. 05177 * The second argument and third argument are optional. 05178 * If the first argument is type library name, then the second and third argument 05179 * are ignored. 05180 * 05181 * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05182 * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}') 05183 * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3) 05184 * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3) 05185 * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL") 05186 * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library' 05187 * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library' 05188 * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library' 05189 * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library' 05190 * puts tlib5.name # -> 'Microsoft Shell Controls And Automation' 05191 * 05192 */ 05193 static VALUE 05194 foletypelib_initialize(VALUE self, VALUE args) 05195 { 05196 VALUE found = Qfalse; 05197 VALUE typelib = Qnil; 05198 int len = 0; 05199 OLECHAR * pbuf; 05200 ITypeLib *pTypeLib; 05201 HRESULT hr = S_OK; 05202 05203 len = RARRAY_LEN(args); 05204 if (len < 1 || len > 3) { 05205 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); 05206 } 05207 05208 typelib = rb_ary_entry(args, 0); 05209 05210 SafeStringValue(typelib); 05211 05212 found = oletypelib_search_registry(self, typelib); 05213 if (found == Qfalse) { 05214 found = oletypelib_search_registry2(self, args); 05215 } 05216 if (found == Qfalse) { 05217 pbuf = ole_vstr2wc(typelib); 05218 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); 05219 SysFreeString(pbuf); 05220 if (SUCCEEDED(hr)) { 05221 found = Qtrue; 05222 oletypelib_set_member(self, pTypeLib); 05223 } 05224 } 05225 05226 if (found == Qfalse) { 05227 rb_raise(eWIN32OLERuntimeError, "not found type library `%s`", 05228 StringValuePtr(typelib)); 05229 } 05230 return self; 05231 } 05232 05233 /* 05234 * call-seq: 05235 * WIN32OLE_TYPELIB#guid -> The guid string. 05236 * 05237 * Returns guid string which specifies type library. 05238 * 05239 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05240 * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}' 05241 */ 05242 static VALUE 05243 foletypelib_guid(VALUE self) 05244 { 05245 ITypeLib *pTypeLib; 05246 OLECHAR bstr[80]; 05247 VALUE guid = Qnil; 05248 int len; 05249 TLIBATTR *pTLibAttr; 05250 05251 pTypeLib = oletypelib_get_typelib(self); 05252 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05253 len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 05254 if (len > 3) { 05255 guid = ole_wc2vstr(bstr, FALSE); 05256 } 05257 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05258 return guid; 05259 } 05260 05261 /* 05262 * call-seq: 05263 * WIN32OLE_TYPELIB#name -> The type library name 05264 * 05265 * Returns the type library name. 05266 * 05267 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05268 * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library' 05269 */ 05270 static VALUE 05271 foletypelib_name(VALUE self) 05272 { 05273 ITypeLib *pTypeLib; 05274 HRESULT hr; 05275 BSTR bstr; 05276 VALUE name; 05277 pTypeLib = oletypelib_get_typelib(self); 05278 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, 05279 NULL, &bstr, NULL, NULL); 05280 05281 if (FAILED(hr)) { 05282 ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib"); 05283 } 05284 name = WC2VSTR(bstr); 05285 return rb_enc_str_new(StringValuePtr(name), strlen(StringValuePtr(name)), cWIN32OLE_enc); 05286 } 05287 05288 /* 05289 * call-seq: 05290 * WIN32OLE_TYPELIB#version -> The type library version. 05291 * 05292 * Returns the type library version. 05293 * 05294 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05295 * puts tlib.version #-> 1.3 05296 */ 05297 static VALUE 05298 foletypelib_version(VALUE self) 05299 { 05300 TLIBATTR *pTLibAttr; 05301 VALUE major; 05302 VALUE minor; 05303 ITypeLib *pTypeLib; 05304 05305 pTypeLib = oletypelib_get_typelib(self); 05306 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05307 major = INT2NUM(pTLibAttr->wMajorVerNum); 05308 minor = INT2NUM(pTLibAttr->wMinorVerNum); 05309 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05310 return rb_Float(make_version_str(major, minor)); 05311 } 05312 05313 /* 05314 * call-seq: 05315 * WIN32OLE_TYPELIB#major_version -> The type library major version. 05316 * 05317 * Returns the type library major version. 05318 * 05319 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05320 * puts tlib.major_version # -> 1 05321 */ 05322 static VALUE 05323 foletypelib_major_version(VALUE self) 05324 { 05325 TLIBATTR *pTLibAttr; 05326 VALUE major; 05327 ITypeLib *pTypeLib; 05328 pTypeLib = oletypelib_get_typelib(self); 05329 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05330 05331 major = INT2NUM(pTLibAttr->wMajorVerNum); 05332 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05333 return major; 05334 } 05335 05336 /* 05337 * call-seq: 05338 * WIN32OLE_TYPELIB#minor_version -> The type library minor version. 05339 * 05340 * Returns the type library minor version. 05341 * 05342 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05343 * puts tlib.minor_version # -> 3 05344 */ 05345 static VALUE 05346 foletypelib_minor_version(VALUE self) 05347 { 05348 TLIBATTR *pTLibAttr; 05349 VALUE minor; 05350 ITypeLib *pTypeLib; 05351 pTypeLib = oletypelib_get_typelib(self); 05352 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05353 minor = INT2NUM(pTLibAttr->wMinorVerNum); 05354 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05355 return minor; 05356 } 05357 05358 static VALUE 05359 oletypelib_path(VALUE guid, VALUE version) 05360 { 05361 int k; 05362 LONG err; 05363 HKEY hkey; 05364 HKEY hlang; 05365 VALUE lang; 05366 VALUE path = Qnil; 05367 05368 VALUE key = rb_str_new2("TypeLib\\"); 05369 rb_str_concat(key, guid); 05370 rb_str_cat2(key, "\\"); 05371 rb_str_concat(key, version); 05372 05373 err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey); 05374 if (err != ERROR_SUCCESS) { 05375 return Qnil; 05376 } 05377 for(k = 0; path == Qnil; k++) { 05378 lang = reg_enum_key(hkey, k); 05379 if (lang == Qnil) 05380 break; 05381 err = reg_open_vkey(hkey, lang, &hlang); 05382 if (err == ERROR_SUCCESS) { 05383 path = reg_get_typelib_file_path(hlang); 05384 RegCloseKey(hlang); 05385 } 05386 } 05387 RegCloseKey(hkey); 05388 return path; 05389 } 05390 05391 static HRESULT 05392 oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib) 05393 { 05394 VALUE path; 05395 OLECHAR *pBuf; 05396 HRESULT hr; 05397 path = oletypelib_path(guid, version); 05398 if (path == Qnil) { 05399 return E_UNEXPECTED; 05400 } 05401 pBuf = ole_vstr2wc(path); 05402 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib); 05403 SysFreeString(pBuf); 05404 return hr; 05405 } 05406 05407 /* 05408 * call-seq: 05409 * WIN32OLE_TYPELIB#path -> The type library file path. 05410 * 05411 * Returns the type library file path. 05412 * 05413 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05414 * puts tlib.path #-> 'C:\...\EXCEL9.OLB' 05415 */ 05416 static VALUE 05417 foletypelib_path(VALUE self) 05418 { 05419 TLIBATTR *pTLibAttr; 05420 HRESULT hr = S_OK; 05421 BSTR bstr; 05422 LCID lcid = cWIN32OLE_lcid; 05423 VALUE path; 05424 ITypeLib *pTypeLib; 05425 05426 pTypeLib = oletypelib_get_typelib(self); 05427 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05428 hr = QueryPathOfRegTypeLib(&pTLibAttr->guid, 05429 pTLibAttr->wMajorVerNum, 05430 pTLibAttr->wMinorVerNum, 05431 lcid, 05432 &bstr); 05433 if (FAILED(hr)) { 05434 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05435 ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib"); 05436 } 05437 05438 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05439 path = WC2VSTR(bstr); 05440 return rb_enc_str_new(StringValuePtr(path), strlen(StringValuePtr(path)), cWIN32OLE_enc); 05441 } 05442 05443 /* 05444 * call-seq: 05445 * WIN32OLE_TYPELIB#visible? 05446 * 05447 * Returns true if the type library information is not hidden. 05448 * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN, 05449 * the method returns false, otherwise, returns true. 05450 * If the method fails to access the TLIBATTR information, then 05451 * WIN32OLERuntimeError is raised. 05452 * 05453 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05454 * tlib.visible? # => true 05455 */ 05456 static VALUE 05457 foletypelib_visible(VALUE self) 05458 { 05459 ITypeLib *pTypeLib = NULL; 05460 VALUE visible = Qtrue; 05461 TLIBATTR *pTLibAttr; 05462 05463 pTypeLib = oletypelib_get_typelib(self); 05464 oletypelib_get_libattr(pTypeLib, &pTLibAttr); 05465 05466 if ((pTLibAttr->wLibFlags == 0) || 05467 (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) || 05468 (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) { 05469 visible = Qfalse; 05470 } 05471 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); 05472 return visible; 05473 } 05474 05475 /* 05476 * call-seq: 05477 * WIN32OLE_TYPELIB#library_name 05478 * 05479 * Returns library name. 05480 * If the method fails to access library name, WIN32OLERuntimeError is raised. 05481 * 05482 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05483 * tlib.library_name # => Excel 05484 */ 05485 static VALUE 05486 foletypelib_library_name(VALUE self) 05487 { 05488 HRESULT hr; 05489 ITypeLib *pTypeLib = NULL; 05490 VALUE libname = Qnil; 05491 BSTR bstr; 05492 05493 pTypeLib = oletypelib_get_typelib(self); 05494 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, 05495 &bstr, NULL, NULL, NULL); 05496 if (FAILED(hr)) { 05497 ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name"); 05498 } 05499 libname = WC2VSTR(bstr); 05500 return libname; 05501 } 05502 05503 05504 /* 05505 * call-seq: 05506 * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library. 05507 * 05508 * Returns the type library file path. 05509 * 05510 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05511 * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...] 05512 */ 05513 static VALUE 05514 foletypelib_ole_types(VALUE self) 05515 { 05516 ITypeLib *pTypeLib = NULL; 05517 VALUE classes = rb_ary_new(); 05518 pTypeLib = oletypelib_get_typelib(self); 05519 ole_types_from_typelib(pTypeLib, classes); 05520 return classes; 05521 } 05522 05523 /* 05524 * call-seq: 05525 * WIN32OLE_TYPELIB#inspect -> String 05526 * 05527 * Returns the type library name with class name. 05528 * 05529 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') 05530 * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>" 05531 */ 05532 static VALUE 05533 foletypelib_inspect(VALUE self) 05534 { 05535 return default_inspect(self, "WIN32OLE_TYPELIB"); 05536 } 05537 05538 /* 05539 * Document-class: WIN32OLE_TYPE 05540 * 05541 * <code>WIN32OLE_TYPE</code> objects represent OLE type libarary information. 05542 */ 05543 05544 /* 05545 * call-seq: 05546 * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object 05547 * 05548 * Returns a new WIN32OLE_TYPE object. 05549 * The first argument <i>typelib</i> specifies OLE type library name. 05550 * The second argument specifies OLE class name. 05551 * 05552 * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05553 * # => WIN32OLE_TYPE object of Application class of Excel. 05554 */ 05555 static VALUE 05556 foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) 05557 { 05558 VALUE file; 05559 OLECHAR * pbuf; 05560 ITypeLib *pTypeLib; 05561 HRESULT hr; 05562 05563 SafeStringValue(oleclass); 05564 SafeStringValue(typelib); 05565 file = typelib_file(typelib); 05566 if (file == Qnil) { 05567 file = typelib; 05568 } 05569 pbuf = ole_vstr2wc(file); 05570 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); 05571 if (FAILED(hr)) 05572 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); 05573 SysFreeString(pbuf); 05574 if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) { 05575 OLE_RELEASE(pTypeLib); 05576 rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`", 05577 StringValuePtr(oleclass), StringValuePtr(typelib)); 05578 } 05579 OLE_RELEASE(pTypeLib); 05580 return self; 05581 } 05582 05583 /* 05584 * call-seq: 05585 * WIN32OLE_TYPE#name #=> OLE type name 05586 * 05587 * Returns OLE type name. 05588 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05589 * puts tobj.name # => Application 05590 */ 05591 static VALUE 05592 foletype_name(VALUE self) 05593 { 05594 return rb_ivar_get(self, rb_intern("name")); 05595 } 05596 05597 static VALUE 05598 ole_ole_type(ITypeInfo *pTypeInfo) 05599 { 05600 HRESULT hr; 05601 TYPEATTR *pTypeAttr; 05602 VALUE type = Qnil; 05603 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05604 if(FAILED(hr)){ 05605 return type; 05606 } 05607 switch(pTypeAttr->typekind) { 05608 case TKIND_ENUM: 05609 type = rb_str_new2("Enum"); 05610 break; 05611 case TKIND_RECORD: 05612 type = rb_str_new2("Record"); 05613 break; 05614 case TKIND_MODULE: 05615 type = rb_str_new2("Module"); 05616 break; 05617 case TKIND_INTERFACE: 05618 type = rb_str_new2("Interface"); 05619 break; 05620 case TKIND_DISPATCH: 05621 type = rb_str_new2("Dispatch"); 05622 break; 05623 case TKIND_COCLASS: 05624 type = rb_str_new2("Class"); 05625 break; 05626 case TKIND_ALIAS: 05627 type = rb_str_new2("Alias"); 05628 break; 05629 case TKIND_UNION: 05630 type = rb_str_new2("Union"); 05631 break; 05632 case TKIND_MAX: 05633 type = rb_str_new2("Max"); 05634 break; 05635 default: 05636 type = Qnil; 05637 break; 05638 } 05639 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05640 return type; 05641 } 05642 05643 /* 05644 * call-seq: 05645 * WIN32OLE_TYPE#ole_type #=> OLE type string. 05646 * 05647 * returns type of OLE class. 05648 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05649 * puts tobj.ole_type # => Class 05650 */ 05651 static VALUE 05652 foletype_ole_type(VALUE self) 05653 { 05654 struct oletypedata *ptype; 05655 Data_Get_Struct(self, struct oletypedata, ptype); 05656 return ole_ole_type(ptype->pTypeInfo); 05657 } 05658 05659 static VALUE 05660 ole_type_guid(ITypeInfo *pTypeInfo) 05661 { 05662 HRESULT hr; 05663 TYPEATTR *pTypeAttr; 05664 int len; 05665 OLECHAR bstr[80]; 05666 VALUE guid = Qnil; 05667 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05668 if (FAILED(hr)) 05669 return guid; 05670 len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); 05671 if (len > 3) { 05672 guid = ole_wc2vstr(bstr, FALSE); 05673 } 05674 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05675 return guid; 05676 } 05677 05678 /* 05679 * call-seq: 05680 * WIN32OLE_TYPE#guid #=> GUID 05681 * 05682 * Returns GUID. 05683 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05684 * puts tobj.guid # => {00024500-0000-0000-C000-000000000046} 05685 */ 05686 static VALUE 05687 foletype_guid(VALUE self) 05688 { 05689 struct oletypedata *ptype; 05690 Data_Get_Struct(self, struct oletypedata, ptype); 05691 return ole_type_guid(ptype->pTypeInfo); 05692 } 05693 05694 static VALUE 05695 ole_type_progid(ITypeInfo *pTypeInfo) 05696 { 05697 HRESULT hr; 05698 TYPEATTR *pTypeAttr; 05699 OLECHAR *pbuf; 05700 VALUE progid = Qnil; 05701 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05702 if (FAILED(hr)) 05703 return progid; 05704 hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf); 05705 if (SUCCEEDED(hr)) { 05706 progid = ole_wc2vstr(pbuf, FALSE); 05707 CoTaskMemFree(pbuf); 05708 } 05709 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05710 return progid; 05711 } 05712 05713 /* 05714 * call-seq: 05715 * WIN32OLE_TYPE#progid #=> ProgID 05716 * 05717 * Returns ProgID if it exists. If not found, then returns nil. 05718 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05719 * puts tobj.progid # => Excel.Application.9 05720 */ 05721 static VALUE 05722 foletype_progid(VALUE self) 05723 { 05724 struct oletypedata *ptype; 05725 Data_Get_Struct(self, struct oletypedata, ptype); 05726 return ole_type_progid(ptype->pTypeInfo); 05727 } 05728 05729 05730 static VALUE 05731 ole_type_visible(ITypeInfo *pTypeInfo) 05732 { 05733 HRESULT hr; 05734 TYPEATTR *pTypeAttr; 05735 VALUE visible; 05736 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05737 if (FAILED(hr)) 05738 return Qtrue; 05739 if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) { 05740 visible = Qfalse; 05741 } else { 05742 visible = Qtrue; 05743 } 05744 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05745 return visible; 05746 } 05747 05748 /* 05749 * call-seq: 05750 * WIN32OLE_TYPE#visible #=> true or false 05751 * 05752 * Returns true if the OLE class is public. 05753 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') 05754 * puts tobj.visible # => true 05755 */ 05756 static VALUE 05757 foletype_visible(VALUE self) 05758 { 05759 struct oletypedata *ptype; 05760 Data_Get_Struct(self, struct oletypedata, ptype); 05761 return ole_type_visible(ptype->pTypeInfo); 05762 } 05763 05764 static VALUE 05765 ole_type_major_version(ITypeInfo *pTypeInfo) 05766 { 05767 VALUE ver; 05768 TYPEATTR *pTypeAttr; 05769 HRESULT hr; 05770 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05771 if (FAILED(hr)) 05772 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 05773 ver = INT2FIX(pTypeAttr->wMajorVerNum); 05774 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05775 return ver; 05776 } 05777 05778 /* 05779 * call-seq: 05780 * WIN32OLE_TYPE#major_version 05781 * 05782 * Returns major version. 05783 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 05784 * puts tobj.major_version # => 8 05785 */ 05786 static VALUE 05787 foletype_major_version(VALUE self) 05788 { 05789 struct oletypedata *ptype; 05790 Data_Get_Struct(self, struct oletypedata, ptype); 05791 return ole_type_major_version(ptype->pTypeInfo); 05792 } 05793 05794 static VALUE 05795 ole_type_minor_version(ITypeInfo *pTypeInfo) 05796 { 05797 VALUE ver; 05798 TYPEATTR *pTypeAttr; 05799 HRESULT hr; 05800 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05801 if (FAILED(hr)) 05802 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 05803 ver = INT2FIX(pTypeAttr->wMinorVerNum); 05804 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05805 return ver; 05806 } 05807 05808 /* 05809 * call-seq: 05810 * WIN32OLE_TYPE#minor_version #=> OLE minor version 05811 * 05812 * Returns minor version. 05813 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 05814 * puts tobj.minor_version # => 2 05815 */ 05816 static VALUE 05817 foletype_minor_version(VALUE self) 05818 { 05819 struct oletypedata *ptype; 05820 Data_Get_Struct(self, struct oletypedata, ptype); 05821 return ole_type_minor_version(ptype->pTypeInfo); 05822 } 05823 05824 static VALUE 05825 ole_type_typekind(ITypeInfo *pTypeInfo) 05826 { 05827 VALUE typekind; 05828 TYPEATTR *pTypeAttr; 05829 HRESULT hr; 05830 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05831 if (FAILED(hr)) 05832 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 05833 typekind = INT2FIX(pTypeAttr->typekind); 05834 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05835 return typekind; 05836 } 05837 05838 /* 05839 * call-seq: 05840 * WIN32OLE_TYPE#typekind #=> number of type. 05841 * 05842 * Returns number which represents type. 05843 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') 05844 * puts tobj.typekind # => 4 05845 * 05846 */ 05847 static VALUE 05848 foletype_typekind(VALUE self) 05849 { 05850 struct oletypedata *ptype; 05851 Data_Get_Struct(self, struct oletypedata, ptype); 05852 return ole_type_typekind(ptype->pTypeInfo); 05853 } 05854 05855 static VALUE 05856 ole_type_helpstring(ITypeInfo *pTypeInfo) 05857 { 05858 HRESULT hr; 05859 BSTR bhelpstr; 05860 hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL); 05861 if(FAILED(hr)) { 05862 return Qnil; 05863 } 05864 return WC2VSTR(bhelpstr); 05865 } 05866 05867 /* 05868 * call-seq: 05869 * WIN32OLE_TYPE#helpstring #=> help string. 05870 * 05871 * Returns help string. 05872 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') 05873 * puts tobj.helpstring # => Web Browser interface 05874 */ 05875 static VALUE 05876 foletype_helpstring(VALUE self) 05877 { 05878 struct oletypedata *ptype; 05879 Data_Get_Struct(self, struct oletypedata, ptype); 05880 return ole_type_helpstring(ptype->pTypeInfo); 05881 } 05882 05883 static VALUE 05884 ole_type_src_type(ITypeInfo *pTypeInfo) 05885 { 05886 HRESULT hr; 05887 TYPEATTR *pTypeAttr; 05888 VALUE alias = Qnil; 05889 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 05890 if (FAILED(hr)) 05891 return alias; 05892 if(pTypeAttr->typekind != TKIND_ALIAS) { 05893 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05894 return alias; 05895 } 05896 alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil); 05897 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 05898 return alias; 05899 } 05900 05901 /* 05902 * call-seq: 05903 * WIN32OLE_TYPE#src_type #=> OLE source class 05904 * 05905 * Returns source class when the OLE class is 'Alias'. 05906 * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType') 05907 * puts tobj.src_type # => I4 05908 * 05909 */ 05910 static VALUE 05911 foletype_src_type(VALUE self) 05912 { 05913 struct oletypedata *ptype; 05914 Data_Get_Struct(self, struct oletypedata, ptype); 05915 return ole_type_src_type(ptype->pTypeInfo); 05916 } 05917 05918 static VALUE 05919 ole_type_helpfile(ITypeInfo *pTypeInfo) 05920 { 05921 HRESULT hr; 05922 BSTR bhelpfile; 05923 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile); 05924 if(FAILED(hr)) { 05925 return Qnil; 05926 } 05927 return WC2VSTR(bhelpfile); 05928 } 05929 05930 /* 05931 * call-seq: 05932 * WIN32OLE_TYPE#helpfile 05933 * 05934 * Returns helpfile path. If helpfile is not found, then returns nil. 05935 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 05936 * puts tobj.helpfile # => C:\...\VBAXL9.CHM 05937 * 05938 */ 05939 static VALUE 05940 foletype_helpfile(VALUE self) 05941 { 05942 struct oletypedata *ptype; 05943 Data_Get_Struct(self, struct oletypedata, ptype); 05944 return ole_type_helpfile(ptype->pTypeInfo); 05945 } 05946 05947 static VALUE 05948 ole_type_helpcontext(ITypeInfo *pTypeInfo) 05949 { 05950 HRESULT hr; 05951 DWORD helpcontext; 05952 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, 05953 &helpcontext, NULL); 05954 if(FAILED(hr)) 05955 return Qnil; 05956 return INT2FIX(helpcontext); 05957 } 05958 05959 /* 05960 * call-seq: 05961 * WIN32OLE_TYPE#helpcontext 05962 * 05963 * Returns helpcontext. If helpcontext is not found, then returns nil. 05964 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 05965 * puts tobj.helpfile # => 131185 05966 */ 05967 static VALUE 05968 foletype_helpcontext(VALUE self) 05969 { 05970 struct oletypedata *ptype; 05971 Data_Get_Struct(self, struct oletypedata, ptype); 05972 return ole_type_helpcontext(ptype->pTypeInfo); 05973 } 05974 05975 /* 05976 * call-seq: 05977 * WIN32OLE_TYPE#ole_typelib 05978 * 05979 * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE 05980 * object. If it is not found, then returns nil. 05981 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 05982 * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library' 05983 */ 05984 static VALUE 05985 foletype_ole_typelib(VALUE self) 05986 { 05987 struct oletypedata *ptype; 05988 Data_Get_Struct(self, struct oletypedata, ptype); 05989 return ole_typelib_from_itypeinfo(ptype->pTypeInfo); 05990 } 05991 05992 static VALUE 05993 ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) 05994 { 05995 HRESULT hr; 05996 ITypeInfo *pRefTypeInfo; 05997 HREFTYPE href; 05998 WORD i; 05999 VALUE type; 06000 TYPEATTR *pTypeAttr; 06001 int flags; 06002 06003 VALUE types = rb_ary_new(); 06004 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 06005 if (FAILED(hr)) { 06006 return types; 06007 } 06008 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 06009 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 06010 if (FAILED(hr)) 06011 continue; 06012 06013 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); 06014 if (FAILED(hr)) 06015 continue; 06016 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); 06017 if (FAILED(hr)) 06018 continue; 06019 06020 if ((flags & implflags) == implflags) { 06021 type = ole_type_from_itypeinfo(pRefTypeInfo); 06022 if (type != Qnil) { 06023 rb_ary_push(types, type); 06024 } 06025 } 06026 06027 OLE_RELEASE(pRefTypeInfo); 06028 } 06029 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 06030 return types; 06031 } 06032 06033 /* 06034 * call-seq: 06035 * WIN32OLE_TYPE#implemented_ole_types 06036 * 06037 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06038 * object. 06039 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 06040 * p tobj.implemented_ole_types # => [_Worksheet, DocEvents] 06041 */ 06042 static VALUE 06043 foletype_impl_ole_types(VALUE self) 06044 { 06045 struct oletypedata *ptype; 06046 Data_Get_Struct(self, struct oletypedata, ptype); 06047 return ole_type_impl_ole_types(ptype->pTypeInfo, 0); 06048 } 06049 06050 /* 06051 * call-seq: 06052 * WIN32OLE_TYPE#source_ole_types 06053 * 06054 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06055 * object and having IMPLTYPEFLAG_FSOURCE. 06056 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 06057 * p tobj.source_ole_types 06058 * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>] 06059 */ 06060 static VALUE 06061 foletype_source_ole_types(VALUE self) 06062 { 06063 struct oletypedata *ptype; 06064 Data_Get_Struct(self, struct oletypedata, ptype); 06065 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE); 06066 } 06067 06068 /* 06069 * call-seq: 06070 * WIN32OLE_TYPE#default_event_sources 06071 * 06072 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06073 * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. 06074 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 06075 * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>] 06076 */ 06077 static VALUE 06078 foletype_default_event_sources(VALUE self) 06079 { 06080 struct oletypedata *ptype; 06081 Data_Get_Struct(self, struct oletypedata, ptype); 06082 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT); 06083 } 06084 06085 /* 06086 * call-seq: 06087 * WIN32OLE_TYPE#default_ole_types 06088 * 06089 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 06090 * object and having IMPLTYPEFLAG_FDEFAULT. 06091 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 06092 * p tobj.default_ole_types 06093 * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>] 06094 */ 06095 static VALUE 06096 foletype_default_ole_types(VALUE self) 06097 { 06098 struct oletypedata *ptype; 06099 Data_Get_Struct(self, struct oletypedata, ptype); 06100 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT); 06101 } 06102 06103 /* 06104 * call-seq: 06105 * WIN32OLE_TYPE#inspect -> String 06106 * 06107 * Returns the type name with class name. 06108 * 06109 * ie = WIN32OLE.new('InternetExplorer.Application') 06110 * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2> 06111 */ 06112 static VALUE 06113 foletype_inspect(VALUE self) 06114 { 06115 return default_inspect(self, "WIN32OLE_TYPE"); 06116 } 06117 06118 static VALUE 06119 ole_variables(ITypeInfo *pTypeInfo) 06120 { 06121 HRESULT hr; 06122 TYPEATTR *pTypeAttr; 06123 WORD i; 06124 UINT len; 06125 BSTR bstr; 06126 VARDESC *pVarDesc; 06127 struct olevariabledata *pvar; 06128 VALUE var; 06129 VALUE variables = rb_ary_new(); 06130 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 06131 if (FAILED(hr)) { 06132 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); 06133 } 06134 06135 for(i = 0; i < pTypeAttr->cVars; i++) { 06136 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc); 06137 if(FAILED(hr)) 06138 continue; 06139 len = 0; 06140 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 06141 1, &len); 06142 if(FAILED(hr) || len == 0 || !bstr) 06143 continue; 06144 06145 var = Data_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata, 06146 0,olevariable_free,pvar); 06147 pvar->pTypeInfo = pTypeInfo; 06148 OLE_ADDREF(pTypeInfo); 06149 pvar->index = i; 06150 rb_ivar_set(var, rb_intern("name"), WC2VSTR(bstr)); 06151 rb_ary_push(variables, var); 06152 06153 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06154 pVarDesc = NULL; 06155 } 06156 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 06157 return variables; 06158 } 06159 06160 /* 06161 * call-seq: 06162 * WIN32OLE_TYPE#variables 06163 * 06164 * Returns array of WIN32OLE_VARIABLE objects which represent variables 06165 * defined in OLE class. 06166 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06167 * vars = tobj.variables 06168 * vars.each do |v| 06169 * puts "#{v.name} = #{v.value}" 06170 * end 06171 * 06172 * The result of above sample script is follows: 06173 * xlChart = -4109 06174 * xlDialogSheet = -4116 06175 * xlExcel4IntlMacroSheet = 4 06176 * xlExcel4MacroSheet = 3 06177 * xlWorksheet = -4167 06178 * 06179 */ 06180 static VALUE 06181 foletype_variables(VALUE self) 06182 { 06183 struct oletypedata *ptype; 06184 Data_Get_Struct(self, struct oletypedata, ptype); 06185 return ole_variables(ptype->pTypeInfo); 06186 } 06187 06188 /* 06189 * call-seq: 06190 * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects. 06191 * 06192 * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in 06193 * OLE type library. 06194 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') 06195 * methods = tobj.ole_methods.collect{|m| 06196 * m.name 06197 * } 06198 * # => ['Activate', 'Copy', 'Delete',....] 06199 */ 06200 static VALUE 06201 foletype_methods(VALUE self) 06202 { 06203 struct oletypedata *ptype; 06204 Data_Get_Struct(self, struct oletypedata, ptype); 06205 return ole_methods_from_typeinfo(ptype->pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); 06206 } 06207 06208 /* 06209 * Document-class: WIN32OLE_VARIABLE 06210 * 06211 * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information. 06212 */ 06213 06214 /* 06215 * call-seq: 06216 * WIN32OLE_VARIABLE#name 06217 * 06218 * Returns the name of variable. 06219 * 06220 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06221 * variables = tobj.variables 06222 * variables.each do |variable| 06223 * puts "#{variable.name}" 06224 * end 06225 * 06226 * The result of above script is following: 06227 * xlChart 06228 * xlDialogSheet 06229 * xlExcel4IntlMacroSheet 06230 * xlExcel4MacroSheet 06231 * xlWorksheet 06232 * 06233 */ 06234 static VALUE 06235 folevariable_name(VALUE self) 06236 { 06237 return rb_ivar_get(self, rb_intern("name")); 06238 } 06239 06240 static VALUE 06241 ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index) 06242 { 06243 VARDESC *pVarDesc; 06244 HRESULT hr; 06245 VALUE type; 06246 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06247 if (FAILED(hr)) 06248 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); 06249 type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil); 06250 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06251 return type; 06252 } 06253 06254 /* 06255 * call-seq: 06256 * WIN32OLE_VARIABLE#ole_type 06257 * 06258 * Returns OLE type string. 06259 * 06260 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06261 * variables = tobj.variables 06262 * variables.each do |variable| 06263 * puts "#{variable.ole_type} #{variable.name}" 06264 * end 06265 * 06266 * The result of above script is following: 06267 * INT xlChart 06268 * INT xlDialogSheet 06269 * INT xlExcel4IntlMacroSheet 06270 * INT xlExcel4MacroSheet 06271 * INT xlWorksheet 06272 * 06273 */ 06274 static VALUE 06275 folevariable_ole_type(VALUE self) 06276 { 06277 struct olevariabledata *pvar; 06278 Data_Get_Struct(self, struct olevariabledata, pvar); 06279 return ole_variable_ole_type(pvar->pTypeInfo, pvar->index); 06280 } 06281 06282 static VALUE 06283 ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index) 06284 { 06285 VARDESC *pVarDesc; 06286 HRESULT hr; 06287 VALUE type = rb_ary_new(); 06288 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06289 if (FAILED(hr)) 06290 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); 06291 ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type); 06292 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06293 return type; 06294 } 06295 06296 /* 06297 * call-seq: 06298 * WIN32OLE_VARIABLE#ole_type_detail 06299 * 06300 * Returns detail information of type. The information is array of type. 06301 * 06302 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS') 06303 * variable = tobj.variables.find {|variable| variable.name == 'lFlags'} 06304 * tdetail = variable.ole_type_detail 06305 * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"] 06306 * 06307 */ 06308 static VALUE 06309 folevariable_ole_type_detail(VALUE self) 06310 { 06311 struct olevariabledata *pvar; 06312 Data_Get_Struct(self, struct olevariabledata, pvar); 06313 return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index); 06314 } 06315 06316 static VALUE 06317 ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index) 06318 { 06319 VARDESC *pVarDesc; 06320 HRESULT hr; 06321 VALUE val = Qnil; 06322 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06323 if (FAILED(hr)) 06324 return Qnil; 06325 if(pVarDesc->varkind == VAR_CONST) 06326 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); 06327 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06328 return val; 06329 } 06330 06331 /* 06332 * call-seq: 06333 * WIN32OLE_VARIABLE#value 06334 * 06335 * Returns value if value is exists. If the value does not exist, 06336 * this method returns nil. 06337 * 06338 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06339 * variables = tobj.variables 06340 * variables.each do |variable| 06341 * puts "#{variable.name} #{variable.value}" 06342 * end 06343 * 06344 * The result of above script is following: 06345 * xlChart = -4109 06346 * xlDialogSheet = -4116 06347 * xlExcel4IntlMacroSheet = 4 06348 * xlExcel4MacroSheet = 3 06349 * xlWorksheet = -4167 06350 * 06351 */ 06352 static VALUE 06353 folevariable_value(VALUE self) 06354 { 06355 struct olevariabledata *pvar; 06356 Data_Get_Struct(self, struct olevariabledata, pvar); 06357 return ole_variable_value(pvar->pTypeInfo, pvar->index); 06358 } 06359 06360 static VALUE 06361 ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index) 06362 { 06363 VARDESC *pVarDesc; 06364 HRESULT hr; 06365 VALUE visible = Qfalse; 06366 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06367 if (FAILED(hr)) 06368 return visible; 06369 if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | 06370 VARFLAG_FRESTRICTED | 06371 VARFLAG_FNONBROWSABLE))) { 06372 visible = Qtrue; 06373 } 06374 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06375 return visible; 06376 } 06377 06378 /* 06379 * call-seq: 06380 * WIN32OLE_VARIABLE#visible? 06381 * 06382 * Returns true if the variable is public. 06383 * 06384 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06385 * variables = tobj.variables 06386 * variables.each do |variable| 06387 * puts "#{variable.name} #{variable.visible?}" 06388 * end 06389 * 06390 * The result of above script is following: 06391 * xlChart true 06392 * xlDialogSheet true 06393 * xlExcel4IntlMacroSheet true 06394 * xlExcel4MacroSheet true 06395 * xlWorksheet true 06396 * 06397 */ 06398 static VALUE 06399 folevariable_visible(VALUE self) 06400 { 06401 struct olevariabledata *pvar; 06402 Data_Get_Struct(self, struct olevariabledata, pvar); 06403 return ole_variable_visible(pvar->pTypeInfo, pvar->index); 06404 } 06405 06406 static VALUE 06407 ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index) 06408 { 06409 VARDESC *pVarDesc; 06410 HRESULT hr; 06411 VALUE kind = rb_str_new2("UNKNOWN"); 06412 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06413 if (FAILED(hr)) 06414 return kind; 06415 switch(pVarDesc->varkind) { 06416 case VAR_PERINSTANCE: 06417 kind = rb_str_new2("PERINSTANCE"); 06418 break; 06419 case VAR_STATIC: 06420 kind = rb_str_new2("STATIC"); 06421 break; 06422 case VAR_CONST: 06423 kind = rb_str_new2("CONSTANT"); 06424 break; 06425 case VAR_DISPATCH: 06426 kind = rb_str_new2("DISPATCH"); 06427 break; 06428 default: 06429 break; 06430 } 06431 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06432 return kind; 06433 } 06434 06435 /* 06436 * call-seq: 06437 * WIN32OLE_VARIABLE#variable_kind 06438 * 06439 * Returns variable kind string. 06440 * 06441 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06442 * variables = tobj.variables 06443 * variables.each do |variable| 06444 * puts "#{variable.name} #{variable.variable_kind}" 06445 * end 06446 * 06447 * The result of above script is following: 06448 * xlChart CONSTANT 06449 * xlDialogSheet CONSTANT 06450 * xlExcel4IntlMacroSheet CONSTANT 06451 * xlExcel4MacroSheet CONSTANT 06452 * xlWorksheet CONSTANT 06453 */ 06454 static VALUE 06455 folevariable_variable_kind(VALUE self) 06456 { 06457 struct olevariabledata *pvar; 06458 Data_Get_Struct(self, struct olevariabledata, pvar); 06459 return ole_variable_kind(pvar->pTypeInfo, pvar->index); 06460 } 06461 06462 static VALUE 06463 ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index) 06464 { 06465 VARDESC *pVarDesc; 06466 HRESULT hr; 06467 VALUE kind = Qnil; 06468 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); 06469 if (FAILED(hr)) 06470 return kind; 06471 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); 06472 kind = INT2FIX(pVarDesc->varkind); 06473 return kind; 06474 } 06475 06476 /* 06477 * call-seq: 06478 * WIN32OLE_VARIABLE#varkind 06479 * 06480 * Returns the number which represents variable kind. 06481 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') 06482 * variables = tobj.variables 06483 * variables.each do |variable| 06484 * puts "#{variable.name} #{variable.varkind}" 06485 * end 06486 * 06487 * The result of above script is following: 06488 * xlChart 2 06489 * xlDialogSheet 2 06490 * xlExcel4IntlMacroSheet 2 06491 * xlExcel4MacroSheet 2 06492 * xlWorksheet 2 06493 */ 06494 static VALUE 06495 folevariable_varkind(VALUE self) 06496 { 06497 struct olevariabledata *pvar; 06498 Data_Get_Struct(self, struct olevariabledata, pvar); 06499 return ole_variable_varkind(pvar->pTypeInfo, pvar->index); 06500 } 06501 06502 /* 06503 * call-seq: 06504 * WIN32OLE_VARIABLE#inspect -> String 06505 * 06506 * Returns the OLE variable name and the value with class name. 06507 * 06508 */ 06509 static VALUE 06510 folevariable_inspect(VALUE self) 06511 { 06512 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0); 06513 rb_str_cat2(detail, "="); 06514 rb_str_concat(detail, rb_funcall(rb_funcall(self, rb_intern("value"), 0), rb_intern("inspect"), 0)); 06515 return make_inspect("WIN32OLE_VARIABLE", detail); 06516 } 06517 06518 /* 06519 * Document-class: WIN32OLE_METHOD 06520 * 06521 * <code>WIN32OLE_METHOD</code> objects represent OLE method information. 06522 */ 06523 06524 static VALUE 06525 olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name) 06526 { 06527 struct olemethoddata *pmethod; 06528 Data_Get_Struct(self, struct olemethoddata, pmethod); 06529 pmethod->pTypeInfo = pTypeInfo; 06530 OLE_ADDREF(pTypeInfo); 06531 pmethod->pOwnerTypeInfo = pOwnerTypeInfo; 06532 if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo); 06533 pmethod->index = index; 06534 rb_ivar_set(self, rb_intern("name"), name); 06535 return self; 06536 } 06537 06538 static VALUE 06539 folemethod_s_allocate(VALUE klass) 06540 { 06541 struct olemethoddata *pmethod; 06542 VALUE obj; 06543 obj = Data_Make_Struct(klass, 06544 struct olemethoddata, 06545 0, olemethod_free, pmethod); 06546 pmethod->pTypeInfo = NULL; 06547 pmethod->pOwnerTypeInfo = NULL; 06548 pmethod->index = 0; 06549 return obj; 06550 } 06551 06552 /* 06553 * call-seq: 06554 * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object 06555 * 06556 * Returns a new WIN32OLE_METHOD object which represents the information 06557 * about OLE method. 06558 * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object. 06559 * The second argument <i>method</i> specifies OLE method name defined OLE class 06560 * which represents WIN32OLE_TYPE object. 06561 * 06562 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06563 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 06564 */ 06565 static VALUE 06566 folemethod_initialize(VALUE self, VALUE oletype, VALUE method) 06567 { 06568 struct oletypedata *ptype; 06569 VALUE obj = Qnil; 06570 if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) { 06571 SafeStringValue(method); 06572 Data_Get_Struct(oletype, struct oletypedata, ptype); 06573 obj = olemethod_from_typeinfo(self, ptype->pTypeInfo, method); 06574 if (obj == Qnil) { 06575 rb_raise(eWIN32OLERuntimeError, "not found %s", 06576 StringValuePtr(method)); 06577 } 06578 } 06579 else { 06580 rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); 06581 } 06582 return obj; 06583 } 06584 06585 /* 06586 * call-seq 06587 * WIN32OLE_METHOD#name 06588 * 06589 * Returns the name of the method. 06590 * 06591 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06592 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 06593 * puts method.name # => SaveAs 06594 * 06595 */ 06596 static VALUE 06597 folemethod_name(VALUE self) 06598 { 06599 return rb_ivar_get(self, rb_intern("name")); 06600 } 06601 06602 static VALUE 06603 ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) 06604 { 06605 FUNCDESC *pFuncDesc; 06606 HRESULT hr; 06607 VALUE type; 06608 06609 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06610 if (FAILED(hr)) 06611 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 06612 06613 type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil); 06614 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06615 return type; 06616 } 06617 06618 /* 06619 * call-seq: 06620 * WIN32OLE_METHOD#return_type 06621 * 06622 * Returns string of return value type of method. 06623 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06624 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06625 * puts method.return_type # => Workbook 06626 * 06627 */ 06628 static VALUE 06629 folemethod_return_type(VALUE self) 06630 { 06631 struct olemethoddata *pmethod; 06632 Data_Get_Struct(self, struct olemethoddata, pmethod); 06633 return ole_method_return_type(pmethod->pTypeInfo, pmethod->index); 06634 } 06635 06636 static VALUE 06637 ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) 06638 { 06639 FUNCDESC *pFuncDesc; 06640 HRESULT hr; 06641 VALUE vvt; 06642 06643 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06644 if (FAILED(hr)) 06645 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 06646 06647 vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt); 06648 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06649 return vvt; 06650 } 06651 06652 /* 06653 * call-seq: 06654 * WIN32OLE_METHOD#return_vtype 06655 * 06656 * Returns number of return value type of method. 06657 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06658 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06659 * puts method.return_vtype # => 26 06660 * 06661 */ 06662 static VALUE 06663 folemethod_return_vtype(VALUE self) 06664 { 06665 struct olemethoddata *pmethod; 06666 Data_Get_Struct(self, struct olemethoddata, pmethod); 06667 return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index); 06668 } 06669 06670 static VALUE 06671 ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) 06672 { 06673 FUNCDESC *pFuncDesc; 06674 HRESULT hr; 06675 VALUE type = rb_ary_new(); 06676 06677 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06678 if (FAILED(hr)) 06679 return type; 06680 06681 ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type); 06682 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06683 return type; 06684 } 06685 06686 /* 06687 * call-seq: 06688 * WIN32OLE_METHOD#return_type_detail 06689 * 06690 * Returns detail information of return value type of method. 06691 * The information is array. 06692 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06693 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06694 * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] 06695 */ 06696 static VALUE 06697 folemethod_return_type_detail(VALUE self) 06698 { 06699 struct olemethoddata *pmethod; 06700 Data_Get_Struct(self, struct olemethoddata, pmethod); 06701 return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index); 06702 } 06703 06704 static VALUE 06705 ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index) 06706 { 06707 FUNCDESC *pFuncDesc; 06708 HRESULT hr; 06709 VALUE invkind; 06710 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06711 if(FAILED(hr)) 06712 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); 06713 invkind = INT2FIX(pFuncDesc->invkind); 06714 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06715 return invkind; 06716 } 06717 06718 static VALUE 06719 ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) 06720 { 06721 VALUE type = rb_str_new2("UNKNOWN"); 06722 VALUE invkind = ole_method_invkind(pTypeInfo, method_index); 06723 if((FIX2INT(invkind) & INVOKE_PROPERTYGET) && 06724 (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) { 06725 type = rb_str_new2("PROPERTY"); 06726 } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) { 06727 type = rb_str_new2("PROPERTYGET"); 06728 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) { 06729 type = rb_str_new2("PROPERTYPUT"); 06730 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) { 06731 type = rb_str_new2("PROPERTYPUTREF"); 06732 } else if(FIX2INT(invkind) & INVOKE_FUNC) { 06733 type = rb_str_new2("FUNC"); 06734 } 06735 return type; 06736 } 06737 06738 /* 06739 * call-seq: 06740 * WIN32OLE_MTHOD#invkind 06741 * 06742 * Returns the method invoke kind. 06743 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06744 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06745 * puts method.invkind # => 1 06746 * 06747 */ 06748 static VALUE 06749 folemethod_invkind(VALUE self) 06750 { 06751 struct olemethoddata *pmethod; 06752 Data_Get_Struct(self, struct olemethoddata, pmethod); 06753 return ole_method_invkind(pmethod->pTypeInfo, pmethod->index); 06754 } 06755 06756 /* 06757 * call-seq: 06758 * WIN32OLE_METHOD#invoke_kind 06759 * 06760 * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" 06761 * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" 06762 * or "FUNC". 06763 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06764 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06765 * puts method.invoke_kind # => "FUNC" 06766 */ 06767 static VALUE 06768 folemethod_invoke_kind(VALUE self) 06769 { 06770 struct olemethoddata *pmethod; 06771 Data_Get_Struct(self, struct olemethoddata, pmethod); 06772 return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index); 06773 } 06774 06775 static VALUE 06776 ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) 06777 { 06778 FUNCDESC *pFuncDesc; 06779 HRESULT hr; 06780 VALUE visible; 06781 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06782 if(FAILED(hr)) 06783 return Qfalse; 06784 if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED | 06785 FUNCFLAG_FHIDDEN | 06786 FUNCFLAG_FNONBROWSABLE)) { 06787 visible = Qfalse; 06788 } else { 06789 visible = Qtrue; 06790 } 06791 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06792 return visible; 06793 } 06794 06795 /* 06796 * call-seq: 06797 * WIN32OLE_METHOD#visible? 06798 * 06799 * Returns true if the method is public. 06800 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06801 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06802 * puts method.visible? # => true 06803 */ 06804 static VALUE 06805 folemethod_visible(VALUE self) 06806 { 06807 struct olemethoddata *pmethod; 06808 Data_Get_Struct(self, struct olemethoddata, pmethod); 06809 return ole_method_visible(pmethod->pTypeInfo, pmethod->index); 06810 } 06811 06812 static VALUE 06813 ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) 06814 { 06815 TYPEATTR *pTypeAttr; 06816 HRESULT hr; 06817 WORD i; 06818 int flags; 06819 HREFTYPE href; 06820 ITypeInfo *pRefTypeInfo; 06821 FUNCDESC *pFuncDesc; 06822 BSTR bstr; 06823 VALUE name; 06824 VALUE event = Qfalse; 06825 06826 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 06827 if (FAILED(hr)) 06828 return event; 06829 if(pTypeAttr->typekind != TKIND_COCLASS) { 06830 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); 06831 return event; 06832 } 06833 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 06834 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 06835 if (FAILED(hr)) 06836 continue; 06837 06838 if (flags & IMPLTYPEFLAG_FSOURCE) { 06839 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 06840 i, &href); 06841 if (FAILED(hr)) 06842 continue; 06843 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 06844 href, &pRefTypeInfo); 06845 if (FAILED(hr)) 06846 continue; 06847 hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index, 06848 &pFuncDesc); 06849 if (FAILED(hr)) { 06850 OLE_RELEASE(pRefTypeInfo); 06851 continue; 06852 } 06853 06854 hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo, 06855 pFuncDesc->memid, 06856 &bstr, NULL, NULL, NULL); 06857 if (FAILED(hr)) { 06858 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); 06859 OLE_RELEASE(pRefTypeInfo); 06860 continue; 06861 } 06862 06863 name = WC2VSTR(bstr); 06864 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); 06865 OLE_RELEASE(pRefTypeInfo); 06866 if (rb_str_cmp(method_name, name) == 0) { 06867 event = Qtrue; 06868 break; 06869 } 06870 } 06871 } 06872 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 06873 return event; 06874 } 06875 06876 /* 06877 * call-seq: 06878 * WIN32OLE_METHOD#event? 06879 * 06880 * Returns true if the method is event. 06881 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06882 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') 06883 * puts method.event? # => true 06884 * 06885 */ 06886 static VALUE 06887 folemethod_event(VALUE self) 06888 { 06889 struct olemethoddata *pmethod; 06890 Data_Get_Struct(self, struct olemethoddata, pmethod); 06891 if (!pmethod->pOwnerTypeInfo) 06892 return Qfalse; 06893 return ole_method_event(pmethod->pOwnerTypeInfo, 06894 pmethod->index, 06895 rb_ivar_get(self, rb_intern("name"))); 06896 } 06897 06898 /* 06899 * call-seq: 06900 * WIN32OLE_METHOD#event_interface 06901 * 06902 * Returns event interface name if the method is event. 06903 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 06904 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') 06905 * puts method.event_interface # => WorkbookEvents 06906 */ 06907 static VALUE 06908 folemethod_event_interface(VALUE self) 06909 { 06910 BSTR name; 06911 struct olemethoddata *pmethod; 06912 HRESULT hr; 06913 Data_Get_Struct(self, struct olemethoddata, pmethod); 06914 if(folemethod_event(self) == Qtrue) { 06915 hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL); 06916 if(SUCCEEDED(hr)) 06917 return WC2VSTR(name); 06918 } 06919 return Qnil; 06920 } 06921 06922 static VALUE 06923 ole_method_docinfo_from_type( 06924 ITypeInfo *pTypeInfo, 06925 UINT method_index, 06926 BSTR *name, 06927 BSTR *helpstr, 06928 DWORD *helpcontext, 06929 BSTR *helpfile 06930 ) 06931 { 06932 FUNCDESC *pFuncDesc; 06933 HRESULT hr; 06934 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 06935 if (FAILED(hr)) 06936 return hr; 06937 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, 06938 name, helpstr, 06939 helpcontext, helpfile); 06940 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 06941 return hr; 06942 } 06943 06944 static VALUE 06945 ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) 06946 { 06947 HRESULT hr; 06948 BSTR bhelpstring; 06949 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring, 06950 NULL, NULL); 06951 if (FAILED(hr)) 06952 return Qnil; 06953 return WC2VSTR(bhelpstring); 06954 } 06955 06956 /* 06957 * call-seq: 06958 * WIN32OLE_METHOD#helpstring 06959 * 06960 * Returns help string of OLE method. If the help string is not found, 06961 * then the method returns nil. 06962 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') 06963 * method = WIN32OLE_METHOD.new(tobj, 'Navigate') 06964 * puts method.helpstring # => Navigates to a URL or file. 06965 * 06966 */ 06967 static VALUE 06968 folemethod_helpstring(VALUE self) 06969 { 06970 struct olemethoddata *pmethod; 06971 Data_Get_Struct(self, struct olemethoddata, pmethod); 06972 return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index); 06973 } 06974 06975 static VALUE 06976 ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index) 06977 { 06978 HRESULT hr; 06979 BSTR bhelpfile; 06980 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, 06981 NULL, &bhelpfile); 06982 if (FAILED(hr)) 06983 return Qnil; 06984 return WC2VSTR(bhelpfile); 06985 } 06986 06987 /* 06988 * call-seq: 06989 * WIN32OLE_METHOD#helpfile 06990 * 06991 * Returns help file. If help file is not found, then 06992 * the method returns nil. 06993 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 06994 * method = WIN32OLE_METHOD.new(tobj, 'Add') 06995 * puts method.helpfile # => C:\...\VBAXL9.CHM 06996 */ 06997 static VALUE 06998 folemethod_helpfile(VALUE self) 06999 { 07000 struct olemethoddata *pmethod; 07001 Data_Get_Struct(self, struct olemethoddata, pmethod); 07002 07003 return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index); 07004 } 07005 07006 static VALUE 07007 ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) 07008 { 07009 HRESULT hr; 07010 DWORD helpcontext = 0; 07011 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, 07012 &helpcontext, NULL); 07013 if (FAILED(hr)) 07014 return Qnil; 07015 return INT2FIX(helpcontext); 07016 } 07017 07018 /* 07019 * call-seq: 07020 * WIN32OLE_METHOD#helpcontext 07021 * 07022 * Returns help context. 07023 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 07024 * method = WIN32OLE_METHOD.new(tobj, 'Add') 07025 * puts method.helpcontext # => 65717 07026 */ 07027 static VALUE 07028 folemethod_helpcontext(VALUE self) 07029 { 07030 struct olemethoddata *pmethod; 07031 Data_Get_Struct(self, struct olemethoddata, pmethod); 07032 return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index); 07033 } 07034 07035 static VALUE 07036 ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) 07037 { 07038 FUNCDESC *pFuncDesc; 07039 HRESULT hr; 07040 VALUE dispid = Qnil; 07041 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07042 if (FAILED(hr)) 07043 return dispid; 07044 dispid = INT2NUM(pFuncDesc->memid); 07045 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07046 return dispid; 07047 } 07048 07049 /* 07050 * call-seq: 07051 * WIN32OLE_METHOD#dispid 07052 * 07053 * Returns dispatch ID. 07054 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 07055 * method = WIN32OLE_METHOD.new(tobj, 'Add') 07056 * puts method.dispid # => 181 07057 */ 07058 static VALUE 07059 folemethod_dispid(VALUE self) 07060 { 07061 struct olemethoddata *pmethod; 07062 Data_Get_Struct(self, struct olemethoddata, pmethod); 07063 return ole_method_dispid(pmethod->pTypeInfo, pmethod->index); 07064 } 07065 07066 static VALUE 07067 ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) 07068 { 07069 FUNCDESC *pFuncDesc; 07070 HRESULT hr; 07071 VALUE offset_vtbl = Qnil; 07072 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07073 if (FAILED(hr)) 07074 return offset_vtbl; 07075 offset_vtbl = INT2FIX(pFuncDesc->oVft); 07076 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07077 return offset_vtbl; 07078 } 07079 07080 /* 07081 * call-seq: 07082 * WIN32OLE_METHOD#offset_vtbl 07083 * 07084 * Returns the offset ov VTBL. 07085 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') 07086 * method = WIN32OLE_METHOD.new(tobj, 'Add') 07087 * puts method.offset_vtbl # => 40 07088 */ 07089 static VALUE 07090 folemethod_offset_vtbl(VALUE self) 07091 { 07092 struct olemethoddata *pmethod; 07093 Data_Get_Struct(self, struct olemethoddata, pmethod); 07094 return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index); 07095 } 07096 07097 static VALUE 07098 ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) 07099 { 07100 FUNCDESC *pFuncDesc; 07101 HRESULT hr; 07102 VALUE size_params = Qnil; 07103 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07104 if (FAILED(hr)) 07105 return size_params; 07106 size_params = INT2FIX(pFuncDesc->cParams); 07107 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07108 return size_params; 07109 } 07110 07111 /* 07112 * call-seq: 07113 * WIN32OLE_METHOD#size_params 07114 * 07115 * Returns the size of arguments of the method. 07116 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07117 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07118 * puts method.size_params # => 11 07119 * 07120 */ 07121 static VALUE 07122 folemethod_size_params(VALUE self) 07123 { 07124 struct olemethoddata *pmethod; 07125 Data_Get_Struct(self, struct olemethoddata, pmethod); 07126 return ole_method_size_params(pmethod->pTypeInfo, pmethod->index); 07127 } 07128 07129 static VALUE 07130 ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) 07131 { 07132 FUNCDESC *pFuncDesc; 07133 HRESULT hr; 07134 VALUE size_opt_params = Qnil; 07135 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07136 if (FAILED(hr)) 07137 return size_opt_params; 07138 size_opt_params = INT2FIX(pFuncDesc->cParamsOpt); 07139 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07140 return size_opt_params; 07141 } 07142 07143 /* 07144 * call-seq: 07145 * WIN32OLE_METHOD#size_opt_params 07146 * 07147 * Returns the size of optional parameters. 07148 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07149 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07150 * puts method.size_opt_params # => 4 07151 */ 07152 static VALUE 07153 folemethod_size_opt_params(VALUE self) 07154 { 07155 struct olemethoddata *pmethod; 07156 Data_Get_Struct(self, struct olemethoddata, pmethod); 07157 return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index); 07158 } 07159 07160 static VALUE 07161 ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) 07162 { 07163 FUNCDESC *pFuncDesc; 07164 HRESULT hr; 07165 BSTR *bstrs; 07166 UINT len, i; 07167 struct oleparamdata *pparam; 07168 VALUE param; 07169 VALUE params = rb_ary_new(); 07170 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07171 if (FAILED(hr)) 07172 return params; 07173 07174 len = 0; 07175 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); 07176 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, 07177 bstrs, pFuncDesc->cParams + 1, 07178 &len); 07179 if (FAILED(hr)) { 07180 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07181 return params; 07182 } 07183 SysFreeString(bstrs[0]); 07184 if (pFuncDesc->cParams > 0) { 07185 for(i = 1; i < len; i++) { 07186 param = Data_Make_Struct(cWIN32OLE_PARAM, struct oleparamdata, 0, 07187 oleparam_free, pparam); 07188 pparam->pTypeInfo = pTypeInfo; 07189 OLE_ADDREF(pTypeInfo); 07190 pparam->method_index = method_index; 07191 pparam->index = i - 1; 07192 rb_ivar_set(param, rb_intern("name"), WC2VSTR(bstrs[i])); 07193 rb_ary_push(params, param); 07194 } 07195 } 07196 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07197 return params; 07198 } 07199 07200 07201 /* 07202 * call-seq: 07203 * WIN32OLE_METHOD#params 07204 * 07205 * returns array of WIN32OLE_PARAM object corresponding with method parameters. 07206 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07207 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07208 * p method.params # => [Filename, FileFormat, Password, WriteResPassword, 07209 * ReadOnlyRecommended, CreateBackup, AccessMode, 07210 * ConflictResolution, AddToMru, TextCodepage, 07211 * TextVisualLayout] 07212 */ 07213 static VALUE 07214 folemethod_params(VALUE self) 07215 { 07216 struct olemethoddata *pmethod; 07217 Data_Get_Struct(self, struct olemethoddata, pmethod); 07218 return ole_method_params(pmethod->pTypeInfo, pmethod->index); 07219 } 07220 07221 /* 07222 * call-seq: 07223 * WIN32OLE_METHOD#inspect -> String 07224 * 07225 * Returns the method name with class name. 07226 * 07227 */ 07228 static VALUE 07229 folemethod_inspect(VALUE self) 07230 { 07231 return default_inspect(self, "WIN32OLE_METHOD"); 07232 } 07233 07234 /* 07235 * Document-class: WIN32OLE_PARAM 07236 * 07237 * <code>WIN32OLE_PARAM</code> objects represent param information of 07238 * the OLE method. 07239 */ 07240 static VALUE foleparam_s_allocate(VALUE klass) 07241 { 07242 struct oleparamdata *pparam; 07243 VALUE obj; 07244 obj = Data_Make_Struct(klass, 07245 struct oleparamdata, 07246 0, oleparam_free, pparam); 07247 pparam->pTypeInfo = NULL; 07248 pparam->method_index = 0; 07249 pparam->index = 0; 07250 return obj; 07251 } 07252 07253 static VALUE 07254 oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index) 07255 { 07256 FUNCDESC *pFuncDesc; 07257 HRESULT hr; 07258 BSTR *bstrs; 07259 UINT len; 07260 struct oleparamdata *pparam; 07261 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07262 if (FAILED(hr)) 07263 ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc"); 07264 07265 len = 0; 07266 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); 07267 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, 07268 bstrs, pFuncDesc->cParams + 1, 07269 &len); 07270 if (FAILED(hr)) { 07271 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07272 ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames"); 07273 } 07274 SysFreeString(bstrs[0]); 07275 if (param_index < 1 || len <= (UINT)param_index) 07276 { 07277 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07278 rb_raise(rb_eIndexError, "index of param must be in 1..%d", len); 07279 } 07280 07281 Data_Get_Struct(self, struct oleparamdata, pparam); 07282 pparam->pTypeInfo = pTypeInfo; 07283 OLE_ADDREF(pTypeInfo); 07284 pparam->method_index = method_index; 07285 pparam->index = param_index - 1; 07286 rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index])); 07287 07288 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07289 return self; 07290 } 07291 07292 static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n) 07293 { 07294 struct olemethoddata *pmethod; 07295 Data_Get_Struct(olemethod, struct olemethoddata, pmethod); 07296 return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n); 07297 } 07298 07299 static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n) 07300 { 07301 int idx; 07302 if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) { 07303 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object"); 07304 } 07305 idx = FIX2INT(n); 07306 return oleparam_ole_param(self, olemethod, idx); 07307 } 07308 07309 /* 07310 * call-seq: 07311 * WIN32OLE_PARAM#name 07312 * 07313 * Returns name. 07314 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07315 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07316 * param1 = method.params[0] 07317 * puts param1.name # => Filename 07318 */ 07319 static VALUE 07320 foleparam_name(VALUE self) 07321 { 07322 return rb_ivar_get(self, rb_intern("name")); 07323 } 07324 07325 static VALUE 07326 ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 07327 { 07328 FUNCDESC *pFuncDesc; 07329 HRESULT hr; 07330 VALUE type = rb_str_new2("unknown type"); 07331 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07332 if (FAILED(hr)) 07333 return type; 07334 type = ole_typedesc2val(pTypeInfo, 07335 &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil); 07336 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07337 return type; 07338 } 07339 07340 /* 07341 * call-seq: 07342 * WIN32OLE_PARAM#ole_type 07343 * 07344 * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method). 07345 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07346 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07347 * param1 = method.params[0] 07348 * puts param1.ole_type # => VARIANT 07349 */ 07350 static VALUE 07351 foleparam_ole_type(VALUE self) 07352 { 07353 struct oleparamdata *pparam; 07354 Data_Get_Struct(self, struct oleparamdata, pparam); 07355 return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index, 07356 pparam->index); 07357 } 07358 07359 static VALUE 07360 ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 07361 { 07362 FUNCDESC *pFuncDesc; 07363 HRESULT hr; 07364 VALUE typedetail = rb_ary_new(); 07365 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07366 if (FAILED(hr)) 07367 return typedetail; 07368 ole_typedesc2val(pTypeInfo, 07369 &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail); 07370 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07371 return typedetail; 07372 } 07373 07374 /* 07375 * call-seq: 07376 * WIN32OLE_PARAM#ole_type_detail 07377 * 07378 * Returns detail information of type of argument. 07379 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction') 07380 * method = WIN32OLE_METHOD.new(tobj, 'SumIf') 07381 * param1 = method.params[0] 07382 * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"] 07383 */ 07384 static VALUE 07385 foleparam_ole_type_detail(VALUE self) 07386 { 07387 struct oleparamdata *pparam; 07388 Data_Get_Struct(self, struct oleparamdata, pparam); 07389 return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index, 07390 pparam->index); 07391 } 07392 07393 static VALUE 07394 ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask) 07395 { 07396 FUNCDESC *pFuncDesc; 07397 HRESULT hr; 07398 VALUE ret = Qfalse; 07399 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07400 if(FAILED(hr)) 07401 return ret; 07402 if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask) 07403 ret = Qtrue; 07404 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07405 return ret; 07406 } 07407 07408 /* 07409 * call-seq: 07410 * WIN32OLE_PARAM#input? 07411 * 07412 * Returns true if the parameter is input. 07413 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07414 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07415 * param1 = method.params[0] 07416 * puts param1.input? # => true 07417 */ 07418 static VALUE foleparam_input(VALUE self) 07419 { 07420 struct oleparamdata *pparam; 07421 Data_Get_Struct(self, struct oleparamdata, pparam); 07422 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07423 pparam->index, PARAMFLAG_FIN); 07424 } 07425 07426 /* 07427 * call-seq: 07428 * WIN32OLE#output? 07429 * 07430 * Returns true if argument is output. 07431 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents') 07432 * method = WIN32OLE_METHOD.new(tobj, 'NewWindow') 07433 * method.params.each do |param| 07434 * puts "#{param.name} #{param.output?}" 07435 * end 07436 * 07437 * The result of above script is following: 07438 * URL false 07439 * Flags false 07440 * TargetFrameName false 07441 * PostData false 07442 * Headers false 07443 * Processed true 07444 */ 07445 static VALUE foleparam_output(VALUE self) 07446 { 07447 struct oleparamdata *pparam; 07448 Data_Get_Struct(self, struct oleparamdata, pparam); 07449 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07450 pparam->index, PARAMFLAG_FOUT); 07451 } 07452 07453 /* 07454 * call-seq: 07455 * WIN32OLE_PARAM#optional? 07456 * 07457 * Returns true if argument is optional. 07458 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07459 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07460 * param1 = method.params[0] 07461 * puts "#{param1.name} #{param1.optional?}" # => Filename true 07462 */ 07463 static VALUE foleparam_optional(VALUE self) 07464 { 07465 struct oleparamdata *pparam; 07466 Data_Get_Struct(self, struct oleparamdata, pparam); 07467 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07468 pparam->index, PARAMFLAG_FOPT); 07469 } 07470 07471 /* 07472 * call-seq: 07473 * WIN32OLE_PARAM#retval? 07474 * 07475 * Returns true if argument is return value. 07476 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 07477 * 'DirectPlayLobbyConnection') 07478 * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName') 07479 * param = method.params[0] 07480 * puts "#{param.name} #{param.retval?}" # => name true 07481 */ 07482 static VALUE foleparam_retval(VALUE self) 07483 { 07484 struct oleparamdata *pparam; 07485 Data_Get_Struct(self, struct oleparamdata, pparam); 07486 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, 07487 pparam->index, PARAMFLAG_FRETVAL); 07488 } 07489 07490 static VALUE 07491 ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index) 07492 { 07493 FUNCDESC *pFuncDesc; 07494 ELEMDESC *pElemDesc; 07495 PARAMDESCEX * pParamDescEx; 07496 HRESULT hr; 07497 USHORT wParamFlags; 07498 USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT; 07499 VALUE defval = Qnil; 07500 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); 07501 if (FAILED(hr)) 07502 return defval; 07503 pElemDesc = &pFuncDesc->lprgelemdescParam[index]; 07504 wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags; 07505 if ((wParamFlags & mask) == mask) { 07506 pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex; 07507 defval = ole_variant2val(&pParamDescEx->varDefaultValue); 07508 } 07509 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); 07510 return defval; 07511 } 07512 07513 /* 07514 * call-seq: 07515 * WIN32OLE_PARAM#default 07516 * 07517 * Returns default value. If the default value does not exist, 07518 * this method returns nil. 07519 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') 07520 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') 07521 * method.params.each do |param| 07522 * if param.default 07523 * puts "#{param.name} (= #{param.default})" 07524 * else 07525 * puts "#{param}" 07526 * end 07527 * end 07528 * 07529 * The above script result is following: 07530 * Filename 07531 * FileFormat 07532 * Password 07533 * WriteResPassword 07534 * ReadOnlyRecommended 07535 * CreateBackup 07536 * AccessMode (= 1) 07537 * ConflictResolution 07538 * AddToMru 07539 * TextCodepage 07540 * TextVisualLayout 07541 */ 07542 static VALUE foleparam_default(VALUE self) 07543 { 07544 struct oleparamdata *pparam; 07545 Data_Get_Struct(self, struct oleparamdata, pparam); 07546 return ole_param_default(pparam->pTypeInfo, pparam->method_index, 07547 pparam->index); 07548 } 07549 07550 /* 07551 * call-seq: 07552 * WIN32OLE_PARAM#inspect -> String 07553 * 07554 * Returns the parameter name with class name. If the parameter has default value, 07555 * then returns name=value string with class name. 07556 * 07557 */ 07558 static VALUE 07559 foleparam_inspect(VALUE self) 07560 { 07561 VALUE detail = foleparam_name(self); 07562 VALUE defval = foleparam_default(self); 07563 if (defval != Qnil) { 07564 rb_str_cat2(detail, "="); 07565 rb_str_concat(detail, rb_funcall(defval, rb_intern("inspect"), 0)); 07566 } 07567 return make_inspect("WIN32OLE_PARAM", detail); 07568 } 07569 07570 /* 07571 * Document-class: WIN32OLE_EVENT 07572 * 07573 * <code>WIN32OLE_EVENT</code> objects controls OLE event. 07574 */ 07575 07576 static IEventSinkVtbl vtEventSink; 07577 static BOOL g_IsEventSinkVtblInitialized = FALSE; 07578 07579 void EVENTSINK_Destructor(PIEVENTSINKOBJ); 07580 07581 STDMETHODIMP 07582 EVENTSINK_QueryInterface( 07583 PEVENTSINK pEV, 07584 REFIID iid, 07585 LPVOID* ppv 07586 ) { 07587 if (IsEqualIID(iid, &IID_IUnknown) || 07588 IsEqualIID(iid, &IID_IDispatch) || 07589 IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) { 07590 *ppv = pEV; 07591 } 07592 else { 07593 *ppv = NULL; 07594 return E_NOINTERFACE; 07595 } 07596 ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv); 07597 return NOERROR; 07598 } 07599 07600 STDMETHODIMP_(ULONG) 07601 EVENTSINK_AddRef( 07602 PEVENTSINK pEV 07603 ){ 07604 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; 07605 return ++pEVObj->m_cRef; 07606 } 07607 07608 STDMETHODIMP_(ULONG) EVENTSINK_Release( 07609 PEVENTSINK pEV 07610 ) { 07611 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; 07612 --pEVObj->m_cRef; 07613 if(pEVObj->m_cRef != 0) 07614 return pEVObj->m_cRef; 07615 EVENTSINK_Destructor(pEVObj); 07616 return 0; 07617 } 07618 07619 STDMETHODIMP EVENTSINK_GetTypeInfoCount( 07620 PEVENTSINK pEV, 07621 UINT *pct 07622 ) { 07623 *pct = 0; 07624 return NOERROR; 07625 } 07626 07627 STDMETHODIMP EVENTSINK_GetTypeInfo( 07628 PEVENTSINK pEV, 07629 UINT info, 07630 LCID lcid, 07631 ITypeInfo **pInfo 07632 ) { 07633 *pInfo = NULL; 07634 return DISP_E_BADINDEX; 07635 } 07636 07637 STDMETHODIMP EVENTSINK_GetIDsOfNames( 07638 PEVENTSINK pEventSink, 07639 REFIID riid, 07640 OLECHAR **szNames, 07641 UINT cNames, 07642 LCID lcid, 07643 DISPID *pDispID 07644 ) { 07645 ITypeInfo *pTypeInfo; 07646 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; 07647 pTypeInfo = pEV->pTypeInfo; 07648 if (pTypeInfo) { 07649 return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID); 07650 } 07651 return DISP_E_UNKNOWNNAME; 07652 } 07653 07654 static long 07655 ole_search_event_at(VALUE ary, VALUE ev) 07656 { 07657 VALUE event; 07658 VALUE event_name; 07659 long i, len; 07660 long ret = -1; 07661 len = RARRAY_LEN(ary); 07662 for(i = 0; i < len; i++) { 07663 event = rb_ary_entry(ary, i); 07664 event_name = rb_ary_entry(event, 1); 07665 if(NIL_P(event_name) && NIL_P(ev)) { 07666 ret = i; 07667 break; 07668 } 07669 else if (TYPE(ev) == T_STRING && 07670 TYPE(event_name) == T_STRING && 07671 rb_str_cmp(ev, event_name) == 0) { 07672 ret = i; 07673 break; 07674 } 07675 } 07676 return ret; 07677 } 07678 07679 static VALUE 07680 ole_search_event(VALUE ary, VALUE ev, BOOL *is_default) 07681 { 07682 VALUE event; 07683 VALUE def_event; 07684 VALUE event_name; 07685 int i, len; 07686 *is_default = FALSE; 07687 def_event = Qnil; 07688 len = RARRAY_LEN(ary); 07689 for(i = 0; i < len; i++) { 07690 event = rb_ary_entry(ary, i); 07691 event_name = rb_ary_entry(event, 1); 07692 if(NIL_P(event_name)) { 07693 *is_default = TRUE; 07694 def_event = event; 07695 } 07696 else if (rb_str_cmp(ev, event_name) == 0) { 07697 *is_default = FALSE; 07698 return event; 07699 } 07700 } 07701 return def_event; 07702 } 07703 static VALUE 07704 ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler) 07705 { 07706 VALUE mid; 07707 07708 *is_default_handler = FALSE; 07709 mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev))); 07710 if (rb_respond_to(handler, mid)) { 07711 return mid; 07712 } 07713 mid = rb_intern("method_missing"); 07714 if (rb_respond_to(handler, mid)) { 07715 *is_default_handler = TRUE; 07716 return mid; 07717 } 07718 return Qnil; 07719 } 07720 07721 static void 07722 ole_delete_event(VALUE ary, VALUE ev) 07723 { 07724 long at = -1; 07725 at = ole_search_event_at(ary, ev); 07726 if (at >= 0) { 07727 rb_ary_delete_at(ary, at); 07728 } 07729 } 07730 07731 static void 07732 hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams) 07733 { 07734 BSTR *bstrs; 07735 HRESULT hr; 07736 UINT len, i; 07737 VARIANT *pvar; 07738 VALUE val; 07739 VALUE key; 07740 len = 0; 07741 bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1); 07742 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 07743 bstrs, pdispparams->cArgs + 1, 07744 &len); 07745 if (FAILED(hr)) 07746 return; 07747 07748 for (i = 0; i < len - 1; i++) { 07749 key = WC2VSTR(bstrs[i + 1]); 07750 val = rb_hash_aref(hash, INT2FIX(i)); 07751 if (val == Qnil) 07752 val = rb_hash_aref(hash, key); 07753 if (val == Qnil) 07754 val = rb_hash_aref(hash, rb_str_intern(key)); 07755 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 07756 ole_val2ptr_variant(val, pvar); 07757 } 07758 } 07759 07760 static VALUE 07761 hash2result(VALUE hash) 07762 { 07763 VALUE ret = Qnil; 07764 ret = rb_hash_aref(hash, rb_str_new2("return")); 07765 if (ret == Qnil) 07766 ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return"))); 07767 return ret; 07768 } 07769 07770 static void 07771 ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams) 07772 { 07773 int i; 07774 VALUE v; 07775 VARIANT *pvar; 07776 for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) { 07777 v = rb_ary_entry(ary, i); 07778 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 07779 ole_val2ptr_variant(v, pvar); 07780 } 07781 } 07782 07783 static VALUE 07784 exec_callback(VALUE arg) 07785 { 07786 VALUE *parg = (VALUE *)arg; 07787 VALUE handler = parg[0]; 07788 VALUE mid = parg[1]; 07789 VALUE args = parg[2]; 07790 return rb_apply(handler, mid, args); 07791 } 07792 07793 static VALUE 07794 rescue_callback(VALUE arg) 07795 { 07796 07797 VALUE error; 07798 VALUE e = rb_errinfo(); 07799 VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0); 07800 VALUE msg = rb_funcall(e, rb_intern("message"), 0); 07801 bt = rb_ary_entry(bt, 0); 07802 error = rb_sprintf("%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e)); 07803 rb_write_error(StringValuePtr(error)); 07804 rb_backtrace(); 07805 ruby_finalize(); 07806 exit(-1); 07807 07808 return Qnil; 07809 } 07810 07811 STDMETHODIMP EVENTSINK_Invoke( 07812 PEVENTSINK pEventSink, 07813 DISPID dispid, 07814 REFIID riid, 07815 LCID lcid, 07816 WORD wFlags, 07817 DISPPARAMS *pdispparams, 07818 VARIANT *pvarResult, 07819 EXCEPINFO *pexcepinfo, 07820 UINT *puArgErr 07821 ) { 07822 07823 HRESULT hr; 07824 BSTR bstr; 07825 unsigned int count; 07826 unsigned int i; 07827 ITypeInfo *pTypeInfo; 07828 VARIANT *pvar; 07829 VALUE ary, obj, event, args, outargv, ev, result; 07830 VALUE handler = Qnil; 07831 VALUE arg[3]; 07832 VALUE mid; 07833 VALUE is_outarg = Qfalse; 07834 BOOL is_default_handler = FALSE; 07835 int state; 07836 07837 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; 07838 pTypeInfo = pEV->pTypeInfo; 07839 obj = evs_entry(pEV->m_event_id); 07840 if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) { 07841 return NOERROR; 07842 } 07843 07844 ary = rb_ivar_get(obj, id_events); 07845 if (NIL_P(ary) || TYPE(ary) != T_ARRAY) { 07846 return NOERROR; 07847 } 07848 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 07849 &bstr, 1, &count); 07850 if (FAILED(hr)) { 07851 return NOERROR; 07852 } 07853 ev = WC2VSTR(bstr); 07854 event = ole_search_event(ary, ev, &is_default_handler); 07855 if (TYPE(event) == T_ARRAY) { 07856 handler = rb_ary_entry(event, 0); 07857 mid = rb_intern("call"); 07858 is_outarg = rb_ary_entry(event, 3); 07859 } else { 07860 handler = rb_ivar_get(obj, rb_intern("handler")); 07861 if (handler == Qnil) { 07862 return NOERROR; 07863 } 07864 mid = ole_search_handler_method(handler, ev, &is_default_handler); 07865 } 07866 if (handler == Qnil || mid == Qnil) { 07867 return NOERROR; 07868 } 07869 07870 args = rb_ary_new(); 07871 if (is_default_handler) { 07872 rb_ary_push(args, ev); 07873 } 07874 07875 /* make argument of event handler */ 07876 for (i = 0; i < pdispparams->cArgs; ++i) { 07877 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; 07878 rb_ary_push(args, ole_variant2val(pvar)); 07879 } 07880 outargv = Qnil; 07881 if (is_outarg == Qtrue) { 07882 outargv = rb_ary_new(); 07883 rb_ary_push(args, outargv); 07884 } 07885 07886 /* 07887 * if exception raised in event callback, 07888 * then you receive cfp consistency error. 07889 * to avoid this error we use begin rescue end. 07890 * and the exception raised then error message print 07891 * and exit ruby process by Win32OLE itself. 07892 */ 07893 arg[0] = handler; 07894 arg[1] = mid; 07895 arg[2] = args; 07896 result = rb_protect(exec_callback, (VALUE)arg, &state); 07897 if (state != 0) { 07898 rescue_callback(Qnil); 07899 } 07900 if(TYPE(result) == T_HASH) { 07901 hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); 07902 result = hash2result(result); 07903 }else if (is_outarg == Qtrue && TYPE(outargv) == T_ARRAY) { 07904 ary2ptr_dispparams(outargv, pdispparams); 07905 } 07906 07907 if (pvarResult) { 07908 VariantInit(pvarResult); 07909 ole_val2variant(result, pvarResult); 07910 } 07911 07912 return NOERROR; 07913 } 07914 07915 PIEVENTSINKOBJ 07916 EVENTSINK_Constructor() { 07917 PIEVENTSINKOBJ pEv; 07918 if (!g_IsEventSinkVtblInitialized) { 07919 vtEventSink.QueryInterface=EVENTSINK_QueryInterface; 07920 vtEventSink.AddRef = EVENTSINK_AddRef; 07921 vtEventSink.Release = EVENTSINK_Release; 07922 vtEventSink.Invoke = EVENTSINK_Invoke; 07923 vtEventSink.GetIDsOfNames = EVENTSINK_GetIDsOfNames; 07924 vtEventSink.GetTypeInfoCount = EVENTSINK_GetTypeInfoCount; 07925 vtEventSink.GetTypeInfo = EVENTSINK_GetTypeInfo; 07926 07927 g_IsEventSinkVtblInitialized = TRUE; 07928 } 07929 pEv = ALLOC_N(IEVENTSINKOBJ, 1); 07930 if(pEv == NULL) return NULL; 07931 pEv->lpVtbl = &vtEventSink; 07932 pEv->m_cRef = 0; 07933 pEv->m_event_id = 0; 07934 pEv->pTypeInfo = NULL; 07935 return pEv; 07936 } 07937 07938 void EVENTSINK_Destructor( 07939 PIEVENTSINKOBJ pEVObj 07940 ) { 07941 if(pEVObj != NULL) { 07942 OLE_RELEASE(pEVObj->pTypeInfo); 07943 free(pEVObj); 07944 pEVObj = NULL; 07945 } 07946 } 07947 07948 static HRESULT 07949 find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) 07950 { 07951 HRESULT hr; 07952 IDispatch *pDispatch; 07953 ITypeInfo *pTypeInfo; 07954 ITypeLib *pTypeLib; 07955 TYPEATTR *pTypeAttr; 07956 HREFTYPE RefType; 07957 ITypeInfo *pImplTypeInfo; 07958 TYPEATTR *pImplTypeAttr; 07959 07960 struct oledata *pole; 07961 unsigned int index; 07962 unsigned int count; 07963 int type; 07964 BSTR bstr; 07965 char *pstr; 07966 07967 BOOL is_found = FALSE; 07968 LCID lcid = cWIN32OLE_lcid; 07969 07970 OLEData_Get_Struct(ole, pole); 07971 07972 pDispatch = pole->pDispatch; 07973 07974 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo); 07975 if (FAILED(hr)) 07976 return hr; 07977 07978 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, 07979 &pTypeLib, 07980 &index); 07981 OLE_RELEASE(pTypeInfo); 07982 if (FAILED(hr)) 07983 return hr; 07984 07985 if (!pitf) { 07986 hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, 07987 piid, 07988 ppTypeInfo); 07989 OLE_RELEASE(pTypeLib); 07990 return hr; 07991 } 07992 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 07993 for (index = 0; index < count; index++) { 07994 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, 07995 index, 07996 &pTypeInfo); 07997 if (FAILED(hr)) 07998 break; 07999 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 08000 08001 if(FAILED(hr)) { 08002 OLE_RELEASE(pTypeInfo); 08003 break; 08004 } 08005 if(pTypeAttr->typekind == TKIND_COCLASS) { 08006 for (type = 0; type < pTypeAttr->cImplTypes; type++) { 08007 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 08008 type, 08009 &RefType); 08010 if (FAILED(hr)) 08011 break; 08012 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 08013 RefType, 08014 &pImplTypeInfo); 08015 if (FAILED(hr)) 08016 break; 08017 08018 hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo, 08019 -1, 08020 &bstr, 08021 NULL, NULL, NULL); 08022 if (FAILED(hr)) { 08023 OLE_RELEASE(pImplTypeInfo); 08024 break; 08025 } 08026 pstr = ole_wc2mb(bstr); 08027 if (strcmp(pitf, pstr) == 0) { 08028 hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo, 08029 &pImplTypeAttr); 08030 if (SUCCEEDED(hr)) { 08031 is_found = TRUE; 08032 *piid = pImplTypeAttr->guid; 08033 if (ppTypeInfo) { 08034 *ppTypeInfo = pImplTypeInfo; 08035 (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo)); 08036 } 08037 pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo, 08038 pImplTypeAttr); 08039 } 08040 } 08041 free(pstr); 08042 OLE_RELEASE(pImplTypeInfo); 08043 if (is_found || FAILED(hr)) 08044 break; 08045 } 08046 } 08047 08048 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 08049 OLE_RELEASE(pTypeInfo); 08050 if (is_found || FAILED(hr)) 08051 break; 08052 } 08053 OLE_RELEASE(pTypeLib); 08054 if(!is_found) 08055 return E_NOINTERFACE; 08056 return hr; 08057 } 08058 08059 static HRESULT 08060 find_coclass( 08061 ITypeInfo *pTypeInfo, 08062 TYPEATTR *pTypeAttr, 08063 ITypeInfo **pCOTypeInfo, 08064 TYPEATTR **pCOTypeAttr) 08065 { 08066 HRESULT hr = E_NOINTERFACE; 08067 ITypeLib *pTypeLib; 08068 int count; 08069 BOOL found = FALSE; 08070 ITypeInfo *pTypeInfo2; 08071 TYPEATTR *pTypeAttr2; 08072 int flags; 08073 int i,j; 08074 HREFTYPE href; 08075 ITypeInfo *pRefTypeInfo; 08076 TYPEATTR *pRefTypeAttr; 08077 08078 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); 08079 if (FAILED(hr)) { 08080 return hr; 08081 } 08082 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); 08083 for (i = 0; i < count && !found; i++) { 08084 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2); 08085 if (FAILED(hr)) 08086 continue; 08087 hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2); 08088 if (FAILED(hr)) { 08089 OLE_RELEASE(pTypeInfo2); 08090 continue; 08091 } 08092 if (pTypeAttr2->typekind != TKIND_COCLASS) { 08093 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 08094 OLE_RELEASE(pTypeInfo2); 08095 continue; 08096 } 08097 for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) { 08098 hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags); 08099 if (FAILED(hr)) 08100 continue; 08101 if (!(flags & IMPLTYPEFLAG_FDEFAULT)) 08102 continue; 08103 hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href); 08104 if (FAILED(hr)) 08105 continue; 08106 hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo); 08107 if (FAILED(hr)) 08108 continue; 08109 hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr); 08110 if (FAILED(hr)) { 08111 OLE_RELEASE(pRefTypeInfo); 08112 continue; 08113 } 08114 if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) { 08115 found = TRUE; 08116 } 08117 } 08118 if (!found) { 08119 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 08120 OLE_RELEASE(pTypeInfo2); 08121 } 08122 } 08123 OLE_RELEASE(pTypeLib); 08124 if (found) { 08125 *pCOTypeInfo = pTypeInfo2; 08126 *pCOTypeAttr = pTypeAttr2; 08127 hr = S_OK; 08128 } else { 08129 hr = E_NOINTERFACE; 08130 } 08131 return hr; 08132 } 08133 08134 static HRESULT 08135 find_default_source_from_typeinfo( 08136 ITypeInfo *pTypeInfo, 08137 TYPEATTR *pTypeAttr, 08138 ITypeInfo **ppTypeInfo) 08139 { 08140 int i = 0; 08141 HRESULT hr = E_NOINTERFACE; 08142 int flags; 08143 HREFTYPE hRefType; 08144 /* Enumerate all implemented types of the COCLASS */ 08145 for (i = 0; i < pTypeAttr->cImplTypes; i++) { 08146 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); 08147 if (FAILED(hr)) 08148 continue; 08149 08150 /* 08151 looking for the [default] [source] 08152 we just hope that it is a dispinterface :-) 08153 */ 08154 if ((flags & IMPLTYPEFLAG_FDEFAULT) && 08155 (flags & IMPLTYPEFLAG_FSOURCE)) { 08156 08157 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, 08158 i, &hRefType); 08159 if (FAILED(hr)) 08160 continue; 08161 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, 08162 hRefType, ppTypeInfo); 08163 if (SUCCEEDED(hr)) 08164 break; 08165 } 08166 } 08167 return hr; 08168 } 08169 08170 static HRESULT 08171 find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) 08172 { 08173 HRESULT hr; 08174 IProvideClassInfo2 *pProvideClassInfo2; 08175 IProvideClassInfo *pProvideClassInfo; 08176 void *p; 08177 08178 IDispatch *pDispatch; 08179 ITypeInfo *pTypeInfo; 08180 ITypeInfo *pTypeInfo2 = NULL; 08181 TYPEATTR *pTypeAttr; 08182 TYPEATTR *pTypeAttr2 = NULL; 08183 08184 struct oledata *pole; 08185 08186 OLEData_Get_Struct(ole, pole); 08187 pDispatch = pole->pDispatch; 08188 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 08189 &IID_IProvideClassInfo2, 08190 &p); 08191 if (SUCCEEDED(hr)) { 08192 pProvideClassInfo2 = p; 08193 hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2, 08194 GUIDKIND_DEFAULT_SOURCE_DISP_IID, 08195 piid); 08196 OLE_RELEASE(pProvideClassInfo2); 08197 if (SUCCEEDED(hr)) { 08198 hr = find_iid(ole, NULL, piid, ppTypeInfo); 08199 } 08200 } 08201 if (SUCCEEDED(hr)) { 08202 return hr; 08203 } 08204 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 08205 &IID_IProvideClassInfo, 08206 &p); 08207 if (SUCCEEDED(hr)) { 08208 pProvideClassInfo = p; 08209 hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo, 08210 &pTypeInfo); 08211 OLE_RELEASE(pProvideClassInfo); 08212 } 08213 if (FAILED(hr)) { 08214 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo ); 08215 } 08216 if (FAILED(hr)) 08217 return hr; 08218 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); 08219 if (FAILED(hr)) { 08220 OLE_RELEASE(pTypeInfo); 08221 return hr; 08222 } 08223 08224 *ppTypeInfo = 0; 08225 hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo); 08226 if (!*ppTypeInfo) { 08227 hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2); 08228 if (SUCCEEDED(hr)) { 08229 hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo); 08230 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); 08231 OLE_RELEASE(pTypeInfo2); 08232 } 08233 } 08234 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); 08235 OLE_RELEASE(pTypeInfo); 08236 /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */ 08237 if (!*ppTypeInfo) { 08238 if (SUCCEEDED(hr)) 08239 hr = E_UNEXPECTED; 08240 return hr; 08241 } 08242 08243 /* Determine IID of default source interface */ 08244 hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr); 08245 if (SUCCEEDED(hr)) { 08246 *piid = pTypeAttr->guid; 08247 (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr); 08248 } 08249 else 08250 OLE_RELEASE(*ppTypeInfo); 08251 08252 return hr; 08253 08254 } 08255 08256 static void 08257 ole_event_free(struct oleeventdata *poleev) 08258 { 08259 if (poleev->pConnectionPoint) { 08260 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); 08261 OLE_RELEASE(poleev->pConnectionPoint); 08262 poleev->pConnectionPoint = NULL; 08263 } 08264 free(poleev); 08265 } 08266 08267 static VALUE 08268 fev_s_allocate(VALUE klass) 08269 { 08270 VALUE obj; 08271 struct oleeventdata *poleev; 08272 obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev); 08273 poleev->dwCookie = 0; 08274 poleev->pConnectionPoint = NULL; 08275 poleev->event_id = 0; 08276 return obj; 08277 } 08278 08279 static VALUE 08280 ev_advise(int argc, VALUE *argv, VALUE self) 08281 { 08282 08283 VALUE ole, itf; 08284 struct oledata *pole; 08285 char *pitf; 08286 HRESULT hr; 08287 IID iid; 08288 ITypeInfo *pTypeInfo = 0; 08289 IDispatch *pDispatch; 08290 IConnectionPointContainer *pContainer; 08291 IConnectionPoint *pConnectionPoint; 08292 IEVENTSINKOBJ *pIEV; 08293 DWORD dwCookie; 08294 struct oleeventdata *poleev; 08295 void *p; 08296 08297 rb_secure(4); 08298 rb_scan_args(argc, argv, "11", &ole, &itf); 08299 08300 if (!rb_obj_is_kind_of(ole, cWIN32OLE)) { 08301 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object"); 08302 } 08303 08304 if(TYPE(itf) != T_NIL) { 08305 if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) { 08306 rb_raise(rb_eSecurityError, "Insecure Event Creation - %s", 08307 StringValuePtr(itf)); 08308 } 08309 SafeStringValue(itf); 08310 pitf = StringValuePtr(itf); 08311 hr = find_iid(ole, pitf, &iid, &pTypeInfo); 08312 } 08313 else { 08314 hr = find_default_source(ole, &iid, &pTypeInfo); 08315 } 08316 if (FAILED(hr)) { 08317 ole_raise(hr, rb_eRuntimeError, "interface not found"); 08318 } 08319 08320 OLEData_Get_Struct(ole, pole); 08321 pDispatch = pole->pDispatch; 08322 hr = pDispatch->lpVtbl->QueryInterface(pDispatch, 08323 &IID_IConnectionPointContainer, 08324 &p); 08325 if (FAILED(hr)) { 08326 OLE_RELEASE(pTypeInfo); 08327 ole_raise(hr, rb_eRuntimeError, 08328 "failed to query IConnectionPointContainer"); 08329 } 08330 pContainer = p; 08331 08332 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer, 08333 &iid, 08334 &pConnectionPoint); 08335 OLE_RELEASE(pContainer); 08336 if (FAILED(hr)) { 08337 OLE_RELEASE(pTypeInfo); 08338 ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint"); 08339 } 08340 pIEV = EVENTSINK_Constructor(); 08341 pIEV->m_iid = iid; 08342 hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint, 08343 (IUnknown*)pIEV, 08344 &dwCookie); 08345 if (FAILED(hr)) { 08346 ole_raise(hr, rb_eRuntimeError, "Advise Error"); 08347 } 08348 08349 Data_Get_Struct(self, struct oleeventdata, poleev); 08350 pIEV->m_event_id 08351 = NUM2INT(evs_length()); 08352 pIEV->pTypeInfo = pTypeInfo; 08353 poleev->dwCookie = dwCookie; 08354 poleev->pConnectionPoint = pConnectionPoint; 08355 poleev->event_id = pIEV->m_event_id; 08356 08357 return self; 08358 } 08359 08360 /* 08361 * call-seq: 08362 * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object. 08363 * 08364 * Returns OLE event object. 08365 * The first argument specifies WIN32OLE object. 08366 * The second argument specifies OLE event name. 08367 * ie = WIN32OLE.new('InternetExplorer.Application') 08368 * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') 08369 */ 08370 static VALUE 08371 fev_initialize(int argc, VALUE *argv, VALUE self) 08372 { 08373 ev_advise(argc, argv, self); 08374 evs_push(self); 08375 rb_ivar_set(self, id_events, rb_ary_new()); 08376 fev_set_handler(self, Qnil); 08377 return self; 08378 } 08379 08380 /* 08381 * call-seq: 08382 * WIN32OLE_EVENT.message_loop 08383 * 08384 * Translates and dispatches Windows message. 08385 */ 08386 static VALUE 08387 fev_s_msg_loop(VALUE klass) 08388 { 08389 ole_msg_loop(); 08390 return Qnil; 08391 } 08392 08393 08394 static void 08395 add_event_call_back(VALUE obj, VALUE event, VALUE data) 08396 { 08397 VALUE events = rb_ivar_get(obj, id_events); 08398 if (NIL_P(events) || TYPE(events) != T_ARRAY) { 08399 events = rb_ary_new(); 08400 rb_ivar_set(obj, id_events, events); 08401 } 08402 ole_delete_event(events, event); 08403 rb_ary_push(events, data); 08404 } 08405 08406 static VALUE 08407 ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) 08408 { 08409 struct oleeventdata *poleev; 08410 VALUE event, args, data; 08411 Data_Get_Struct(self, struct oleeventdata, poleev); 08412 if (poleev->pConnectionPoint == NULL) { 08413 rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first."); 08414 } 08415 rb_scan_args(argc, argv, "01*", &event, &args); 08416 if(!NIL_P(event)) { 08417 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) { 08418 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 08419 } 08420 if (TYPE(event) == T_SYMBOL) { 08421 event = rb_sym_to_s(event); 08422 } 08423 } 08424 data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg); 08425 add_event_call_back(self, event, data); 08426 return Qnil; 08427 } 08428 08429 /* 08430 * call-seq: 08431 * WIN32OLE_EVENT#on_event([event]){...} 08432 * 08433 * Defines the callback event. 08434 * If argument is omitted, this method defines the callback of all events. 08435 * If you want to modify reference argument in callback, return hash in 08436 * callback. If you want to return value to OLE server as result of callback 08437 * use `return' or :return. 08438 * 08439 * ie = WIN32OLE.new('InternetExplorer.Application') 08440 * ev = WIN32OLE_EVENT.new(ie) 08441 * ev.on_event("NavigateComplete") {|url| puts url} 08442 * ev.on_event() {|ev, *args| puts "#{ev} fired"} 08443 * 08444 * ev.on_event("BeforeNavigate2") {|*args| 08445 * ... 08446 * # set true to BeforeNavigate reference argument `Cancel'. 08447 * # Cancel is 7-th argument of BeforeNavigate, 08448 * # so you can use 6 as key of hash instead of 'Cancel'. 08449 * # The argument is counted from 0. 08450 * # The hash key of 0 means first argument.) 08451 * {:Cancel => true} # or {'Cancel' => true} or {6 => true} 08452 * } 08453 * 08454 * ev.on_event(...) {|*args| 08455 * {:return => 1, :xxx => yyy} 08456 * } 08457 */ 08458 static VALUE 08459 fev_on_event(int argc, VALUE *argv, VALUE self) 08460 { 08461 return ev_on_event(argc, argv, self, Qfalse); 08462 } 08463 08464 /* 08465 * call-seq: 08466 * WIN32OLE_EVENT#on_event_with_outargs([event]){...} 08467 * 08468 * Defines the callback of event. 08469 * If you want modify argument in callback, 08470 * you could use this method instead of WIN32OLE_EVENT#on_event. 08471 * 08472 * ie = WIN32OLE.new('InternetExplorer.Application') 08473 * ev = WIN32OLE_EVENT.new(ie) 08474 * ev.on_event_with_outargs('BeforeNavigate2') {|*args| 08475 * args.last[6] = true 08476 * } 08477 */ 08478 static VALUE 08479 fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self) 08480 { 08481 return ev_on_event(argc, argv, self, Qtrue); 08482 } 08483 08484 /* 08485 * call-seq: 08486 * WIN32OLE_EVENT#off_event([event]) 08487 * 08488 * removes the callback of event. 08489 * 08490 * ie = WIN32OLE.new('InternetExplorer.Application') 08491 * ev = WIN32OLE_EVENT.new(ie) 08492 * ev.on_event('BeforeNavigate2') {|*args| 08493 * args.last[6] = true 08494 * } 08495 * ... 08496 * ev.off_event('BeforeNavigate2') 08497 * ... 08498 */ 08499 static VALUE 08500 fev_off_event(int argc, VALUE *argv, VALUE self) 08501 { 08502 VALUE event = Qnil; 08503 VALUE events; 08504 08505 rb_secure(4); 08506 rb_scan_args(argc, argv, "01", &event); 08507 if(!NIL_P(event)) { 08508 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) { 08509 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); 08510 } 08511 if (TYPE(event) == T_SYMBOL) { 08512 event = rb_sym_to_s(event); 08513 } 08514 } 08515 events = rb_ivar_get(self, id_events); 08516 if (NIL_P(events)) { 08517 return Qnil; 08518 } 08519 ole_delete_event(events, event); 08520 return Qnil; 08521 } 08522 08523 /* 08524 * call-seq: 08525 * WIN32OLE_EVENT#unadvise -> nil 08526 * 08527 * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object 08528 * does not receive the OLE server event any more. 08529 * This method is trial implementation. 08530 * 08531 * ie = WIN32OLE.new('InternetExplorer.Application') 08532 * ev = WIN32OLE_EVENT.new(ie) 08533 * ev.on_event() {...} 08534 * ... 08535 * ev.unadvise 08536 * 08537 */ 08538 static VALUE 08539 fev_unadvise(VALUE self) 08540 { 08541 struct oleeventdata *poleev; 08542 Data_Get_Struct(self, struct oleeventdata, poleev); 08543 if (poleev->pConnectionPoint) { 08544 ole_msg_loop(); 08545 evs_delete(poleev->event_id); 08546 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); 08547 OLE_RELEASE(poleev->pConnectionPoint); 08548 poleev->pConnectionPoint = NULL; 08549 } 08550 return Qnil; 08551 } 08552 08553 static VALUE 08554 evs_push(VALUE ev) 08555 { 08556 return rb_ary_push(ary_ole_event, ev); 08557 } 08558 08559 static VALUE 08560 evs_delete(long i) 08561 { 08562 rb_ary_store(ary_ole_event, i, Qnil); 08563 return Qnil; 08564 } 08565 08566 static VALUE 08567 evs_entry(long i) 08568 { 08569 return rb_ary_entry(ary_ole_event, i); 08570 } 08571 08572 static VALUE 08573 evs_length(void) 08574 { 08575 return rb_funcall(ary_ole_event, rb_intern("length"), 0); 08576 } 08577 08578 /* 08579 * call-seq: 08580 * WIN32OLE_EVENT#handler= 08581 * 08582 * sets event handler object. If handler object has onXXX 08583 * method according to XXX event, then onXXX method is called 08584 * when XXX event occurs. 08585 * 08586 * If handler object has method_missing and there is no 08587 * method according to the event, then method_missing 08588 * called and 1-st argument is event name. 08589 * 08590 * If handler object has onXXX method and there is block 08591 * defined by WIN32OLE_EVENT#on_event('XXX'){}, 08592 * then block is executed but handler object method is not called 08593 * when XXX event occurs. 08594 * 08595 * class Handler 08596 * def onStatusTextChange(text) 08597 * puts "StatusTextChanged" 08598 * end 08599 * def onPropertyChange(prop) 08600 * puts "PropertyChanged" 08601 * end 08602 * def method_missing(ev, *arg) 08603 * puts "other event #{ev}" 08604 * end 08605 * end 08606 * 08607 * handler = Handler.new 08608 * ie = WIN32OLE.new('InternetExplorer.Application') 08609 * ev = WIN32OLE_EVENT.new(ie) 08610 * ev.on_event("StatusTextChange") {|*args| 08611 * puts "this block executed." 08612 * puts "handler.onStatusTextChange method is not called." 08613 * } 08614 * ev.handler = handler 08615 * 08616 */ 08617 static VALUE 08618 fev_set_handler(VALUE self, VALUE val) 08619 { 08620 return rb_ivar_set(self, rb_intern("handler"), val); 08621 } 08622 08623 /* 08624 * call-seq: 08625 * WIN32OLE_EVENT#handler 08626 * 08627 * returns handler object. 08628 * 08629 */ 08630 static VALUE 08631 fev_get_handler(VALUE self) 08632 { 08633 return rb_ivar_get(self, rb_intern("handler")); 08634 } 08635 08636 static void 08637 olevariant_free(struct olevariantdata *pvar) 08638 { 08639 VariantClear(&(pvar->realvar)); 08640 VariantClear(&(pvar->var)); 08641 free(pvar); 08642 } 08643 08644 static VALUE 08645 folevariant_s_allocate(VALUE klass) 08646 { 08647 struct olevariantdata *pvar; 08648 VALUE obj; 08649 ole_initialize(); 08650 obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar); 08651 VariantInit(&(pvar->var)); 08652 VariantInit(&(pvar->realvar)); 08653 return obj; 08654 } 08655 08656 /* 08657 * call-seq: 08658 * WIN32OLE_VARIANT.array(ary, vt) 08659 * 08660 * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. 08661 * The first argument should be Array object which specifies dimensions 08662 * and each size of dimensions of OLE array. 08663 * The second argument specifies variant type of the element of OLE array. 08664 * 08665 * The following create 2 dimensions OLE array. The first dimensions size 08666 * is 3, and the second is 4. 08667 * 08668 * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4) 08669 * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 08670 * 08671 */ 08672 static VALUE 08673 folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt) 08674 { 08675 VALUE obj = Qnil; 08676 VARTYPE vt; 08677 struct olevariantdata *pvar; 08678 SAFEARRAYBOUND *psab = NULL; 08679 SAFEARRAY *psa = NULL; 08680 UINT dim = 0; 08681 UINT i = 0; 08682 08683 ole_initialize(); 08684 08685 vt = NUM2UINT(vvt); 08686 vt = (vt | VT_ARRAY); 08687 Check_Type(elems, T_ARRAY); 08688 obj = folevariant_s_allocate(klass); 08689 08690 Data_Get_Struct(obj, struct olevariantdata, pvar); 08691 dim = RARRAY_LEN(elems); 08692 08693 psab = ALLOC_N(SAFEARRAYBOUND, dim); 08694 08695 if(!psab) { 08696 rb_raise(rb_eRuntimeError, "memory allocation error"); 08697 } 08698 08699 for (i = 0; i < dim; i++) { 08700 psab[i].cElements = FIX2INT(rb_ary_entry(elems, i)); 08701 psab[i].lLbound = 0; 08702 } 08703 08704 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); 08705 if (psa == NULL) { 08706 if (psab) free(psab); 08707 rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)"); 08708 } 08709 08710 V_VT(&(pvar->var)) = vt; 08711 if (vt & VT_BYREF) { 08712 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); 08713 V_ARRAY(&(pvar->realvar)) = psa; 08714 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); 08715 } else { 08716 V_ARRAY(&(pvar->var)) = psa; 08717 } 08718 if (psab) free(psab); 08719 return obj; 08720 } 08721 08722 /* 08723 * call-seq: 08724 * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object. 08725 * 08726 * Returns Ruby object wrapping OLE variant. 08727 * The first argument specifies Ruby object to convert OLE variant variable. 08728 * The second argument specifies VARIANT type. 08729 * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method 08730 * 08731 * shell = WIN32OLE.new("Shell.Application") 08732 * folder = shell.NameSpace("C:\\Windows") 08733 * item = folder.ParseName("tmp.txt") 08734 * # You can't use Ruby String object to call FolderItem.InvokeVerb. 08735 * # Instead, you have to use WIN32OLE_VARIANT object to call the method. 08736 * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)") 08737 * item.invokeVerb(shortcut) 08738 * 08739 */ 08740 static VALUE 08741 folevariant_initialize(VALUE self, VALUE args) 08742 { 08743 int len = 0; 08744 VARIANT var; 08745 VALUE val; 08746 VALUE vvt; 08747 VARTYPE vt; 08748 struct olevariantdata *pvar; 08749 08750 len = RARRAY_LEN(args); 08751 if (len < 1 || len > 3) { 08752 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); 08753 } 08754 VariantInit(&var); 08755 val = rb_ary_entry(args, 0); 08756 08757 if(!rb_obj_is_kind_of(val, cWIN32OLE) && 08758 !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) && 08759 !rb_obj_is_kind_of(val, rb_cTime)) { 08760 switch (TYPE(val)) { 08761 case T_ARRAY: 08762 case T_STRING: 08763 case T_FIXNUM: 08764 case T_BIGNUM: 08765 case T_FLOAT: 08766 case T_TRUE: 08767 case T_FALSE: 08768 case T_NIL: 08769 break; 08770 default: 08771 rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s", 08772 rb_obj_classname(val)); 08773 } 08774 } 08775 08776 Data_Get_Struct(self, struct olevariantdata, pvar); 08777 if (len == 1) { 08778 ole_val2variant(val, &(pvar->var)); 08779 } else { 08780 vvt = rb_ary_entry(args, 1); 08781 vt = NUM2INT(vvt); 08782 ole_val2olevariantdata(val, vt, pvar); 08783 } 08784 vt = V_VT(&pvar->var); 08785 return self; 08786 } 08787 08788 static SAFEARRAY * 08789 get_locked_safe_array(VALUE val) 08790 { 08791 struct olevariantdata *pvar; 08792 SAFEARRAY *psa = NULL; 08793 HRESULT hr; 08794 Data_Get_Struct(val, struct olevariantdata, pvar); 08795 if (!(V_VT(&(pvar->var)) & VT_ARRAY)) { 08796 rb_raise(rb_eTypeError, "variant type is not VT_ARRAY."); 08797 } 08798 psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var)); 08799 if (psa == NULL) { 08800 return psa; 08801 } 08802 hr = SafeArrayLock(psa); 08803 if (FAILED(hr)) { 08804 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock"); 08805 } 08806 return psa; 08807 } 08808 08809 static long * 08810 ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa) 08811 { 08812 long dim; 08813 long *pid; 08814 long i; 08815 dim = SafeArrayGetDim(psa); 08816 if (dim != ary_size) { 08817 rb_raise(rb_eArgError, "unmatch number of indices"); 08818 } 08819 pid = ALLOC_N(long, dim); 08820 if (pid == NULL) { 08821 rb_raise(rb_eRuntimeError, "failed to allocate memory for indices"); 08822 } 08823 for (i = 0; i < dim; i++) { 08824 pid[i] = NUM2INT(ary[i]); 08825 } 08826 return pid; 08827 } 08828 08829 static void 08830 unlock_safe_array(SAFEARRAY *psa) 08831 { 08832 HRESULT hr; 08833 hr = SafeArrayUnlock(psa); 08834 if (FAILED(hr)) { 08835 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock"); 08836 } 08837 } 08838 08839 /* 08840 * call-seq: 08841 * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array. 08842 * 08843 * Returns the element of WIN32OLE_VARIANT object(OLE array). 08844 * This method is available only when the variant type of 08845 * WIN32OLE_VARIANT object is VT_ARRAY. 08846 * 08847 * REMARK: 08848 * The all indicies should be 0 or natural number and 08849 * lower than or equal to max indicies. 08850 * (This point is different with Ruby Array indicies.) 08851 * 08852 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) 08853 * p obj[0,0] # => 1 08854 * p obj[1,0] # => 4 08855 * p obj[2,0] # => WIN32OLERuntimeError 08856 * p obj[0, -1] # => WIN32OLERuntimeError 08857 * 08858 */ 08859 static VALUE 08860 folevariant_ary_aref(int argc, VALUE *argv, VALUE self) 08861 { 08862 struct olevariantdata *pvar; 08863 SAFEARRAY *psa; 08864 VALUE val = Qnil; 08865 VARIANT variant; 08866 long *pid; 08867 HRESULT hr; 08868 08869 Data_Get_Struct(self, struct olevariantdata, pvar); 08870 if (!V_ISARRAY(&(pvar->var))) { 08871 rb_raise(eWIN32OLERuntimeError, 08872 "`[]' is not available for this variant type object"); 08873 } 08874 psa = get_locked_safe_array(self); 08875 if (psa == NULL) { 08876 return val; 08877 } 08878 08879 pid = ary2safe_array_index(argc, argv, psa); 08880 08881 VariantInit(&variant); 08882 V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF; 08883 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); 08884 if (FAILED(hr)) { 08885 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex"); 08886 } 08887 val = ole_variant2val(&variant); 08888 08889 unlock_safe_array(psa); 08890 if (pid) free(pid); 08891 return val; 08892 } 08893 08894 static VOID * 08895 val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt) 08896 { 08897 VOID *p = NULL; 08898 HRESULT hr = S_OK; 08899 ole_val2variant_ex(val, var, vt); 08900 if ((vt & ~VT_BYREF) == VT_VARIANT) { 08901 p = var; 08902 } else { 08903 if ( (vt & ~VT_BYREF) != V_VT(var)) { 08904 hr = VariantChangeTypeEx(var, var, 08905 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); 08906 if (FAILED(hr)) { 08907 ole_raise(hr, rb_eRuntimeError, "failed to change type"); 08908 } 08909 } 08910 p = get_ptr_of_variant(var); 08911 } 08912 if (p == NULL) { 08913 rb_raise(rb_eRuntimeError, "failed to get pointer of variant"); 08914 } 08915 return p; 08916 } 08917 08918 /* 08919 * call-seq: 08920 * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array 08921 * 08922 * Set the element of WIN32OLE_VARIANT object(OLE array) to val. 08923 * This method is available only when the variant type of 08924 * WIN32OLE_VARIANT object is VT_ARRAY. 08925 * 08926 * REMARK: 08927 * The all indicies should be 0 or natural number and 08928 * lower than or equal to max indicies. 08929 * (This point is different with Ruby Array indicies.) 08930 * 08931 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) 08932 * obj[0,0] = 7 08933 * obj[1,0] = 8 08934 * p obj.value # => [[7,2,3], [8,5,6]] 08935 * obj[2,0] = 9 # => WIN32OLERuntimeError 08936 * obj[0, -1] = 9 # => WIN32OLERuntimeError 08937 * 08938 */ 08939 static VALUE 08940 folevariant_ary_aset(int argc, VALUE *argv, VALUE self) 08941 { 08942 struct olevariantdata *pvar; 08943 SAFEARRAY *psa; 08944 VARIANT var; 08945 VARTYPE vt; 08946 long *pid; 08947 HRESULT hr; 08948 VOID *p = NULL; 08949 08950 Data_Get_Struct(self, struct olevariantdata, pvar); 08951 if (!V_ISARRAY(&(pvar->var))) { 08952 rb_raise(eWIN32OLERuntimeError, 08953 "`[]' is not available for this variant type object"); 08954 } 08955 psa = get_locked_safe_array(self); 08956 if (psa == NULL) { 08957 rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer"); 08958 } 08959 08960 pid = ary2safe_array_index(argc-1, argv, psa); 08961 08962 VariantInit(&var); 08963 vt = (V_VT(&(pvar->var)) & ~VT_ARRAY); 08964 p = val2variant_ptr(argv[argc-1], &var, vt); 08965 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || 08966 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { 08967 rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface"); 08968 } 08969 hr = SafeArrayPutElement(psa, pid, p); 08970 if (FAILED(hr)) { 08971 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement"); 08972 } 08973 08974 unlock_safe_array(psa); 08975 if (pid) free(pid); 08976 return argv[argc-1]; 08977 } 08978 08979 /* 08980 * call-seq: 08981 * WIN32OLE_VARIANT.value #=> Ruby object. 08982 * 08983 * Returns Ruby object value from OLE variant. 08984 * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) 08985 * obj.value # => "1" (not Fixnum object, but String object "1") 08986 * 08987 */ 08988 static VALUE 08989 folevariant_value(VALUE self) 08990 { 08991 struct olevariantdata *pvar; 08992 VALUE val = Qnil; 08993 VARTYPE vt; 08994 int dim; 08995 SAFEARRAY *psa; 08996 Data_Get_Struct(self, struct olevariantdata, pvar); 08997 08998 val = ole_variant2val(&(pvar->var)); 08999 vt = V_VT(&(pvar->var)); 09000 09001 if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) { 09002 if (vt & VT_BYREF) { 09003 psa = *V_ARRAYREF(&(pvar->var)); 09004 } else { 09005 psa = V_ARRAY(&(pvar->var)); 09006 } 09007 if (!psa) { 09008 return val; 09009 } 09010 dim = SafeArrayGetDim(psa); 09011 if (dim == 1) { 09012 val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*")); 09013 } 09014 } 09015 return val; 09016 } 09017 09018 /* 09019 * call-seq: 09020 * WIN32OLE_VARIANT.vartype #=> OLE variant type. 09021 * 09022 * Returns OLE variant type. 09023 * obj = WIN32OLE_VARIANT.new("string") 09024 * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR 09025 * 09026 */ 09027 static VALUE 09028 folevariant_vartype(VALUE self) 09029 { 09030 struct olevariantdata *pvar; 09031 Data_Get_Struct(self, struct olevariantdata, pvar); 09032 return INT2FIX(V_VT(&pvar->var)); 09033 } 09034 09035 /* 09036 * call-seq: 09037 * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val. 09038 * 09039 * Sets variant value to val. If the val type does not match variant value 09040 * type(vartype), then val is changed to match variant value type(vartype) 09041 * before setting val. 09042 * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY). 09043 * If the vartype is VT_UI1|VT_ARRAY, the val should be String object. 09044 * 09045 * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4 09046 * obj.value = 3.2 # 3.2 is changed to 3 when setting value. 09047 * p obj.value # => 3 09048 */ 09049 static VALUE 09050 folevariant_set_value(VALUE self, VALUE val) 09051 { 09052 struct olevariantdata *pvar; 09053 VARTYPE vt; 09054 Data_Get_Struct(self, struct olevariantdata, pvar); 09055 vt = V_VT(&(pvar->var)); 09056 if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) { 09057 rb_raise(eWIN32OLERuntimeError, 09058 "`value=' is not available for this variant type object"); 09059 } 09060 ole_val2olevariantdata(val, vt, pvar); 09061 return Qnil; 09062 } 09063 09064 static void 09065 init_enc2cp(void) 09066 { 09067 enc2cp_table = st_init_numtable(); 09068 } 09069 09070 static void 09071 free_enc2cp(void) 09072 { 09073 st_free_table(enc2cp_table); 09074 } 09075 09076 void 09077 Init_win32ole(void) 09078 { 09079 g_ole_initialized_init(); 09080 ary_ole_event = rb_ary_new(); 09081 rb_gc_register_mark_object(ary_ole_event); 09082 id_events = rb_intern("events"); 09083 09084 com_vtbl.QueryInterface = QueryInterface; 09085 com_vtbl.AddRef = AddRef; 09086 com_vtbl.Release = Release; 09087 com_vtbl.GetTypeInfoCount = GetTypeInfoCount; 09088 com_vtbl.GetTypeInfo = GetTypeInfo; 09089 com_vtbl.GetIDsOfNames = GetIDsOfNames; 09090 com_vtbl.Invoke = Invoke; 09091 09092 message_filter.QueryInterface = mf_QueryInterface; 09093 message_filter.AddRef = mf_AddRef; 09094 message_filter.Release = mf_Release; 09095 message_filter.HandleInComingCall = mf_HandleInComingCall; 09096 message_filter.RetryRejectedCall = mf_RetryRejectedCall; 09097 message_filter.MessagePending = mf_MessagePending; 09098 09099 com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); 09100 rb_gc_register_mark_object(com_hash); 09101 09102 cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); 09103 09104 rb_define_alloc_func(cWIN32OLE, fole_s_allocate); 09105 09106 rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1); 09107 09108 rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1); 09109 rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1); 09110 09111 rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1); 09112 rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1); 09113 rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1); 09114 rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0); 09115 rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1); 09116 rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0); 09117 rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1); 09118 rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0); 09119 rb_define_singleton_method(cWIN32OLE, "ole_initialize", fole_s_ole_initialize, 0); 09120 rb_define_singleton_method(cWIN32OLE, "ole_uninitialize", fole_s_ole_uninitialize, 0); 09121 09122 rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1); 09123 rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1); 09124 rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3); 09125 rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3); 09126 rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3); 09127 09128 /* support propput method that takes an argument */ 09129 rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1); 09130 09131 rb_define_method(cWIN32OLE, "ole_free", fole_free, 0); 09132 09133 rb_define_method(cWIN32OLE, "each", fole_each, 0); 09134 rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1); 09135 09136 /* support setproperty method much like Perl ;-) */ 09137 rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1); 09138 09139 rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0); 09140 rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0); 09141 rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0); 09142 rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0); 09143 09144 rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1); 09145 rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method"); 09146 rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0); 09147 rb_define_method(cWIN32OLE, "ole_type", fole_type, 0); 09148 rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type"); 09149 rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0); 09150 rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1); 09151 rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1); 09152 09153 rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION)); 09154 rb_define_const(cWIN32OLE, "ARGV", rb_ary_new()); 09155 09156 rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP)); 09157 rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP)); 09158 rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP)); 09159 rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP)); 09160 rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL)); 09161 rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7)); 09162 rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8)); 09163 09164 rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT)); 09165 rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT)); 09166 09167 mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT"); 09168 rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY)); 09169 rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL)); 09170 rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2)); 09171 rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4)); 09172 rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4)); 09173 rb_define_const(mWIN32OLE_VARIANT, "VT_R8", INT2FIX(VT_R8)); 09174 rb_define_const(mWIN32OLE_VARIANT, "VT_CY", INT2FIX(VT_CY)); 09175 rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", INT2FIX(VT_DATE)); 09176 rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", INT2FIX(VT_BSTR)); 09177 rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", INT2FIX(VT_USERDEFINED)); 09178 rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", INT2FIX(VT_PTR)); 09179 rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", INT2FIX(VT_DISPATCH)); 09180 rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", INT2FIX(VT_ERROR)); 09181 rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", INT2FIX(VT_BOOL)); 09182 rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", INT2FIX(VT_VARIANT)); 09183 rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", INT2FIX(VT_UNKNOWN)); 09184 rb_define_const(mWIN32OLE_VARIANT, "VT_I1", INT2FIX(VT_I1)); 09185 rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1)); 09186 rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2)); 09187 rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4)); 09188 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) 09189 rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8)); 09190 rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8)); 09191 #endif 09192 rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT)); 09193 rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT)); 09194 rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY)); 09195 rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF)); 09196 09197 cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject); 09198 rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0); 09199 rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate); 09200 rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2); 09201 rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0); 09202 rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0); 09203 rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0); 09204 rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0); 09205 rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0); 09206 rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0); 09207 rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0); 09208 rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types"); 09209 rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0); 09210 rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0); 09211 rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name"); 09212 rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0); 09213 09214 cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject); 09215 rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1); 09216 rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0); 09217 rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0); 09218 rb_define_alloc_func(cWIN32OLE_TYPE, foletype_s_allocate); 09219 rb_define_method(cWIN32OLE_TYPE, "initialize", foletype_initialize, 2); 09220 rb_define_method(cWIN32OLE_TYPE, "name", foletype_name, 0); 09221 rb_define_method(cWIN32OLE_TYPE, "ole_type", foletype_ole_type, 0); 09222 rb_define_method(cWIN32OLE_TYPE, "guid", foletype_guid, 0); 09223 rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0); 09224 rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0); 09225 rb_define_alias(cWIN32OLE_TYPE, "to_s", "name"); 09226 rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0); 09227 rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0); 09228 rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0); 09229 rb_define_method(cWIN32OLE_TYPE, "helpstring", foletype_helpstring, 0); 09230 rb_define_method(cWIN32OLE_TYPE, "src_type", foletype_src_type, 0); 09231 rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0); 09232 rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0); 09233 rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0); 09234 rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0); 09235 rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0); 09236 rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0); 09237 rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0); 09238 rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0); 09239 rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0); 09240 rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0); 09241 09242 cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject); 09243 rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0); 09244 rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0); 09245 rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0); 09246 rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0); 09247 rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0); 09248 rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0); 09249 rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0); 09250 rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0); 09251 rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name"); 09252 09253 cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); 09254 rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); 09255 rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); 09256 rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0); 09257 rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0); 09258 rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0); 09259 rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0); 09260 rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0); 09261 rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0); 09262 rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0); 09263 rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0); 09264 rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0); 09265 rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0); 09266 rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0); 09267 rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0); 09268 rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0); 09269 rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0); 09270 rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0); 09271 rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0); 09272 rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0); 09273 rb_define_alias(cWIN32OLE_METHOD, "to_s", "name"); 09274 rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0); 09275 09276 cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject); 09277 rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate); 09278 rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2); 09279 rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0); 09280 rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0); 09281 rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0); 09282 rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0); 09283 rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0); 09284 rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0); 09285 rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0); 09286 rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0); 09287 rb_define_alias(cWIN32OLE_PARAM, "to_s", "name"); 09288 rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0); 09289 09290 cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject); 09291 rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0); 09292 rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate); 09293 rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1); 09294 rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1); 09295 rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1); 09296 rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1); 09297 rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0); 09298 rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1); 09299 rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0); 09300 09301 cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject); 09302 rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate); 09303 rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2); 09304 rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2); 09305 rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0); 09306 rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1); 09307 rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0); 09308 rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1); 09309 rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1); 09310 rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY))); 09311 rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL))); 09312 rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH))); 09313 09314 eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); 09315 09316 init_enc2cp(); 09317 atexit((void (*)(void))free_enc2cp); 09318 ole_init_cp(); 09319 } 09320
1.7.6.1