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