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