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