• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

ext/win32ole/win32ole.c

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

Generated on Thu Sep 8 2011 03:50:41 for Ruby by  doxygen 1.7.1