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