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