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