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

Generated on Wed Sep 8 2010 09:55:43 for Ruby by  doxygen 1.7.1