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