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