Skip to content

Instantly share code, notes, and snippets.

@jarib
Created August 5, 2009 20:08
Show Gist options
  • Save jarib/162915 to your computer and use it in GitHub Desktop.
Save jarib/162915 to your computer and use it in GitHub Desktop.
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index dc1b77d..51f6b58 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -12,16 +12,22 @@
*/
/*
- $Date$
modified for win32ole (ruby) by Masaki.Suketa <[email protected]>
*/
-#include "ruby.h"
-#include "st.h"
+#include "ruby/ruby.h"
+#include "ruby/st.h"
+#include "ruby/encoding.h"
+#include <ctype.h>
#include <windows.h>
#include <ocidl.h>
#include <olectl.h>
#include <ole2.h>
+#if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE)
+#include <mlang.h>
+#endif
+#include <stdlib.h>
+#include <math.h>
#ifdef HAVE_STDARG_PROTOTYPES
#include <stdarg.h>
#define va_init_list(a,b) va_start(a,b)
@@ -54,6 +60,39 @@
#define V_BOOL(X) V_UNION(X,boolVal)
#endif
+#ifndef V_I1REF
+#define V_I1REF(X) V_UNION(X, pcVal)
+#endif
+
+#ifndef U_UI2REF
+#define V_UI2REF(X) V_UNION(X, puiVal)
+#endif
+
+#ifndef V_INT
+#define V_INT(X) V_UNION(X, intVal)
+#endif
+
+#ifndef V_INTREF
+#define V_INTREF(X) V_UNION(X, pintVal)
+#endif
+
+#ifndef V_UINT
+#define V_UINT(X) V_UNION(X, uintVal)
+#endif
+
+#ifndef V_UINTREF
+#define V_UINTREF(X) V_UNION(X, puintVal)
+#endif
+
+/*
+ * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a
+ * in Cygwin(mingw32).
+ */
+#if defined(__CYGWIN__) || defined(__MINGW32__)
+#undef IID_IMultiLanguage2
+const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}};
+#endif
+
#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
@@ -62,7 +101,7 @@
#define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y)))
#define OLE_FREE(x) {\
- if(gOLEInitialized == Qtrue) {\
+ if(g_ole_initialized == TRUE) {\
if(x) {\
OLE_RELEASE(x);\
(x) = 0;\
@@ -77,15 +116,28 @@
}\
}
+#ifdef HAVE_LONG_LONG
+#define I8_2_NUM LL2NUM
+#define UI8_2_NUM ULL2NUM
+#define NUM2I8 NUM2LL
+#define NUM2UI8 NUM2ULL
+#else
+#define I8_2_NUM INT2NUM
+#define UI8_2_NUM UINT2NUM
+#define NUM2I8 NUM2INT
+#define NUM2UI8 NUM2UINT
+#endif
+
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-#define WIN32OLE_VERSION "0.7.6"
+#define WIN32OLE_VERSION "1.3.9"
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile,
UINT uCommand, DWORD dwData);
+typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD);
typedef struct {
struct IEventSinkVtbl * lpVtbl;
} IEventSink, *PEVENTSINK;
@@ -132,35 +184,50 @@ typedef struct tagIEVENTSINKOBJ {
DWORD m_cRef;
IID m_iid;
int m_event_id;
- DWORD m_dwCookie;
- IConnectionPoint *pConnectionPoint;
ITypeInfo *pTypeInfo;
- int *ptr_freed;
}IEVENTSINKOBJ, *PIEVENTSINKOBJ;
VALUE cWIN32OLE;
+VALUE cWIN32OLE_TYPELIB;
VALUE cWIN32OLE_TYPE;
VALUE cWIN32OLE_VARIABLE;
VALUE cWIN32OLE_METHOD;
VALUE cWIN32OLE_PARAM;
VALUE cWIN32OLE_EVENT;
-VALUE eWIN32OLE_RUNTIME_ERROR;
+VALUE cWIN32OLE_VARIANT;
+VALUE eWIN32OLERuntimeError;
VALUE mWIN32OLE_VARIANT;
+VALUE cWIN32OLE_PROPERTY;
static VALUE ary_ole_event;
static ID id_events;
-static BOOL gOLEInitialized = Qfalse;
+static BOOL g_ole_initialized = FALSE;
+static BOOL g_cp_installed = FALSE;
+static BOOL g_lcid_installed = FALSE;
static HINSTANCE ghhctrl = NULL;
static HINSTANCE gole32 = NULL;
static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL;
static VALUE com_hash;
static IDispatchVtbl com_vtbl;
-static UINT cWIN32OLE_cp = CP_ACP;
+static UINT cWIN32OLE_cp = CP_ACP;
+static LCID cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT;
+static rb_encoding *cWIN32OLE_enc;
+static UINT g_cp_to_check = CP_ACP;
+static char g_lcid_to_check[8 + 1];
static VARTYPE g_nil_to = VT_ERROR;
+static st_table *enc2cp_table;
static IMessageFilterVtbl message_filter;
static IMessageFilter imessage_filter = { &message_filter };
static IMessageFilter* previous_filter;
+#if defined(HAVE_TYPE_IMULTILANGUAGE2)
+static IMultiLanguage2 *pIMultiLanguage = NULL;
+#elif defined(HAVE_TYPE_IMULTILANGUAGE)
+static IMultiLanguage *pIMultiLanguage = NULL;
+#else
+#define pIMultiLanguage NULL /* dummy */
+#endif
+
struct oledata {
IDispatch *pDispatch;
};
@@ -187,8 +254,9 @@ struct oleparamdata {
};
struct oleeventdata {
- IEVENTSINKOBJ *pEvent;
- int freed;
+ DWORD dwCookie;
+ IConnectionPoint *pConnectionPoint;
+ long event_id;
};
struct oleparam {
@@ -196,15 +264,308 @@ struct oleparam {
OLECHAR** pNamedArgs;
};
-static VALUE folemethod_s_allocate _((VALUE));
-static VALUE olemethod_set_member _((VALUE, ITypeInfo *, ITypeInfo *, int, VALUE));
-static VALUE foletype_s_allocate _((VALUE));
-static VALUE oletype_set_member _((VALUE, ITypeInfo *, VALUE));
-static VALUE olemethod_from_typeinfo _((VALUE, ITypeInfo *, VALUE));
-static HRESULT ole_docinfo_from_type _((ITypeInfo *, BSTR *, BSTR *, DWORD *, BSTR *));
-static char *ole_wc2mb(LPWSTR);
-static VALUE ole_variant2val(VARIANT*);
-static void ole_val2variant(VALUE, VARIANT*);
+struct olevariantdata {
+ VARIANT realvar;
+ VARIANT var;
+};
+
+
+static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
+static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This);
+static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This);
+static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo);
+static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId);
+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);
+static IDispatch* val2dispatch(VALUE val);
+static void time2d(int hh, int mm, int ss, double *pv);
+static void d2time(double v, int *hh, int *mm, int *ss);
+static void civil2jd(int y, int m, int d, long *jd);
+static void jd2civil(long day, int *yy, int *mm, int *dd);
+static void double2time(double v, int *y, int *m, int *d, int *hh, int *mm, int *ss);
+static double time_object2date(VALUE tmobj);
+static VALUE date2time_str(double date);
+static rb_encoding *ole_cp2encoding(UINT cp);
+static UINT ole_encoding2cp(rb_encoding *enc);
+NORETURN(static void failed_load_conv51932(void));
+#ifndef pIMultiLanguage
+static void load_conv_function51932(void);
+#endif
+static UINT ole_init_cp(void);
+static char *ole_wc2mb(LPWSTR pw);
+static VALUE ole_hresult2msg(HRESULT hr);
+static void ole_freeexceptinfo(EXCEPINFO *pExInfo);
+static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo);
+static void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...);
+static void ole_initialize();
+static void ole_msg_loop();
+static void ole_free(struct oledata *pole);
+static void oletype_free(struct oletypedata *poletype);
+static void olemethod_free(struct olemethoddata *polemethod);
+static void olevariable_free(struct olevariabledata *polevar);
+static void oleparam_free(struct oleparamdata *pole);
+static LPWSTR ole_vstr2wc(VALUE vstr);
+static LPWSTR ole_mb2wc(char *pm, int len);
+static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree);
+static VALUE ole_ary_m_entry(VALUE val, long *pid);
+static void * get_ptr_of_variant(VARIANT *pvar);
+static VALUE is_all_index_under(long *pid, long *pub, long dim);
+static void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt);
+static long dimension(VALUE val);
+static long ary_len_of_dim(VALUE ary, long dim);
+static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
+static void ole_val2variant(VALUE val, VARIANT *var);
+static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
+static void ole_val2ptr_variant(VALUE val, VARIANT *var);
+static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
+static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
+static void ole_val2variant2(VALUE val, VARIANT *var);
+static VALUE make_inspect(const char *class_name, VALUE detail);
+static VALUE default_inspect(VALUE self, const char *class_name);
+static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
+static VALUE fole_s_allocate(VALUE klass);
+static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
+static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim);
+static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val);
+static VALUE ole_variant2val(VARIANT *pvar);
+static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey);
+static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey);
+static VALUE reg_enum_key(HKEY hkey, DWORD i);
+static VALUE reg_get_val(HKEY hkey, const char *subkey);
+static VALUE reg_get_typelib_file_path(HKEY hkey);
+static VALUE typelib_file_from_clsid(VALUE ole);
+static VALUE typelib_file_from_typelib(VALUE ole);
+static VALUE typelib_file(VALUE ole);
+static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self);
+static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid);
+static VALUE ole_create_dcom(int argc, VALUE *argv, VALUE self);
+static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self);
+static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self);
+static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self);
+static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes);
+static ULONG reference_count(struct oledata * pole);
+static VALUE fole_s_reference_count(VALUE self, VALUE obj);
+static VALUE fole_s_free(VALUE self, VALUE obj);
+static HWND ole_show_help(VALUE helpfile, VALUE helpcontext);
+static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self);
+static VALUE fole_s_get_code_page(VALUE self);
+static BOOL CALLBACK installed_code_page_proc(LPTSTR str);
+static BOOL code_page_installed(UINT cp);
+static VALUE fole_s_set_code_page(VALUE self, VALUE vcp);
+static VALUE fole_s_get_locale(VALUE self);
+static BOOL CALLBACK installed_lcid_proc(LPTSTR str);
+static BOOL lcid_installed(LCID lcid);
+static VALUE fole_s_set_locale(VALUE self, VALUE vlcid);
+static VALUE fole_s_create_guid(VALUE self);
+static VALUE fole_initialize(int argc, VALUE *argv, VALUE self);
+static VALUE hash2named_arg(VALUE pair, struct oleparam* pOp);
+static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end);
+static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket);
+static VALUE fole_invoke(int argc, VALUE *argv, VALUE self);
+static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind);
+static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types);
+static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
+static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
+static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self);
+static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self);
+static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self);
+static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value);
+static VALUE fole_free(VALUE self);
+static VALUE ole_each_sub(VALUE pEnumV);
+static VALUE ole_ienum_free(VALUE pEnumV);
+static VALUE fole_each(VALUE self);
+static VALUE fole_missing(int argc, VALUE *argv, VALUE self);
+static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name);
+static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
+static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask);
+static VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask);
+static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti);
+static VALUE ole_methods(VALUE self, int mask);
+static VALUE fole_methods(VALUE self);
+static VALUE fole_get_methods(VALUE self);
+static VALUE fole_put_methods(VALUE self);
+static VALUE fole_func_methods(VALUE self);
+static VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo);
+static VALUE fole_type(VALUE self);
+static VALUE make_oletypelib_obj(VALUE guid, VALUE major_version, VALUE minor_version);
+static VALUE ole_typelib_from_itypelib(ITypeLib *pTypeLib);
+static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo);
+static VALUE fole_typelib(VALUE self);
+static VALUE fole_query_interface(VALUE self, VALUE str_iid);
+static VALUE fole_respond_to(VALUE self, VALUE method);
+static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
+static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
+static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
+static VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
+static VALUE fole_method_help(VALUE self, VALUE cmdname);
+static VALUE fole_activex_initialize(VALUE self);
+static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib);
+static VALUE foletype_s_typelibs(VALUE self);
+static VALUE foletype_s_progids(VALUE self);
+static VALUE foletype_s_allocate(VALUE klass);
+static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
+static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass);
+static VALUE oletypelib_set_member(VALUE self, VALUE typelib, VALUE guid, VALUE version);
+static VALUE foletypelib_s_typelibs(VALUE self);
+static VALUE make_version_str(VALUE major, VALUE minor);
+static VALUE oletypelib_search_registry2(VALUE self, VALUE args);
+static VALUE oletypelib_search_registry(VALUE self, VALUE typelib);
+static VALUE foletypelib_initialize(VALUE self, VALUE args);
+static VALUE foletypelib_guid(VALUE self);
+static VALUE foletypelib_name(VALUE self);
+static VALUE foletypelib_version(VALUE self);
+static VALUE foletypelib_major_version(VALUE self);
+static VALUE foletypelib_minor_version(VALUE self);
+static VALUE oletypelib_path(VALUE guid, VALUE version);
+static VALUE foletypelib_path(VALUE self);
+static void oletypelib2itypelib(VALUE self, ITypeLib **ppTypeLib);
+static VALUE foletypelib_visible(VALUE self);
+static VALUE foletypelib_library_name(VALUE self);
+static VALUE foletypelib_ole_types(VALUE self);
+static VALUE foletypelib_inspect(VALUE self);
+static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass);
+static VALUE foletype_name(VALUE self);
+static VALUE ole_ole_type(ITypeInfo *pTypeInfo);
+static VALUE foletype_ole_type(VALUE self);
+static VALUE ole_type_guid(ITypeInfo *pTypeInfo);
+static VALUE foletype_guid(VALUE self);
+static VALUE ole_type_progid(ITypeInfo *pTypeInfo);
+static VALUE foletype_progid(VALUE self);
+static VALUE ole_type_visible(ITypeInfo *pTypeInfo);
+static VALUE foletype_visible(VALUE self);
+static VALUE ole_type_major_version(ITypeInfo *pTypeInfo);
+static VALUE foletype_major_version(VALUE self);
+static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo);
+static VALUE foletype_minor_version(VALUE self);
+static VALUE ole_type_typekind(ITypeInfo *pTypeInfo);
+static VALUE foletype_typekind(VALUE self);
+static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo);
+static VALUE foletype_helpstring(VALUE self);
+static VALUE ole_type_src_type(ITypeInfo *pTypeInfo);
+static VALUE foletype_src_type(VALUE self);
+static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo);
+static VALUE foletype_helpfile(VALUE self);
+static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo);
+static VALUE foletype_helpcontext(VALUE self);
+static VALUE foletype_ole_typelib(VALUE self);
+static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags);
+static VALUE foletype_impl_ole_types(VALUE self);
+static VALUE foletype_source_ole_types(VALUE self);
+static VALUE foletype_default_event_sources(VALUE self);
+static VALUE foletype_default_ole_types(VALUE self);
+static VALUE foletype_inspect(VALUE self);
+static VALUE ole_variables(ITypeInfo *pTypeInfo);
+static VALUE foletype_variables(VALUE self);
+static VALUE foletype_methods(VALUE self);
+static VALUE folevariable_name(VALUE self);
+static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index);
+static VALUE folevariable_ole_type(VALUE self);
+static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index);
+static VALUE folevariable_ole_type_detail(VALUE self);
+static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index);
+static VALUE folevariable_value(VALUE self);
+static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index);
+static VALUE folevariable_visible(VALUE self);
+static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index);
+static VALUE folevariable_variable_kind(VALUE self);
+static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index);
+static VALUE folevariable_varkind(VALUE self);
+static VALUE folevariable_inspect(VALUE self);
+static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name);
+static VALUE folemethod_s_allocate(VALUE klass);
+static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method);
+static VALUE folemethod_name(VALUE self);
+static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_return_type(VALUE self);
+static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_return_vtype(VALUE self);
+static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_return_type_detail(VALUE self);
+static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_invkind(VALUE self);
+static VALUE folemethod_invoke_kind(VALUE self);
+static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_visible(VALUE self);
+static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name);
+static VALUE folemethod_event(VALUE self);
+static VALUE folemethod_event_interface(VALUE self);
+static VALUE ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
+static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_helpstring(VALUE self);
+static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_helpfile(VALUE self);
+static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_helpcontext(VALUE self);
+static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_dispid(VALUE self);
+static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_offset_vtbl(VALUE self);
+static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_size_params(VALUE self);
+static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_size_opt_params(VALUE self);
+static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index);
+static VALUE folemethod_params(VALUE self);
+static VALUE folemethod_inspect(VALUE self);
+static VALUE foleparam_name(VALUE self);
+static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
+static VALUE foleparam_ole_type(VALUE self);
+static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
+static VALUE foleparam_ole_type_detail(VALUE self);
+static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask);
+static VALUE foleparam_input(VALUE self);
+static VALUE foleparam_output(VALUE self);
+static VALUE foleparam_optional(VALUE self);
+static VALUE foleparam_retval(VALUE self);
+static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
+static VALUE foleparam_default(VALUE self);
+static VALUE foleparam_inspect(VALUE self);
+static long ole_search_event_at(VALUE ary, VALUE ev);
+static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
+static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
+static void ole_delete_event(VALUE ary, VALUE ev);
+static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
+static VALUE hash2result(VALUE hash);
+static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
+static VALUE exec_callback(VALUE arg);
+static VALUE rescue_callback(VALUE arg);
+static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
+static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
+static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
+static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
+static void ole_event_free(struct oleeventdata *poleev);
+static VALUE fev_s_allocate(VALUE klass);
+static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
+static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
+static VALUE fev_s_msg_loop(VALUE klass);
+static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
+static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
+static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
+static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
+static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
+static VALUE fev_unadvise(VALUE self);
+static VALUE fev_set_handler(VALUE self, VALUE val);
+static VALUE fev_get_handler(VALUE self);
+static VALUE evs_push(VALUE ev);
+static VALUE evs_delete(long i);
+static VALUE evs_entry(long i);
+static VALUE evs_length();
+static void olevariant_free(struct olevariantdata *pvar);
+static VALUE folevariant_s_allocate(VALUE klass);
+static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
+static VALUE folevariant_initialize(VALUE self, VALUE args);
+static long *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
+static void unlock_safe_array(SAFEARRAY *psa);
+static SAFEARRAY *get_locked_safe_array(VALUE val);
+static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
+static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
+static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
+static VALUE folevariant_value(VALUE self);
+static VALUE folevariant_vartype(VALUE self);
+static VALUE folevariant_set_value(VALUE self, VALUE val);
+static void init_enc2cp();
+static void free_enc2cp();
static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
IMessageFilter __RPC_FAR * This,
@@ -369,7 +730,9 @@ static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
{
+ /*
Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
+ */
char* psz = ole_wc2mb(*rgszNames); // support only one method
*rgDispId = rb_intern(psz);
free(psz);
@@ -408,8 +771,7 @@ static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )(
}
static IDispatch*
-val2dispatch(val)
- VALUE val;
+val2dispatch(VALUE val)
{
struct st_table *tbl = DATA_PTR(com_hash);
Win32OLEIDispatch* pdisp;
@@ -430,22 +792,18 @@ val2dispatch(val)
}
static void
-time2d(hh, mm, ss, pv)
- int hh, mm, ss;
- double *pv;
+time2d(int hh, int mm, int ss, double *pv)
{
*pv = (hh * 60.0 * 60.0 + mm * 60.0 + ss) / 86400.0;
}
static void
-d2time(v, hh, mm, ss)
- double v;
- int *hh, *mm, *ss;
+d2time(double v, int *hh, int *mm, int *ss)
{
double d_hh, d_mm, d_ss;
int i_hh, i_mm, i_ss;
- double d = v * 86400.0;
+ double d = fabs(v * 86400.0);
d_hh = d / 3600.0;
i_hh = (int)d_hh;
@@ -480,9 +838,7 @@ d2time(v, hh, mm, ss)
}
static void
-civil2jd(y, m, d, jd)
- int y, m, d;
- long *jd;
+civil2jd(int y, int m, int d, long *jd)
{
long a, b;
if (m <= 2) {
@@ -497,9 +853,7 @@ civil2jd(y, m, d, jd)
}
static void
-jd2civil(day, yy, mm, dd)
- long day;
- int *yy, *mm, *dd;
+jd2civil(long day, int *yy, int *mm, int *dd)
{
long x, a, b, c, d, e;
x = (long)(((double)day - 1867216.25) / 36524.25);
@@ -520,9 +874,7 @@ jd2civil(day, yy, mm, dd)
}
static void
-double2time(v, y, m, d, hh, mm, ss)
- double v;
- int *y, *m, *d, *hh, *mm, *ss;
+double2time(double v, int *y, int *m, int *d, int *hh, int *mm, int *ss)
{
long day;
double t;
@@ -535,8 +887,7 @@ double2time(v, y, m, d, hh, mm, ss)
}
static double
-time_object2date(tmobj)
- VALUE tmobj;
+time_object2date(VALUE tmobj)
{
long y, m, d, hh, mm, ss;
long day;
@@ -553,26 +904,243 @@ time_object2date(tmobj)
}
static VALUE
-date2time_str(date)
- double date;
+date2time_str(double date)
{
int y, m, d, hh, mm, ss;
- char szTime[40];
double2time(date, &y, &m, &d, &hh, &mm, &ss);
- sprintf(szTime,
- "%4.4d/%02.2d/%02.2d %02.2d:%02.2d:%02.2d",
+ return rb_sprintf(
+ "%04d/%02d/%02d %02d:%02d:%02d",
y, m, d, hh, mm, ss);
- return rb_str_new2(szTime);
}
-static void ole_val2variant();
+#define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp
+
+static UINT ole_encoding2cp(rb_encoding *enc)
+{
+ /*
+ * Is there any better solution to convert
+ * Ruby encoding to Windows codepage???
+ */
+ ENC_MACHING_CP(enc, "Big5", 950);
+ ENC_MACHING_CP(enc, "CP51932", 51932);
+ ENC_MACHING_CP(enc, "CP850", 850);
+ ENC_MACHING_CP(enc, "CP852", 852);
+ ENC_MACHING_CP(enc, "CP855", 855);
+ ENC_MACHING_CP(enc, "CP949", 949);
+ ENC_MACHING_CP(enc, "EUC-JP", 20932);
+ ENC_MACHING_CP(enc, "EUC-KR", 51949);
+ ENC_MACHING_CP(enc, "EUC-TW", 51950);
+ ENC_MACHING_CP(enc, "GB18030", 54936);
+ ENC_MACHING_CP(enc, "GB2312", 51936);
+ ENC_MACHING_CP(enc, "GBK", 936);
+ ENC_MACHING_CP(enc, "IBM437", 437);
+ ENC_MACHING_CP(enc, "IBM737", 737);
+ ENC_MACHING_CP(enc, "IBM775", 775);
+ ENC_MACHING_CP(enc, "IBM852", 852);
+ ENC_MACHING_CP(enc, "IBM855", 855);
+ ENC_MACHING_CP(enc, "IBM857", 857);
+ ENC_MACHING_CP(enc, "IBM860", 860);
+ ENC_MACHING_CP(enc, "IBM861", 861);
+ ENC_MACHING_CP(enc, "IBM862", 862);
+ ENC_MACHING_CP(enc, "IBM863", 863);
+ ENC_MACHING_CP(enc, "IBM864", 864);
+ ENC_MACHING_CP(enc, "IBM865", 865);
+ ENC_MACHING_CP(enc, "IBM866", 866);
+ ENC_MACHING_CP(enc, "IBM869", 869);
+ ENC_MACHING_CP(enc, "ISO-2022-JP", 50220);
+ ENC_MACHING_CP(enc, "ISO-8859-1", 28591);
+ ENC_MACHING_CP(enc, "ISO-8859-15", 28605);
+ ENC_MACHING_CP(enc, "ISO-8859-2", 28592);
+ ENC_MACHING_CP(enc, "ISO-8859-3", 28593);
+ ENC_MACHING_CP(enc, "ISO-8859-4", 28594);
+ ENC_MACHING_CP(enc, "ISO-8859-5", 28595);
+ ENC_MACHING_CP(enc, "ISO-8859-6", 28596);
+ ENC_MACHING_CP(enc, "ISO-8859-7", 28597);
+ ENC_MACHING_CP(enc, "ISO-8859-8", 28598);
+ ENC_MACHING_CP(enc, "ISO-8859-9", 28599);
+ ENC_MACHING_CP(enc, "KOI8-R", 20866);
+ ENC_MACHING_CP(enc, "KOI8-U", 21866);
+ ENC_MACHING_CP(enc, "Shift_JIS", 932);
+ ENC_MACHING_CP(enc, "UTF-16BE", 1201);
+ ENC_MACHING_CP(enc, "UTF-16LE", 1200);
+ ENC_MACHING_CP(enc, "UTF-7", 65000);
+ ENC_MACHING_CP(enc, "UTF-8", 65001);
+ ENC_MACHING_CP(enc, "Windows-1250", 1250);
+ ENC_MACHING_CP(enc, "Windows-1251", 1251);
+ ENC_MACHING_CP(enc, "Windows-1252", 1252);
+ ENC_MACHING_CP(enc, "Windows-1253", 1253);
+ ENC_MACHING_CP(enc, "Windows-1254", 1254);
+ ENC_MACHING_CP(enc, "Windows-1255", 1255);
+ ENC_MACHING_CP(enc, "Windows-1256", 1256);
+ ENC_MACHING_CP(enc, "Windows-1257", 1257);
+ ENC_MACHING_CP(enc, "Windows-1258", 1258);
+ ENC_MACHING_CP(enc, "Windows-31J", 932);
+ ENC_MACHING_CP(enc, "Windows-874", 874);
+ ENC_MACHING_CP(enc, "eucJP-ms", 20932);
+ return CP_ACP;
+}
+
+static void
+failed_load_conv51932(void)
+{
+ rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932");
+}
+
+#ifndef pIMultiLanguage
+static void
+load_conv_function51932(void)
+{
+ HRESULT hr = E_NOINTERFACE;
+ void *p;
+ if (!pIMultiLanguage) {
+#if defined(HAVE_TYPE_IMULTILANGUAGE2)
+ hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMultiLanguage2, &p);
+#elif defined(HAVE_TYPE_IMULTILANGUAGE)
+ hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMultiLanguage, &p);
+#endif
+ if (FAILED(hr)) {
+ failed_load_conv51932();
+ }
+ pIMultiLanguage = p;
+ }
+}
+#else
+#define load_conv_function51932() failed_load_conv51932()
+#endif
+
+#define conv_51932(cp) ((cp) == 51932 && (load_conv_function51932(), 1))
+
+static void
+set_ole_codepage(UINT cp)
+{
+ if (code_page_installed(cp)) {
+ cWIN32OLE_cp = cp;
+ } else {
+ switch(cp) {
+ case CP_ACP:
+ case CP_OEMCP:
+ case CP_MACCP:
+ case CP_THREAD_ACP:
+ case CP_SYMBOL:
+ case CP_UTF7:
+ case CP_UTF8:
+ cWIN32OLE_cp = cp;
+ break;
+ case 51932:
+ cWIN32OLE_cp = cp;
+ load_conv_function51932();
+ break;
+ default:
+ 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.");
+ break;
+ }
+ }
+ cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
+}
+
+
+static UINT
+ole_init_cp(void)
+{
+ UINT cp;
+ rb_encoding *encdef;
+ encdef = rb_default_internal_encoding();
+ if (!encdef) {
+ encdef = rb_default_external_encoding();
+ }
+ cp = ole_encoding2cp(encdef);
+ set_ole_codepage(cp);
+ return cp;
+}
+
+struct myCPINFOEX {
+ UINT MaxCharSize;
+ BYTE DefaultChar[2];
+ BYTE LeadByte[12];
+ WCHAR UnicodeDefaultChar;
+ UINT CodePage;
+ char CodePageName[MAX_PATH];
+};
+
+static rb_encoding *
+ole_cp2encoding(UINT cp)
+{
+ static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL;
+ struct myCPINFOEX* buf;
+ VALUE enc_name;
+ char *enc_cstr;
+ int idx;
+
+ if (!code_page_installed(cp)) {
+ switch(cp) {
+ case CP_ACP:
+ cp = GetACP();
+ break;
+ case CP_OEMCP:
+ cp = GetOEMCP();
+ break;
+ case CP_MACCP:
+ case CP_THREAD_ACP:
+ if (!pGetCPInfoEx) {
+ pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
+ GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
+ if (!pGetCPInfoEx) {
+ pGetCPInfoEx = (void*)-1;
+ }
+ }
+ buf = ALLOCA_N(struct myCPINFOEX, 1);
+ ZeroMemory(buf, sizeof(struct myCPINFOEX));
+ if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
+ rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
+ break; /* never reach here */
+ }
+ cp = buf->CodePage;
+ break;
+ case CP_SYMBOL:
+ case CP_UTF7:
+ case CP_UTF8:
+ break;
+ case 51932:
+ load_conv_function51932();
+ break;
+ default:
+ 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.");
+ break;
+ }
+ }
+
+ enc_name = rb_sprintf("CP%d", cp);
+ idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name));
+ if (idx < 0)
+ idx = rb_define_dummy_encoding(enc_cstr);
+ return rb_enc_from_index(idx);
+}
static char *
-ole_wc2mb(pw)
- LPWSTR pw;
+ole_wc2mb(LPWSTR pw)
{
- int size;
LPSTR pm;
+ int size = 0;
+ if (conv_51932(cWIN32OLE_cp)) {
+#ifndef pIMultiLanguage
+ DWORD dw = 0;
+ HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pw, NULL, NULL, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
+ }
+ pm = ALLOC_N(char, size + 1);
+ hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pw, NULL, pm, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
+ }
+ pm[size] = '\0';
+#endif
+ return pm;
+ }
size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL);
if (size) {
pm = ALLOC_N(char, size + 1);
@@ -587,8 +1155,7 @@ ole_wc2mb(pw)
}
static VALUE
-ole_hresult2msg(hr)
- HRESULT hr;
+ole_hresult2msg(HRESULT hr)
{
VALUE msg = Qnil;
char *p_msg = NULL;
@@ -596,13 +1163,13 @@ ole_hresult2msg(hr)
DWORD dwCount;
char strhr[100];
- sprintf(strhr, " HRESULT error code:0x%08lx\n ", hr);
+ sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr);
msg = rb_str_new2(strhr);
dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, hr, LOCALE_SYSTEM_DEFAULT,
+ NULL, hr, cWIN32OLE_lcid,
(LPTSTR)&p_msg, 0, NULL);
if (dwCount > 0) {
term = p_msg + strlen(p_msg);
@@ -621,8 +1188,7 @@ ole_hresult2msg(hr)
}
static void
-ole_freeexceptinfo(pExInfo)
- EXCEPINFO *pExInfo;
+ole_freeexceptinfo(EXCEPINFO *pExInfo)
{
SysFreeString(pExInfo->bstrDescription);
SysFreeString(pExInfo->bstrSource);
@@ -630,8 +1196,7 @@ ole_freeexceptinfo(pExInfo)
}
static VALUE
-ole_excepinfo2msg(pExInfo)
- EXCEPINFO *pExInfo;
+ole_excepinfo2msg(EXCEPINFO *pExInfo)
{
char error_code[40];
char *pSource = NULL;
@@ -673,15 +1238,7 @@ ole_excepinfo2msg(pExInfo)
}
static void
-#ifdef HAVE_STDARG_PROTOTYPES
ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...)
-#else
-ole_raise(hr, exc, fmt, va_alist)
- HRESULT hr;
- VALUE exc;
- const char *fmt;
- va_dcl
-#endif
{
va_list args;
char buf[BUFSIZ];
@@ -703,7 +1260,7 @@ void
ole_uninitialize()
{
OleUninitialize();
- gOLEInitialized = Qfalse;
+ g_ole_initialized = FALSE;
}
static void
@@ -711,12 +1268,12 @@ ole_initialize()
{
HRESULT hr;
- if(gOLEInitialized == Qfalse) {
+ if(g_ole_initialized == FALSE) {
hr = OleInitialize(NULL);
if(FAILED(hr)) {
ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize");
}
- gOLEInitialized = Qtrue;
+ g_ole_initialized = TRUE;
/*
* In some situation, OleUninitialize does not work fine. ;-<
*/
@@ -741,24 +1298,21 @@ ole_msg_loop() {
}
static void
-ole_free(pole)
- struct oledata *pole;
+ole_free(struct oledata *pole)
{
OLE_FREE(pole->pDispatch);
free(pole);
}
static void
-oletype_free(poletype)
- struct oletypedata *poletype;
+oletype_free(struct oletypedata *poletype)
{
OLE_FREE(poletype->pTypeInfo);
free(poletype);
}
static void
-olemethod_free(polemethod)
- struct olemethoddata *polemethod;
+olemethod_free(struct olemethoddata *polemethod)
{
OLE_FREE(polemethod->pTypeInfo);
OLE_FREE(polemethod->pOwnerTypeInfo);
@@ -766,28 +1320,97 @@ olemethod_free(polemethod)
}
static void
-olevariable_free(polevar)
- struct olevariabledata *polevar;
+olevariable_free(struct olevariabledata *polevar)
{
OLE_FREE(polevar->pTypeInfo);
free(polevar);
}
static void
-oleparam_free(pole)
- struct oleparamdata *pole;
+oleparam_free(struct oleparamdata *pole)
{
OLE_FREE(pole->pTypeInfo);
free(pole);
}
+
static LPWSTR
-ole_mb2wc(pm, len)
- char *pm;
- int len;
+ole_vstr2wc(VALUE vstr)
{
- int size;
+ rb_encoding *enc;
+ int cp;
+ int size = 0;
LPWSTR pw;
+ st_data_t data;
+ enc = rb_enc_get(vstr);
+
+ if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) {
+ cp = data;
+ } else {
+ cp = ole_encoding2cp(enc);
+ if (code_page_installed(cp) ||
+ cp == CP_ACP ||
+ cp == CP_OEMCP ||
+ cp == CP_MACCP ||
+ cp == CP_THREAD_ACP ||
+ cp == CP_SYMBOL ||
+ cp == CP_UTF7 ||
+ cp == CP_UTF8 ||
+ cp == 51932) {
+ st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp);
+ } else {
+ rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
+ }
+ }
+ if (conv_51932(cp)) {
+#ifndef pIMultiLanguage
+ DWORD dw = 0;
+ int len = RSTRING_LEN(vstr);
+ HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cp, RSTRING_PTR(vstr), &len, NULL, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
+ }
+ pw = SysAllocStringLen(NULL, size);
+ len = RSTRING_LEN(vstr);
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cp, RSTRING_PTR(vstr), &len, pw, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
+ }
+#endif
+ return pw;
+ }
+ size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0);
+ pw = SysAllocStringLen(NULL, size);
+ MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size);
+ return pw;
+}
+
+static LPWSTR
+ole_mb2wc(char *pm, int len)
+{
+ int size = 0;
+ LPWSTR pw;
+
+ if (conv_51932(cWIN32OLE_cp)) {
+#ifndef pIMultiLanguage
+ DWORD dw = 0;
+ int n = len;
+ HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pm, &n, NULL, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
+ }
+ pw = SysAllocStringLen(NULL, size);
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pm, &n, pw, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
+ }
+#endif
+ return pw;
+ }
size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0);
pw = SysAllocStringLen(NULL, size - 1);
MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size);
@@ -795,12 +1418,10 @@ ole_mb2wc(pm, len)
}
static VALUE
-ole_wc2vstr(pw, isfree)
- LPWSTR pw;
- BOOL isfree;
+ole_wc2vstr(LPWSTR pw, BOOL isfree)
{
char *p = ole_wc2mb(pw);
- VALUE vstr = rb_str_new2(p);
+ VALUE vstr = rb_enc_str_new(p, strlen(p), cWIN32OLE_enc);
if(isfree)
SysFreeString(pw);
free(p);
@@ -808,9 +1429,7 @@ ole_wc2vstr(pw, isfree)
}
static VALUE
-ole_ary_m_entry(val, pid)
- VALUE val;
- long *pid;
+ole_ary_m_entry(VALUE val, long *pid)
{
VALUE obj = Qnil;
int i = 0;
@@ -822,40 +1441,230 @@ ole_ary_m_entry(val, pid)
return obj;
}
+static void *
+get_ptr_of_variant(VARIANT *pvar)
+{
+ switch(V_VT(pvar)) {
+ case VT_UI1:
+ return &V_UI1(pvar);
+ break;
+ case VT_I2:
+ return &V_I2(pvar);
+ break;
+ case VT_UI2:
+ return &V_UI2(pvar);
+ break;
+ case VT_I4:
+ return &V_I4(pvar);
+ break;
+ case VT_UI4:
+ return &V_UI4(pvar);
+ break;
+ case VT_R4:
+ return &V_R4(pvar);
+ break;
+ case VT_R8:
+ return &V_R8(pvar);
+ break;
+#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
+ case VT_I8:
+ return &V_I8(pvar);
+ break;
+ case VT_UI8:
+ return &V_UI8(pvar);
+ break;
+#endif
+ case VT_INT:
+ return &V_INT(pvar);
+ break;
+ case VT_UINT:
+ return &V_UINT(pvar);
+ break;
+ case VT_CY:
+ return &V_CY(pvar);
+ break;
+ case VT_DATE:
+ return &V_DATE(pvar);
+ break;
+ case VT_BSTR:
+ return V_BSTR(pvar);
+ break;
+ case VT_DISPATCH:
+ return V_DISPATCH(pvar);
+ break;
+ case VT_ERROR:
+ return &V_ERROR(pvar);
+ break;
+ case VT_BOOL:
+ return &V_BOOL(pvar);
+ break;
+ case VT_UNKNOWN:
+ return V_UNKNOWN(pvar);
+ break;
+ case VT_ARRAY:
+ return &V_ARRAY(pvar);
+ break;
+ default:
+ return NULL;
+ break;
+ }
+}
+
+static VALUE
+is_all_index_under(long *pid, long *pub, long dim)
+{
+ long i = 0;
+ for (i = 0; i < dim; i++) {
+ if (pid[i] > pub[i]) {
+ return Qfalse;
+ }
+ }
+ return Qtrue;
+}
+
static void
-ole_set_safe_array(n, psa, pid, pub, val, dim)
- long n;
- SAFEARRAY *psa;
- long *pid;
- long *pub;
- VALUE val;
- long dim;
+ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt)
{
VALUE val1;
+ HRESULT hr = S_OK;
VARIANT var;
- VariantInit(&var);
- if(n < 0) return;
- if(n == dim) {
+ VOID *p = NULL;
+ long i = n;
+ while(i >= 0) {
val1 = ole_ary_m_entry(val, pid);
- ole_val2variant(val1, &var);
- SafeArrayPutElement(psa, pid, &var);
+ VariantInit(&var);
+ p = val2variant_ptr(val1, &var, vt);
+ if (is_all_index_under(pid, pub, dim) == Qtrue) {
+ if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
+ (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
+ rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface");
+ }
+ hr = SafeArrayPutElement(psa, pid, p);
+ }
+ if (FAILED(hr)) {
+ ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement");
+ }
+ pid[i] += 1;
+ if (pid[i] > pub[i]) {
+ pid[i] = 0;
+ i -= 1;
+ } else {
+ i = dim - 1;
+ }
+ }
+}
+
+static long
+dimension(VALUE val) {
+ long dim = 0;
+ long dim1 = 0;
+ long len = 0;
+ long i = 0;
+ if (TYPE(val) == T_ARRAY) {
+ len = RARRAY_LEN(val);
+ for (i = 0; i < len; i++) {
+ dim1 = dimension(rb_ary_entry(val, i));
+ if (dim < dim1) {
+ dim = dim1;
+ }
+ }
+ dim += 1;
+ }
+ return dim;
+}
+
+static long
+ary_len_of_dim(VALUE ary, long dim) {
+ long ary_len = 0;
+ long ary_len1 = 0;
+ long len = 0;
+ long i = 0;
+ VALUE val;
+ if (dim == 0) {
+ if (TYPE(ary) == T_ARRAY) {
+ ary_len = RARRAY_LEN(ary);
+ }
+ } else {
+ if (TYPE(ary) == T_ARRAY) {
+ len = RARRAY_LEN(ary);
+ for (i = 0; i < len; i++) {
+ val = rb_ary_entry(ary, i);
+ ary_len1 = ary_len_of_dim(val, dim-1);
+ if (ary_len < ary_len1) {
+ ary_len = ary_len1;
+ }
+ }
+ }
+ }
+ return ary_len;
+}
+
+static HRESULT
+ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
+{
+ long dim = 0;
+ int i = 0;
+ HRESULT hr = S_OK;
+
+ SAFEARRAYBOUND *psab = NULL;
+ SAFEARRAY *psa = NULL;
+ long *pub, *pid;
+
+ Check_Type(val, T_ARRAY);
+
+ dim = dimension(val);
+
+ psab = ALLOC_N(SAFEARRAYBOUND, dim);
+ pub = ALLOC_N(long, dim);
+ pid = ALLOC_N(long, dim);
+
+ if(!psab || !pub || !pid) {
+ if(pub) free(pub);
+ if(psab) free(psab);
+ if(pid) free(pid);
+ rb_raise(rb_eRuntimeError, "memory allocation error");
}
- pid[n] += 1;
- if (pid[n] < pub[n]) {
- ole_set_safe_array(dim, psa, pid, pub, val, dim);
+
+ for (i = 0; i < dim; i++) {
+ psab[i].cElements = ary_len_of_dim(val, i);
+ psab[i].lLbound = 0;
+ pub[i] = psab[i].cElements - 1;
+ pid[i] = 0;
+ }
+ /* Create and fill VARIANT array */
+ if ((vt & ~VT_BYREF) == VT_ARRAY) {
+ vt = (vt | VT_VARIANT);
+ }
+ psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
+ if (psa == NULL)
+ hr = E_OUTOFMEMORY;
+ else
+ hr = SafeArrayLock(psa);
+ if (SUCCEEDED(hr)) {
+ ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK));
+ hr = SafeArrayUnlock(psa);
+ }
+
+ if(pub) free(pub);
+ if(psab) free(psab);
+ if(pid) free(pid);
+
+ if (SUCCEEDED(hr)) {
+ V_VT(var) = vt;
+ V_ARRAY(var) = psa;
}
else {
- pid[n] = 0;
- ole_set_safe_array(n-1, psa, pid, pub, val, dim);
+ if (psa != NULL)
+ SafeArrayDestroy(psa);
}
+ return hr;
}
static void
-ole_val2variant(val, var)
- VALUE val;
- VARIANT *var;
+ole_val2variant(VALUE val, VARIANT *var)
{
struct oledata *pole;
+ struct olevariantdata *pvar;
if(rb_obj_is_kind_of(val, cWIN32OLE)) {
Data_Get_Struct(val, struct oledata, pole);
OLE_ADDREF(pole->pDispatch);
@@ -863,6 +1672,12 @@ ole_val2variant(val, var)
V_DISPATCH(var) = pole->pDispatch;
return;
}
+ if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) {
+ Data_Get_Struct(val, struct olevariantdata, pvar);
+ VariantCopy(var, &(pvar->var));
+ return;
+ }
+
if (rb_obj_is_kind_of(val, rb_cTime)) {
V_VT(var) = VT_DATE;
V_DATE(var) = time_object2date(val);
@@ -870,66 +1685,11 @@ ole_val2variant(val, var)
}
switch (TYPE(val)) {
case T_ARRAY:
- {
- VALUE val1;
- long dim = 0;
- int i = 0;
-
- HRESULT hr;
- SAFEARRAYBOUND *psab;
- SAFEARRAY *psa;
- long *pub, *pid;
-
- val1 = val;
- while(TYPE(val1) == T_ARRAY) {
- val1 = rb_ary_entry(val1, 0);
- dim += 1;
- }
- psab = ALLOC_N(SAFEARRAYBOUND, dim);
- pub = ALLOC_N(long, dim);
- pid = ALLOC_N(long, dim);
-
- if(!psab || !pub || !pid) {
- if(pub) free(pub);
- if(psab) free(psab);
- if(pid) free(pid);
- rb_raise(rb_eRuntimeError, "memory allocation error");
- }
- val1 = val;
- i = 0;
- while(TYPE(val1) == T_ARRAY) {
- psab[i].cElements = RARRAY(val1)->len;
- psab[i].lLbound = 0;
- pub[i] = psab[i].cElements;
- pid[i] = 0;
- i ++;
- val1 = rb_ary_entry(val1, 0);
- }
- /* Create and fill VARIANT array */
- psa = SafeArrayCreate(VT_VARIANT, dim, psab);
- if (psa == NULL)
- hr = E_OUTOFMEMORY;
- else
- hr = SafeArrayLock(psa);
- if (SUCCEEDED(hr)) {
- ole_set_safe_array(dim-1, psa, pid, pub, val, dim-1);
- hr = SafeArrayUnlock(psa);
- }
- if(pub) free(pub);
- if(psab) free(psab);
- if(pid) free(pid);
-
- if (SUCCEEDED(hr)) {
- V_VT(var) = VT_VARIANT | VT_ARRAY;
- V_ARRAY(var) = psa;
- }
- else if (psa != NULL)
- SafeArrayDestroy(psa);
+ ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY);
break;
- }
case T_STRING:
V_VT(var) = VT_BSTR;
- V_BSTR(var) = ole_mb2wc(StringValuePtr(val), -1);
+ V_BSTR(var) = ole_vstr2wc(val);
break;
case T_FIXNUM:
V_VT(var) = VT_I4;
@@ -967,9 +1727,290 @@ ole_val2variant(val, var)
}
static void
-ole_val2variant2(val, var)
- VALUE val;
- VARIANT *var;
+ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
+{
+ if (val == Qnil) {
+ if (vt == VT_VARIANT) {
+ ole_val2variant2(val, var);
+ } else {
+ V_VT(var) = (vt & ~VT_BYREF);
+ if (V_VT(var) == VT_DISPATCH) {
+ V_DISPATCH(var) = NULL;
+ } else if (V_VT(var) == VT_UNKNOWN) {
+ V_UNKNOWN(var) = NULL;
+ }
+ }
+ return;
+ }
+#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
+ switch(vt & ~VT_BYREF) {
+ case VT_I8:
+ V_VT(var) = VT_I8;
+ V_I8(var) = NUM2I8 (val);
+ break;
+ case VT_UI8:
+ V_VT(var) = VT_UI8;
+ V_UI8(var) = NUM2UI8(val);
+ break;
+ default:
+ ole_val2variant2(val, var);
+ break;
+ }
+#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
+ ole_val2variant2(val, var);
+#endif
+}
+
+static void
+ole_val2ptr_variant(VALUE val, VARIANT *var)
+{
+ switch (TYPE(val)) {
+ case T_STRING:
+ if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
+ *V_BSTRREF(var) = ole_vstr2wc(val);
+ }
+ break;
+ case T_FIXNUM:
+ switch(V_VT(var)) {
+ case (VT_UI1 | VT_BYREF) :
+ *V_UI1REF(var) = NUM2CHR(val);
+ break;
+ case (VT_I2 | VT_BYREF) :
+ *V_I2REF(var) = (short)NUM2INT(val);
+ break;
+ case (VT_I4 | VT_BYREF) :
+ *V_I4REF(var) = NUM2INT(val);
+ break;
+ case (VT_R4 | VT_BYREF) :
+ *V_R4REF(var) = (float)NUM2INT(val);
+ break;
+ case (VT_R8 | VT_BYREF) :
+ *V_R8REF(var) = NUM2INT(val);
+ break;
+ default:
+ break;
+ }
+ break;
+ case T_FLOAT:
+ switch(V_VT(var)) {
+ case (VT_I2 | VT_BYREF) :
+ *V_I2REF(var) = (short)NUM2INT(val);
+ break;
+ case (VT_I4 | VT_BYREF) :
+ *V_I4REF(var) = NUM2INT(val);
+ break;
+ case (VT_R4 | VT_BYREF) :
+ *V_R4REF(var) = (float)NUM2DBL(val);
+ break;
+ case (VT_R8 | VT_BYREF) :
+ *V_R8REF(var) = NUM2DBL(val);
+ break;
+ default:
+ break;
+ }
+ break;
+ case T_BIGNUM:
+ if (V_VT(var) == (VT_R8 | VT_BYREF)) {
+ *V_R8REF(var) = rb_big2dbl(val);
+ }
+ break;
+ case T_TRUE:
+ if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
+ *V_BOOLREF(var) = VARIANT_TRUE;
+ }
+ break;
+ case T_FALSE:
+ if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
+ *V_BOOLREF(var) = VARIANT_FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
+{
+ V_VT(var) = vt;
+ if (vt == (VT_VARIANT|VT_BYREF)) {
+ V_VARIANTREF(var) = realvar;
+ } else {
+ if (V_VT(realvar) != (vt & ~VT_BYREF)) {
+ rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
+ }
+ switch(vt & ~VT_BYREF) {
+ case VT_I1:
+ V_I1REF(var) = &V_I1(realvar);
+ break;
+ case VT_UI1:
+ V_UI1REF(var) = &V_UI1(realvar);
+ break;
+ case VT_I2:
+ V_I2REF(var) = &V_I2(realvar);
+ break;
+ case VT_UI2:
+ V_UI2REF(var) = &V_UI2(realvar);
+ break;
+ case VT_I4:
+ V_I4REF(var) = &V_I4(realvar);
+ break;
+ case VT_UI4:
+ V_UI4REF(var) = &V_UI4(realvar);
+ break;
+ case VT_R4:
+ V_R4REF(var) = &V_R4(realvar);
+ break;
+ case VT_R8:
+ V_R8REF(var) = &V_R8(realvar);
+ break;
+
+#if (_MSC_VER >= 1300)
+ case VT_I8:
+ V_I8REF(var) = &V_I8(realvar);
+ break;
+ case VT_UI8:
+ V_UI8REF(var) = &V_UI8(realvar);
+ break;
+#endif
+ case VT_INT:
+ V_INTREF(var) = &V_INT(realvar);
+ break;
+
+ case VT_UINT:
+ V_UINTREF(var) = &V_UINT(realvar);
+ break;
+
+ case VT_CY:
+ V_CYREF(var) = &V_CY(realvar);
+ break;
+ case VT_DATE:
+ V_DATEREF(var) = &V_DATE(realvar);
+ break;
+ case VT_BSTR:
+ V_BSTRREF(var) = &V_BSTR(realvar);
+ break;
+ case VT_DISPATCH:
+ V_DISPATCHREF(var) = &V_DISPATCH(realvar);
+ break;
+ case VT_ERROR:
+ V_ERRORREF(var) = &V_ERROR(realvar);
+ break;
+ case VT_BOOL:
+ V_BOOLREF(var) = &V_BOOL(realvar);
+ break;
+ case VT_UNKNOWN:
+ V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
+ break;
+ case VT_ARRAY:
+ V_ARRAYREF(var) = &V_ARRAY(realvar);
+ break;
+ default:
+ rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
+ break;
+ }
+ }
+}
+
+static void
+ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
+{
+ HRESULT hr = S_OK;
+
+ if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && TYPE(val) == T_STRING) {
+ long len = RSTRING_LEN(val);
+ void *pdest = NULL;
+ SAFEARRAY *p = NULL;
+ SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
+ if (!psa) {
+ rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
+ }
+ hr = SafeArrayAccessData(psa, &pdest);
+ if (SUCCEEDED(hr)) {
+ memcpy(pdest, RSTRING_PTR(val), len);
+ SafeArrayUnaccessData(psa);
+ V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
+ p = V_ARRAY(&(pvar->realvar));
+ if (p != NULL) {
+ SafeArrayDestroy(p);
+ }
+ V_ARRAY(&(pvar->realvar)) = psa;
+ if (vt & VT_BYREF) {
+ V_VT(&(pvar->var)) = vt;
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
+ } else {
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
+ }
+ } else {
+ if (psa)
+ SafeArrayDestroy(psa);
+ }
+ } else if (vt & VT_ARRAY) {
+ if (val == Qnil) {
+ V_VT(&(pvar->var)) = vt;
+ if (vt & VT_BYREF) {
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
+ }
+ } else {
+ hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
+ if (SUCCEEDED(hr)) {
+ if (vt & VT_BYREF) {
+ V_VT(&(pvar->var)) = vt;
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
+ } else {
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
+ }
+ }
+ }
+#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
+ } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) {
+ ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF));
+ ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF));
+ V_VT(&(pvar->var)) = vt;
+ if (vt & VT_BYREF) {
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
+ }
+#endif
+ } else {
+ if (val == Qnil) {
+ V_VT(&(pvar->var)) = vt;
+ if (vt == (VT_BYREF | VT_VARIANT)) {
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
+ } else {
+ V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
+ if (vt & VT_BYREF) {
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
+ }
+ }
+ } else {
+ ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
+ if (vt == (VT_BYREF | VT_VARIANT)) {
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
+ } else if (vt & VT_BYREF) {
+ if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
+ hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
+ cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
+ }
+ if (SUCCEEDED(hr)) {
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
+ }
+ } else {
+ if (vt == V_VT(&(pvar->realvar))) {
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
+ } else {
+ hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
+ cWIN32OLE_lcid, 0, vt);
+ }
+ }
+ }
+ }
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
+ }
+}
+
+static void
+ole_val2variant2(VALUE val, VARIANT *var)
{
g_nil_to = VT_EMPTY;
ole_val2variant(val, var);
@@ -977,9 +2018,26 @@ ole_val2variant2(val, var)
}
static VALUE
-ole_set_member(self, dispatch)
- VALUE self;
- IDispatch * dispatch;
+make_inspect(const char *class_name, VALUE detail)
+{
+ VALUE str;
+ str = rb_str_new2("#<");
+ rb_str_cat2(str, class_name);
+ rb_str_cat2(str, ":");
+ rb_str_concat(str, detail);
+ rb_str_cat2(str, ">");
+ return str;
+}
+
+static VALUE
+default_inspect(VALUE self, const char *class_name)
+{
+ VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
+ return make_inspect(class_name, detail);
+}
+
+static VALUE
+ole_set_member(VALUE self, IDispatch *dispatch)
{
struct oledata *pole;
Data_Get_Struct(self, struct oledata, pole);
@@ -991,10 +2049,9 @@ ole_set_member(self, dispatch)
return self;
}
-static VALUE fole_s_allocate _((VALUE));
+
static VALUE
-fole_s_allocate(klass)
- VALUE klass;
+fole_s_allocate(VALUE klass)
{
struct oledata *pole;
VALUE obj;
@@ -1005,11 +2062,7 @@ fole_s_allocate(klass)
}
static VALUE
-create_win32ole_object(klass, pDispatch, argc, argv)
- VALUE klass;
- IDispatch *pDispatch;
- int argc;
- VALUE *argv;
+create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv)
{
VALUE obj = fole_s_allocate(klass);
ole_set_member(obj, pDispatch);
@@ -1017,8 +2070,40 @@ create_win32ole_object(klass, pDispatch, argc, argv)
}
static VALUE
-ole_variant2val(pvar)
- VARIANT *pvar;
+ary_new_dim(VALUE myary, long *pid, long *plb, long dim) {
+ long i;
+ VALUE obj = Qnil;
+ VALUE pobj = Qnil;
+ long *ids = ALLOC_N(long, dim);
+ if (!ids) {
+ rb_raise(rb_eRuntimeError, "memory allocation error");
+ }
+ for(i = 0; i < dim; i++) {
+ ids[i] = pid[i] - plb[i];
+ }
+ obj = myary;
+ pobj = myary;
+ for(i = 0; i < dim-1; i++) {
+ obj = rb_ary_entry(pobj, ids[i]);
+ if (obj == Qnil) {
+ rb_ary_store(pobj, ids[i], rb_ary_new());
+ }
+ obj = rb_ary_entry(pobj, ids[i]);
+ pobj = obj;
+ }
+ if (ids) free(ids);
+ return obj;
+}
+
+static void
+ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val) {
+ long id = pid[dim - 1] - plb[dim - 1];
+ VALUE obj = ary_new_dim(myary, pid, plb, dim);
+ rb_ary_store(obj, id, val);
+}
+
+static VALUE
+ole_variant2val(VARIANT *pvar)
{
VALUE obj = Qnil;
HRESULT hr;
@@ -1027,75 +2112,70 @@ ole_variant2val(pvar)
if(V_ISARRAY(pvar)) {
SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar);
- long i;
- long *pID, *pLB, *pUB;
+ UINT i = 0;
+ long *pid, *plb, *pub;
VARIANT variant;
VALUE val;
- VALUE val2;
- int dim = 0;
-
+ UINT dim = 0;
if (!psa) {
return obj;
}
dim = SafeArrayGetDim(psa);
-
VariantInit(&variant);
V_VT(&variant) = (V_VT(pvar) & ~VT_ARRAY) | VT_BYREF;
- pID = ALLOC_N(long, dim);
- pLB = ALLOC_N(long, dim);
- pUB = ALLOC_N(long, dim);
+ pid = ALLOC_N(long, dim);
+ plb = ALLOC_N(long, dim);
+ pub = ALLOC_N(long, dim);
- if(!pID || !pLB || !pUB) {
- if(pID) free(pID);
- if(pLB) free(pLB);
- if(pUB) free(pUB);
+ if(!pid || !plb || !pub) {
+ if(pid) free(pid);
+ if(plb) free(plb);
+ if(pub) free(pub);
rb_raise(rb_eRuntimeError, "memory allocation error");
}
- obj = Qnil;
-
for(i = 0; i < dim; ++i) {
- SafeArrayGetLBound(psa, i+1, &pLB[i]);
- SafeArrayGetLBound(psa, i+1, &pID[i]);
- SafeArrayGetUBound(psa, i+1, &pUB[i]);
+ SafeArrayGetLBound(psa, i+1, &plb[i]);
+ SafeArrayGetLBound(psa, i+1, &pid[i]);
+ SafeArrayGetUBound(psa, i+1, &pub[i]);
}
-
hr = SafeArrayLock(psa);
if (SUCCEEDED(hr)) {
- val2 = rb_ary_new();
- while (i >= 0) {
- hr = SafeArrayPtrOfIndex(psa, pID, &V_BYREF(&variant));
- if (FAILED(hr))
- break;
-
- val = ole_variant2val(&variant);
- rb_ary_push(val2, val);
- for (i = dim-1 ; i >= 0 ; --i) {
- if (++pID[i] <= pUB[i])
+ obj = rb_ary_new();
+ i = 0;
+ while (i < dim) {
+ ary_new_dim(obj, pid, plb, dim);
+ hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
+ if (SUCCEEDED(hr)) {
+ val = ole_variant2val(&variant);
+ ary_store_dim(obj, pid, plb, dim, val);
+ }
+ for (i = 0; i < dim; ++i) {
+ if (++pid[i] <= pub[i])
break;
-
- pID[i] = pLB[i];
- if (i > 0) {
- if (obj == Qnil)
- obj = rb_ary_new();
- rb_ary_push(obj, val2);
- val2 = rb_ary_new();
- }
+ pid[i] = plb[i];
}
}
SafeArrayUnlock(psa);
}
- if(pID) free(pID);
- if(pLB) free(pLB);
- if(pUB) free(pUB);
- return (obj == Qnil) ? val2 : obj;
+ if(pid) free(pid);
+ if(plb) free(plb);
+ if(pub) free(pub);
+ return obj;
}
switch(V_VT(pvar) & ~VT_BYREF){
case VT_EMPTY:
break;
case VT_NULL:
break;
+ case VT_I1:
+ if(V_ISBYREF(pvar))
+ obj = INT2NUM((long)*V_I1REF(pvar));
+ else
+ obj = INT2NUM((long)V_I1(pvar));
+ break;
+
case VT_UI1:
if(V_ISBYREF(pvar))
obj = INT2NUM((long)*V_UI1REF(pvar));
@@ -1110,6 +2190,13 @@ ole_variant2val(pvar)
obj = INT2NUM((long)V_I2(pvar));
break;
+ case VT_UI2:
+ if(V_ISBYREF(pvar))
+ obj = INT2NUM((long)*V_UI2REF(pvar));
+ else
+ obj = INT2NUM((long)V_UI2(pvar));
+ break;
+
case VT_I4:
if(V_ISBYREF(pvar))
obj = INT2NUM((long)*V_I4REF(pvar));
@@ -1117,6 +2204,50 @@ ole_variant2val(pvar)
obj = INT2NUM((long)V_I4(pvar));
break;
+ case VT_UI4:
+ if(V_ISBYREF(pvar))
+ obj = INT2NUM((long)*V_UI4REF(pvar));
+ else
+ obj = INT2NUM((long)V_UI4(pvar));
+ break;
+
+ case VT_INT:
+ if(V_ISBYREF(pvar))
+ obj = INT2NUM((long)*V_INTREF(pvar));
+ else
+ obj = INT2NUM((long)V_INT(pvar));
+ break;
+
+ case VT_UINT:
+ if(V_ISBYREF(pvar))
+ obj = INT2NUM((long)*V_UINTREF(pvar));
+ else
+ obj = INT2NUM((long)V_UINT(pvar));
+ break;
+
+#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
+ case VT_I8:
+ if(V_ISBYREF(pvar))
+#if (_MSC_VER >= 1300)
+ obj = I8_2_NUM(*V_I8REF(pvar));
+#else
+ obj = Qnil;
+#endif
+ else
+ obj = I8_2_NUM(V_I8(pvar));
+ break;
+ case VT_UI8:
+ if(V_ISBYREF(pvar))
+#if (_MSC_VER >= 1300)
+ obj = UI8_2_NUM(*V_UI8REF(pvar));
+#else
+ obj = Qnil;
+#endif
+ else
+ obj = UI8_2_NUM(V_UI8(pvar));
+ break;
+#endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
+
case VT_R4:
if(V_ISBYREF(pvar))
obj = rb_float_new(*V_R4REF(pvar));
@@ -1133,13 +2264,10 @@ ole_variant2val(pvar)
case VT_BSTR:
{
- char *p;
if(V_ISBYREF(pvar))
- p = ole_wc2mb(*V_BSTRREF(pvar));
+ obj = ole_wc2vstr(*V_BSTRREF(pvar), FALSE);
else
- p = ole_wc2mb(V_BSTR(pvar));
- obj = rb_str_new2(p);
- if(p) free(p);
+ obj = ole_wc2vstr(V_BSTR(pvar), FALSE);
break;
}
@@ -1175,10 +2303,10 @@ ole_variant2val(pvar)
case VT_UNKNOWN:
{
-
/* get IDispatch interface from IUnknown interface */
IUnknown *punk;
IDispatch *pDispatch;
+ void *p;
HRESULT hr;
if (V_ISBYREF(pvar))
@@ -1187,9 +2315,9 @@ ole_variant2val(pvar)
punk = V_UNKNOWN(pvar);
if(punk != NULL) {
- hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch,
- (void **)&pDispatch);
+ hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p);
if(SUCCEEDED(hr)) {
+ pDispatch = p;
obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
}
}
@@ -1214,11 +2342,9 @@ ole_variant2val(pvar)
VARIANT variant;
VariantInit(&variant);
hr = VariantChangeTypeEx(&variant, pvar,
- LOCALE_SYSTEM_DEFAULT, 0, VT_BSTR);
+ cWIN32OLE_lcid, 0, VT_BSTR);
if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) {
- char *p = ole_wc2mb(V_BSTR(&variant));
- obj = rb_str_new2(p);
- if(p) free(p);
+ obj = ole_wc2vstr(V_BSTR(&variant), FALSE);
}
VariantClear(&variant);
break;
@@ -1227,30 +2353,23 @@ ole_variant2val(pvar)
return obj;
}
-
-static LONG reg_open_key(hkey, name, phkey)
- HKEY hkey;
- const char *name;
- HKEY *phkey;
+static LONG
+reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
{
return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey);
}
-static LONG reg_open_vkey(hkey, key, phkey)
- HKEY hkey;
- VALUE key;
- HKEY *phkey;
+static LONG
+reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
{
return reg_open_key(hkey, StringValuePtr(key), phkey);
}
static VALUE
-reg_enum_key(hkey, i)
- HKEY hkey;
- DWORD i;
+reg_enum_key(HKEY hkey, DWORD i)
{
char buf[BUFSIZ + 1];
- DWORD size_buf = sizeof(buf) - 1;
+ DWORD size_buf = sizeof(buf);
FILETIME ft;
LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf,
NULL, NULL, NULL, &ft);
@@ -1262,59 +2381,84 @@ reg_enum_key(hkey, i)
}
static VALUE
-reg_get_val(hkey, subkey)
- HKEY hkey;
- const char *subkey;
+reg_get_val(HKEY hkey, const char *subkey)
{
- char buf[BUFSIZ + 1];
- LONG size_buf = sizeof(buf) - 1;
- LONG err = RegQueryValue(hkey, subkey, buf, &size_buf);
+ char *pbuf;
+ DWORD dwtype = 0;
+ LONG size = 0;
+ VALUE val = Qnil;
+ LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size);
+
if (err == ERROR_SUCCESS) {
- buf[BUFSIZ] = '\0';
- return rb_str_new2(buf);
+ pbuf = ALLOC_N(char, size + 1);
+ err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, pbuf, &size);
+ if (err == ERROR_SUCCESS) {
+ pbuf[size] = '\0';
+ val = rb_str_new2(pbuf);
+ }
+ free(pbuf);
}
- return Qnil;
+ return val;
}
static VALUE
-typelib_file_from_clsid(ole)
- VALUE ole;
+reg_get_val2(HKEY hkey, const char *subkey)
+{
+ HKEY hsubkey;
+ LONG err;
+ VALUE val = Qnil;
+ err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey);
+ if (err == ERROR_SUCCESS) {
+ val = reg_get_val(hsubkey, NULL);
+ RegCloseKey(hsubkey);
+ }
+ if (val == Qnil) {
+ val = reg_get_val(hkey, subkey);
+ }
+ return val;
+}
+
+static VALUE
+reg_get_typelib_file_path(HKEY hkey)
+{
+ VALUE path = Qnil;
+ path = reg_get_val2(hkey, "win32");
+ if (path == Qnil) {
+ path = reg_get_val2(hkey, "win16");
+ }
+ return path;
+}
+
+static VALUE
+typelib_file_from_clsid(VALUE ole)
{
- OLECHAR *pbuf;
- CLSID clsid;
- HRESULT hr;
HKEY hroot, hclsid;
LONG err;
VALUE typelib;
- VALUE vclsid;
- char *pclsid = NULL;
+ char path[MAX_PATH + 1];
- pbuf = ole_mb2wc(StringValuePtr(ole), -1);
- hr = CLSIDFromProgID(pbuf, &clsid);
- SysFreeString(pbuf);
- if (FAILED(hr)) {
- return Qnil;
- }
- StringFromCLSID(&clsid, &pbuf);
- vclsid = WC2VSTR(pbuf);
err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot);
if (err != ERROR_SUCCESS) {
return Qnil;
}
- err = reg_open_key(hroot, StringValuePtr(vclsid), &hclsid);
+ err = reg_open_key(hroot, StringValuePtr(ole), &hclsid);
if (err != ERROR_SUCCESS) {
RegCloseKey(hroot);
return Qnil;
}
- typelib = reg_get_val(hclsid, "InprocServer32");
+ typelib = reg_get_val2(hclsid, "InprocServer32");
RegCloseKey(hroot);
RegCloseKey(hclsid);
+ if (typelib != Qnil) {
+ ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path));
+ path[MAX_PATH] = '\0';
+ typelib = rb_str_new2(path);
+ }
return typelib;
}
static VALUE
-typelib_file_from_typelib(ole)
- VALUE ole;
+typelib_file_from_typelib(VALUE ole)
{
HKEY htypelib, hclsid, hversion, hlang;
double fver;
@@ -1344,7 +2488,7 @@ typelib_file_from_typelib(ole)
if (ver == Qnil)
break;
err = reg_open_vkey(hclsid, ver, &hversion);
- if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
+ if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
continue;
fver = atof(StringValuePtr(ver));
typelib = reg_get_val(hversion, NULL);
@@ -1357,7 +2501,7 @@ typelib_file_from_typelib(ole)
break;
err = reg_open_vkey(hversion, lang, &hlang);
if (err == ERROR_SUCCESS) {
- if ((file = reg_get_val(hlang, "win32")) != Qnil)
+ if ((file = reg_get_typelib_file_path(hlang)) != Qnil)
found = TRUE;
RegCloseKey(hlang);
}
@@ -1372,8 +2516,7 @@ typelib_file_from_typelib(ole)
}
static VALUE
-typelib_file(ole)
- VALUE ole;
+typelib_file(VALUE ole)
{
VALUE file = typelib_file_from_clsid(ole);
if (file != Qnil) {
@@ -1383,10 +2526,7 @@ typelib_file(ole)
}
static void
-ole_const_load(pTypeLib, klass, self)
- ITypeLib *pTypeLib;
- VALUE klass;
- VALUE self;
+ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self)
{
unsigned int count;
unsigned int index;
@@ -1449,10 +2589,7 @@ ole_const_load(pTypeLib, klass, self)
}
static HRESULT
-clsid_from_remote(host, com, pclsid)
- VALUE host;
- VALUE com;
- CLSID *pclsid;
+clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid)
{
HKEY hlm;
HKEY hpid;
@@ -1474,7 +2611,7 @@ clsid_from_remote(host, com, pclsid)
hr = HRESULT_FROM_WIN32(err);
else {
len = sizeof(clsid);
- err = RegQueryValueEx(hpid, "", NULL, &dwtype, clsid, &len);
+ err = RegQueryValueEx(hpid, (LPBYTE)"", NULL, &dwtype, clsid, &len);
if (err == ERROR_SUCCESS && dwtype == REG_SZ) {
pbuf = ole_mb2wc(clsid, -1);
hr = CLSIDFromString(pbuf, pclsid);
@@ -1490,10 +2627,7 @@ clsid_from_remote(host, com, pclsid)
}
static VALUE
-ole_create_dcom(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+ole_create_dcom(int argc, VALUE *argv, VALUE self)
{
VALUE ole, host, others;
HRESULT hr;
@@ -1515,7 +2649,7 @@ ole_create_dcom(argc, argv, self)
rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment");
rb_scan_args(argc, argv, "2*", &ole, &host, &others);
- pbuf = ole_mb2wc(StringValuePtr(ole), -1);
+ pbuf = ole_vstr2wc(ole);
hr = CLSIDFromProgID(pbuf, &clsid);
if (FAILED(hr))
hr = clsid_from_remote(host, ole, &clsid);
@@ -1523,17 +2657,17 @@ ole_create_dcom(argc, argv, self)
hr = CLSIDFromString(pbuf, &clsid);
SysFreeString(pbuf);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"unknown OLE server: `%s'",
StringValuePtr(ole));
memset(&serverinfo, 0, sizeof(COSERVERINFO));
- serverinfo.pwszName = ole_mb2wc(StringValuePtr(host), -1);
+ serverinfo.pwszName = ole_vstr2wc(host);
memset(&multi_qi, 0, sizeof(MULTI_QI));
multi_qi.pIID = &IID_IDispatch;
hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi);
SysFreeString(serverinfo.pwszName);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to create DCOM server `%s' in `%s'",
StringValuePtr(ole),
StringValuePtr(host));
@@ -1543,15 +2677,12 @@ ole_create_dcom(argc, argv, self)
}
static VALUE
-ole_bind_obj(moniker, argc, argv, self)
- VALUE moniker;
- int argc;
- VALUE *argv;
- VALUE self;
+ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
{
IBindCtx *pBindCtx;
IMoniker *pMoniker;
IDispatch *pDispatch;
+ void *p;
HRESULT hr;
OLECHAR *pbuf;
ULONG eaten = 0;
@@ -1560,27 +2691,27 @@ ole_bind_obj(moniker, argc, argv, self)
hr = CreateBindCtx(0, &pBindCtx);
if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to create bind context");
}
- pbuf = ole_mb2wc(StringValuePtr(moniker), -1);
+ pbuf = ole_vstr2wc(moniker);
hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker);
SysFreeString(pbuf);
if(FAILED(hr)) {
OLE_RELEASE(pBindCtx);
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to parse display name of moniker `%s'",
StringValuePtr(moniker));
}
hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL,
- &IID_IDispatch,
- (void**)&pDispatch);
+ &IID_IDispatch, &p);
+ pDispatch = p;
OLE_RELEASE(pMoniker);
OLE_RELEASE(pBindCtx);
if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to bind moniker `%s'",
StringValuePtr(moniker));
}
@@ -1597,10 +2728,7 @@ ole_bind_obj(moniker, argc, argv, self)
* WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel.
*/
static VALUE
-fole_s_connect(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_s_connect(int argc, VALUE *argv, VALUE self)
{
VALUE svr_name;
VALUE others;
@@ -1608,6 +2736,7 @@ fole_s_connect(argc, argv, self)
CLSID clsid;
OLECHAR *pBuf;
IDispatch *pDispatch;
+ void *p;
IUnknown *pUnknown;
rb_secure(4);
@@ -1615,13 +2744,14 @@ fole_s_connect(argc, argv, self)
ole_initialize();
rb_scan_args(argc, argv, "1*", &svr_name, &others);
- if (ruby_safe_level > 0 && OBJ_TAINTED(svr_name)) {
+ Check_SafeStr(svr_name);
+ if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
rb_raise(rb_eSecurityError, "Insecure Object Connection - %s",
StringValuePtr(svr_name));
}
/* get CLSID from OLE server name */
- pBuf = ole_mb2wc(StringValuePtr(svr_name), -1);
+ pBuf = ole_vstr2wc(svr_name);
hr = CLSIDFromProgID(pBuf, &clsid);
if(FAILED(hr)) {
hr = CLSIDFromString(pBuf, &clsid);
@@ -1633,14 +2763,14 @@ fole_s_connect(argc, argv, self)
hr = GetActiveObject(&clsid, 0, &pUnknown);
if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"OLE server `%s' not running", StringValuePtr(svr_name));
}
- hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch,
- (void **)&pDispatch);
+ hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p);
+ pDispatch = p;
if(FAILED(hr)) {
OLE_RELEASE(pUnknown);
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to create WIN32OLE server `%s'",
StringValuePtr(svr_name));
}
@@ -1680,10 +2810,7 @@ fole_s_connect(argc, argv, self)
* puts MSO::MsoLineSingle # => 1
*/
static VALUE
-fole_s_const_load(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_s_const_load(int argc, VALUE *argv, VALUE self)
{
VALUE ole;
VALUE klass;
@@ -1694,7 +2821,7 @@ fole_s_const_load(argc, argv, self)
HRESULT hr;
OLECHAR *pBuf;
VALUE file;
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
rb_secure(4);
rb_scan_args(argc, argv, "11", &ole, &klass);
@@ -1729,11 +2856,11 @@ fole_s_const_load(argc, argv, self)
if (file == Qnil) {
file = ole;
}
- pBuf = ole_mb2wc(StringValuePtr(file), -1);
+ pBuf = ole_vstr2wc(file);
hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib);
SysFreeString(pBuf);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to LoadTypeLibEx");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
if(TYPE(klass) != T_NIL) {
ole_const_load(pTypeLib, klass, self);
}
@@ -1749,9 +2876,7 @@ fole_s_const_load(argc, argv, self)
}
static VALUE
-ole_classes_from_typelib(pTypeLib, classes)
- ITypeLib *pTypeLib;
- VALUE classes;
+ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes)
{
long count;
@@ -1783,8 +2908,7 @@ ole_classes_from_typelib(pTypeLib, classes)
}
static ULONG
-reference_count(pole)
- struct oledata * pole;
+reference_count(struct oledata * pole)
{
ULONG n = 0;
if(pole->pDispatch) {
@@ -1803,9 +2927,7 @@ reference_count(pole)
* exists only for debugging WIN32OLE.
*/
static VALUE
-fole_s_reference_count(self, obj)
- VALUE self;
- VALUE obj;
+fole_s_reference_count(VALUE self, VALUE obj)
{
struct oledata * pole;
OLEData_Get_Struct(obj, pole);
@@ -1822,9 +2944,7 @@ fole_s_reference_count(self, obj)
* The return value is reference counter of OLE object.
*/
static VALUE
-fole_s_free(self, obj)
- VALUE self;
- VALUE obj;
+fole_s_free(VALUE self, VALUE obj)
{
ULONG n = 0;
struct oledata * pole;
@@ -1838,9 +2958,7 @@ fole_s_free(self, obj)
}
static HWND
-ole_show_help(helpfile, helpcontext)
- VALUE helpfile;
- VALUE helpcontext;
+ole_show_help(VALUE helpfile, VALUE helpcontext)
{
FNHTMLHELP *pfnHtmlHelp;
HWND hwnd = 0;
@@ -1872,10 +2990,7 @@ ole_show_help(helpfile, helpcontext)
* WIN32OLE.ole_show_help(typeobj)
*/
static VALUE
-fole_s_show_help(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_s_show_help(int argc, VALUE *argv, VALUE self)
{
VALUE target;
VALUE helpcontext;
@@ -1914,41 +3029,47 @@ fole_s_show_help(argc, argv, self)
* WIN32OLE.codepage # => WIN32OLE::CP_ACP
*/
static VALUE
-fole_s_get_code_page(self)
- VALUE self;
+fole_s_get_code_page(VALUE self)
{
return INT2FIX(cWIN32OLE_cp);
}
+static BOOL CALLBACK
+installed_code_page_proc(LPTSTR str) {
+ if (strtoul(str, NULL, 10) == g_cp_to_check) {
+ g_cp_installed = TRUE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL
+code_page_installed(UINT cp)
+{
+ g_cp_installed = FALSE;
+ g_cp_to_check = cp;
+ EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED);
+ return g_cp_installed;
+}
+
/*
* call-seq:
* WIN32OLE.codepage = CP
*
- * Sets current codepage.
+ * Sets current codepage.
+ * The WIN32OLE.codepage is initialized according to
+ * Encoding.default_internal.
+ * If Encoding.default_internal is nil then WIN32OLE.codepage
+ * is initialized according to Encoding.default_external.
+ *
* WIN32OLE.codepage = WIN32OLE::CP_UTF8
+ * WIN32OLE.codepage = 65001
*/
static VALUE
-fole_s_set_code_page(self, vcp)
- VALUE self;
- VALUE vcp;
+fole_s_set_code_page(VALUE self, VALUE vcp)
{
UINT cp = FIX2INT(vcp);
-
- switch(cp) {
- case CP_ACP:
- case CP_OEMCP:
- case CP_MACCP:
- case CP_THREAD_ACP:
- case CP_SYMBOL:
- case CP_UTF7:
- case CP_UTF8:
- cWIN32OLE_cp = cp;
- break;
- default:
- rb_raise(eWIN32OLE_RUNTIME_ERROR, "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");
- break;
- }
-
+ set_ole_codepage(cp);
/*
* Should this method return old codepage?
*/
@@ -1956,9 +3077,131 @@ fole_s_set_code_page(self, vcp)
}
/*
+ * call-seq:
+ * WIN32OLE.locale -> locale id.
+ *
+ * Returns current locale id (lcid). The default locale is
+ * LOCALE_SYSTEM_DEFAULT.
+ *
+ * lcid = WIN32OLE.locale
+ */
+static VALUE
+fole_s_get_locale(VALUE self)
+{
+ return INT2FIX(cWIN32OLE_lcid);
+}
+
+static BOOL
+CALLBACK installed_lcid_proc(LPTSTR str)
+{
+ if (strcmp(str, g_lcid_to_check) == 0) {
+ g_lcid_installed = TRUE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL
+lcid_installed(LCID lcid)
+{
+ g_lcid_installed = FALSE;
+ snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", lcid);
+ EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED);
+ return g_lcid_installed;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE.locale = lcid
+ *
+ * Sets current locale id (lcid).
+ *
+ * WIN32OLE.locale = 1033 # set locale English(U.S)
+ * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
+ *
+ */
+static VALUE
+fole_s_set_locale(VALUE self, VALUE vlcid)
+{
+ LCID lcid = FIX2INT(vlcid);
+ if (lcid_installed(lcid)) {
+ cWIN32OLE_lcid = lcid;
+ } else {
+ switch (lcid) {
+ case LOCALE_SYSTEM_DEFAULT:
+ case LOCALE_USER_DEFAULT:
+ cWIN32OLE_lcid = lcid;
+ break;
+ default:
+ rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid);
+ }
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE.create_guid
+ *
+ * Creates GUID.
+ * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
+ */
+static VALUE
+fole_s_create_guid(VALUE self)
+{
+ GUID guid;
+ HRESULT hr;
+ OLECHAR bstr[80];
+ int len = 0;
+ hr = CoCreateGuid(&guid);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID");
+ }
+ len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
+ if (len == 0) {
+ rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)");
+ }
+ return ole_wc2vstr(bstr, FALSE);
+}
+
+/*
* Document-class: WIN32OLE
*
* <code>WIN32OLE</code> objects represent OLE Automation object in Ruby.
+ *
+ * By using WIN32OLE, you can access OLE server like VBScript.
+ *
+ * Here is sample script.
+ *
+ * require 'win32ole'
+ *
+ * excel = WIN32OLE.new('Excel.Application')
+ * excel.visible = true
+ * workbook = excel.Workbooks.Add();
+ * worksheet = workbook.Worksheets(1);
+ * worksheet.Range("A1:D1").value = ["North","South","East","West"];
+ * worksheet.Range("A2:B2").value = [5.2, 10];
+ * worksheet.Range("C2").value = 8;
+ * worksheet.Range("D2").value = 20;
+ *
+ * range = worksheet.Range("A1:D2");
+ * range.select
+ * chart = workbook.Charts.Add;
+ *
+ * workbook.saved = true;
+ *
+ * excel.ActiveWorkbook.Close(0);
+ * excel.Quit();
+ *
+ * Unfortunately, Win32OLE doesn't support the argument passed by
+ * reference directly.
+ * Instead, Win32OLE provides WIN32OLE::ARGV.
+ * If you want to get the result value of argument passed by reference,
+ * you can use WIN32OLE::ARGV.
+ *
+ * oleobj.method(arg1, arg2, refargv3)
+ * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
+ *
*/
/*
@@ -1975,10 +3218,7 @@ fole_s_set_code_page(self, vcp)
* WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
*/
static VALUE
-fole_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE svr_name;
VALUE host;
@@ -1987,17 +3227,19 @@ fole_initialize(argc, argv, self)
CLSID clsid;
OLECHAR *pBuf;
IDispatch *pDispatch;
-
+ void *p;
rb_secure(4);
rb_call_super(0, 0);
rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
- if (ruby_safe_level > 0 && OBJ_TAINTED(svr_name)) {
+ Check_SafeStr(svr_name);
+ if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
StringValuePtr(svr_name));
}
if (!NIL_P(host)) {
- if (ruby_safe_level > 0 && OBJ_TAINTED(host)) {
+ Check_SafeStr(host);
+ if (rb_safe_level() > 0 && OBJ_TAINTED(host)) {
rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
StringValuePtr(svr_name));
}
@@ -2005,45 +3247,44 @@ fole_initialize(argc, argv, self)
}
/* get CLSID from OLE server name */
- pBuf = ole_mb2wc(StringValuePtr(svr_name), -1);
+ pBuf = ole_vstr2wc(svr_name);
hr = CLSIDFromProgID(pBuf, &clsid);
if(FAILED(hr)) {
hr = CLSIDFromString(pBuf, &clsid);
}
SysFreeString(pBuf);
if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"unknown OLE server: `%s'",
StringValuePtr(svr_name));
}
/* get IDispatch interface */
hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
- &IID_IDispatch, (void**)&pDispatch);
+ &IID_IDispatch, &p);
+ pDispatch = p;
if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to create WIN32OLE object from `%s'",
StringValuePtr(svr_name));
}
-
+
ole_set_member(self, pDispatch);
return self;
}
static VALUE
-hash2named_arg(pair, pOp)
- VALUE pair;
- struct oleparam* pOp;
+hash2named_arg(VALUE pair, struct oleparam* pOp)
{
unsigned int index, i;
VALUE key, value;
index = pOp->dp.cNamedArgs;
- /*-------------------------------------
- the data-type of key must be String
- ---------------------------------------*/
+ /*---------------------------------------------
+ the data-type of key must be String or Symbol
+ -----------------------------------------------*/
key = rb_ary_entry(pair, 0);
- if(TYPE(key) != T_STRING) {
+ if(TYPE(key) != T_STRING && TYPE(key) != T_SYMBOL) {
/* clear name of dispatch parameters */
for(i = 1; i < index + 1; i++) {
SysFreeString(pOp->pNamedArgs[i]);
@@ -2053,11 +3294,14 @@ hash2named_arg(pair, pOp)
VariantClear(&(pOp->dp.rgvarg[i]));
}
/* raise an exception */
- Check_Type(key, T_STRING);
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
+ }
+ if (TYPE(key) == T_SYMBOL) {
+ key = rb_sym_to_s(key);
}
/* pNamedArgs[0] is <method name>, so "index + 1" */
- pOp->pNamedArgs[index + 1] = ole_mb2wc(StringValuePtr(key), -1);
+ pOp->pNamedArgs[index + 1] = ole_vstr2wc(key);
value = rb_ary_entry(pair, 1);
VariantInit(&(pOp->dp.rgvarg[index]));
@@ -2068,9 +3312,7 @@ hash2named_arg(pair, pOp)
}
static VALUE
-set_argv(realargs, beg, end)
- VARIANTARG* realargs;
- unsigned int beg, end;
+set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
{
VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV"));
@@ -2084,13 +3326,9 @@ set_argv(realargs, beg, end)
}
static VALUE
-ole_invoke(argc, argv, self, wFlags)
- int argc;
- VALUE *argv;
- VALUE self;
- USHORT wFlags;
+ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
{
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
struct oledata *pole;
HRESULT hr;
VALUE cmd;
@@ -2111,6 +3349,7 @@ ole_invoke(argc, argv, self, wFlags)
unsigned int cNamedArgs;
int n;
struct oleparam op;
+ struct olevariantdata *pvar;
memset(&excepinfo, 0, sizeof(EXCEPINFO));
VariantInit(&result);
@@ -2121,18 +3360,30 @@ ole_invoke(argc, argv, self, wFlags)
op.dp.cArgs = 0;
rb_scan_args(argc, argv, "1*", &cmd, &paramS);
+ if(TYPE(cmd) != T_STRING && TYPE(cmd) != T_SYMBOL && !is_bracket) {
+ rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
+ }
+ if (TYPE(cmd) == T_SYMBOL) {
+ cmd = rb_sym_to_s(cmd);
+ }
OLEData_Get_Struct(self, pole);
if(!pole->pDispatch) {
rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
}
- wcmdname = ole_mb2wc(StringValuePtr(cmd), -1);
- hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
- &wcmdname, 1, lcid, &DispID);
- SysFreeString(wcmdname);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
- "unknown property or method `%s'",
- StringValuePtr(cmd));
+ if (is_bracket) {
+ DispID = DISPID_VALUE;
+ argc += 1;
+ rb_ary_unshift(paramS, cmd);
+ } else {
+ wcmdname = ole_vstr2wc(cmd);
+ hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
+ &wcmdname, 1, lcid, &DispID);
+ SysFreeString(wcmdname);
+ if(FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError,
+ "unknown property or method: `%s'",
+ StringValuePtr(cmd));
+ }
}
/* pick up last argument of method */
@@ -2149,10 +3400,10 @@ ole_invoke(argc, argv, self, wFlags)
op.dp.cArgs = cNamedArgs + argc - 2;
op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
- rb_iterate(rb_each, param, hash2named_arg, (VALUE)&op);
+ rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op);
pDispID = ALLOCA_N(DISPID, cNamedArgs + 1);
- op.pNamedArgs[0] = ole_mb2wc(StringValuePtr(cmd), -1);
+ op.pNamedArgs[0] = ole_vstr2wc(cmd);
hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch,
&IID_NULL,
op.pNamedArgs,
@@ -2167,7 +3418,7 @@ ole_invoke(argc, argv, self, wFlags)
for(i = 0; i < op.dp.cArgs; i++ ) {
VariantClear(&op.dp.rgvarg[i]);
}
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"failed to get named argument info: `%s'",
StringValuePtr(cmd));
}
@@ -2191,17 +3442,20 @@ ole_invoke(argc, argv, self, wFlags)
VariantInit(&realargs[n]);
VariantInit(&op.dp.rgvarg[n]);
param = rb_ary_entry(paramS, i-cNamedArgs);
-
- ole_val2variant(param, &realargs[n]);
- V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF;
- V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n];
-
+ if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
+ Data_Get_Struct(param, struct olevariantdata, pvar);
+ VariantCopy(&op.dp.rgvarg[n], &(pvar->var));
+ } else {
+ ole_val2variant(param, &realargs[n]);
+ V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF;
+ V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n];
+ }
}
}
/* apparent you need to call propput, you need this */
if (wFlags & DISPATCH_PROPERTYPUT) {
if (op.dp.cArgs == 0)
- return ResultFromScode(E_INVALIDARG);
+ ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error");
op.dp.cNamedArgs = 1;
op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
@@ -2211,6 +3465,7 @@ ole_invoke(argc, argv, self, wFlags)
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
&IID_NULL, lcid, wFlags, &op.dp,
&result, &excepinfo, &argErr);
+
if (FAILED(hr)) {
/* retry to call args by value */
if(op.dp.cArgs >= cNamedArgs) {
@@ -2242,12 +3497,14 @@ ole_invoke(argc, argv, self, wFlags)
&IID_NULL, lcid, wFlags,
&op.dp, NULL,
&excepinfo, &argErr);
+
}
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
n = op.dp.cArgs - i + cNamedArgs - 1;
VariantClear(&op.dp.rgvarg[n]);
}
}
+
if (FAILED(hr)) {
/* retry after converting nil to VT_EMPTY */
if (op.dp.cArgs > cNamedArgs) {
@@ -2275,6 +3532,13 @@ ole_invoke(argc, argv, self, wFlags)
}
/* clear dispatch parameter */
if(op.dp.cArgs > cNamedArgs) {
+ for(i = cNamedArgs; i < op.dp.cArgs; i++) {
+ n = op.dp.cArgs - i + cNamedArgs - 1;
+ param = rb_ary_entry(paramS, i-cNamedArgs);
+ if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
+ ole_val2variant(param, &realargs[n]);
+ }
+ }
set_argv(realargs, cNamedArgs, op.dp.cArgs);
}
else {
@@ -2285,8 +3549,9 @@ ole_invoke(argc, argv, self, wFlags)
if (FAILED(hr)) {
v = ole_excepinfo2msg(&excepinfo);
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "%s%s",
- StringValuePtr(cmd), StringValuePtr(v));
+ ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s",
+ StringValuePtr(cmd),
+ StringValuePtr(v));
}
obj = ole_variant2val(&result);
VariantClear(&result);
@@ -2307,21 +3572,13 @@ ole_invoke(argc, argv, self, wFlags)
*
*/
static VALUE
-fole_invoke(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_invoke(int argc, VALUE *argv, VALUE self)
{
- return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET);
+ return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
}
static VALUE
-ole_invoke2(self, dispid, args, types, dispkind)
- VALUE self;
- VALUE dispid;
- VALUE args;
- VALUE types;
- USHORT dispkind;
+ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
{
HRESULT hr;
struct oledata *pole;
@@ -2344,7 +3601,7 @@ ole_invoke2(self, dispid, args, types, dispkind)
VariantInit(&result);
OLEData_Get_Struct(self, pole);
- dispParams.cArgs = RARRAY(args)->len;
+ dispParams.cArgs = RARRAY_LEN(args);
dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs);
realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs);
for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--)
@@ -2375,7 +3632,7 @@ ole_invoke2(self, dispid, args, types, dispkind)
SAFEARRAYBOUND rgsabound[1];
Check_Type(param, T_ARRAY);
rgsabound[0].lLbound = 0;
- rgsabound[0].cElements = RARRAY(param)->len;
+ rgsabound[0].cElements = RARRAY_LEN(param);
v = vt & ~(VT_ARRAY | VT_BYREF);
V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound);
V_VT(&realargs[i]) = VT_ARRAY | v;
@@ -2393,7 +3650,7 @@ ole_invoke2(self, dispid, args, types, dispkind)
if (v != VT_VARIANT)
{
VariantChangeTypeEx(&velem, &velem,
- LOCALE_SYSTEM_DEFAULT, 0, v);
+ cWIN32OLE_lcid, 0, v);
}
switch (v)
{
@@ -2432,7 +3689,7 @@ ole_invoke2(self, dispid, args, types, dispkind)
if ((vt & (~VT_BYREF)) != VT_VARIANT)
{
hr = VariantChangeTypeEx(&realargs[i], &realargs[i],
- LOCALE_SYSTEM_DEFAULT, 0,
+ cWIN32OLE_lcid, 0,
(VARTYPE)(vt & (~VT_BYREF)));
if (hr != S_OK)
{
@@ -2488,14 +3745,15 @@ ole_invoke2(self, dispid, args, types, dispkind)
}
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid),
- &IID_NULL, LOCALE_SYSTEM_DEFAULT,
+ &IID_NULL, cWIN32OLE_lcid,
dispkind,
&dispParams, &result,
&excepinfo, &argErr);
if (FAILED(hr)) {
v = ole_excepinfo2msg(&excepinfo);
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "_invoke %s",
+ ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s",
+ NUM2INT(dispid),
StringValuePtr(v));
}
@@ -2522,11 +3780,7 @@ ole_invoke2(self, dispid, args, types, dispkind)
* excel._invoke(302, [], []) # same effect as excel.Quit
*/
static VALUE
-fole_invoke2(self, dispid, args, types)
- VALUE self;
- VALUE dispid;
- VALUE args;
- VALUE types;
+fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
{
return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD);
}
@@ -2544,11 +3798,7 @@ fole_invoke2(self, dispid, args, types)
* puts excel._getproperty(558, [], []) # same effect as puts excel.visible
*/
static VALUE
-fole_getproperty2(self, dispid, args, types)
- VALUE self;
- VALUE dispid;
- VALUE args;
- VALUE types;
+fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
{
return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET);
}
@@ -2566,59 +3816,78 @@ fole_getproperty2(self, dispid, args, types)
* excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true
*/
static VALUE
-fole_setproperty2(self, dispid, args, types)
- VALUE self;
- VALUE dispid;
- VALUE args;
- VALUE types;
+fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
{
return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT);
}
/*
* call-seq:
- * WIN32OLE['property']=val
+ * WIN32OLE[a1, a2, ...]=val
+ *
+ * Sets the value to WIN32OLE object specified by a1, a2, ...
+ *
+ * dict = WIN32OLE.new('Scripting.Dictionary')
+ * dict.add('ruby', 'RUBY')
+ * dict['ruby'] = 'Ruby'
+ * puts dict['ruby'] # => 'Ruby'
+ *
+ * Remark: You can not use this method to set the property value.
+ *
+ * excel = WIN32OLE.new('Excel.Application')
+ * # excel['Visible'] = true # This is error !!!
+ * excel.Visible = true # You should to use this style to set the property.
+ *
+ */
+static VALUE
+fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
+{
+ return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE);
+}
+
+/*
+ * call-seq:
* WIN32OLE.setproperty('property', [arg1, arg2,...] val)
*
* Sets property of OLE object.
* When you want to set property with argument, you can use this method.
*
* excel = WIN32OLE.new('Excel.Application')
- * excel['Visible'] = true
+ * excel.Visible = true
* book = excel.workbooks.add
* sheet = book.worksheets(1)
* sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10.
*/
static VALUE
-fole_setproperty(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_setproperty(int argc, VALUE *argv, VALUE self)
{
- return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT);
+ return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE);
}
/*
* call-seq:
- * WIN32OLE['property']
+ * WIN32OLE[a1,a2,...]
*
- * Returns property of OLE object.
+ * Returns the value of Collection specified by a1, a2,....
*
+ * dict = WIN32OLE.new('Scripting.Dictionary')
+ * dict.add('ruby', 'Ruby')
+ * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')')
+ *
+ * Remark: You can not use this method to get the property.
* excel = WIN32OLE.new('Excel.Application')
- * puts excel['Visible'] # => false
+ * # puts excel['Visible'] This is error !!!
+ * puts excel.Visible # You should to use this style to get the property.
+ *
*/
static VALUE
-fole_getproperty(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self)
{
- return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET);
+ return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE);
}
static VALUE
-ole_propertyput(self, property, value)
- VALUE self, property, value;
+ole_propertyput(VALUE self, VALUE property, VALUE value)
{
struct oledata *pole;
unsigned argErr;
@@ -2632,7 +3901,7 @@ ole_propertyput(self, property, value)
VARIANTARG propertyValue[2];
OLECHAR* pBuf[1];
VALUE v;
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
dispParams.rgdispidNamedArgs = &dispIDParam;
dispParams.rgvarg = propertyValue;
dispParams.cNamedArgs = 1;
@@ -2645,14 +3914,14 @@ ole_propertyput(self, property, value)
OLEData_Get_Struct(self, pole);
/* get ID from property name */
- pBuf[0] = ole_mb2wc(StringValuePtr(property), -1);
+ pBuf[0] = ole_vstr2wc(property);
hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL,
pBuf, 1, lcid, &dispID);
SysFreeString(pBuf[0]);
pBuf[0] = NULL;
if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
+ ole_raise(hr, eWIN32OLERuntimeError,
"unknown property or method: `%s'",
StringValuePtr(property));
}
@@ -2667,7 +3936,9 @@ ole_propertyput(self, property, value)
}
if (FAILED(hr)) {
v = ole_excepinfo2msg(&excepinfo);
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, StringValuePtr(v));
+ ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s",
+ StringValuePtr(property),
+ StringValuePtr(v));
}
return Qnil;
}
@@ -2682,8 +3953,7 @@ ole_propertyput(self, property, value)
*
*/
static VALUE
-fole_free(self)
- VALUE self;
+fole_free(VALUE self)
{
struct oledata *pole;
rb_secure(4);
@@ -2694,8 +3964,7 @@ fole_free(self)
}
static VALUE
-ole_each_sub(pEnumV)
- VALUE pEnumV;
+ole_each_sub(VALUE pEnumV)
{
VARIANT variant;
VALUE obj = Qnil;
@@ -2711,8 +3980,7 @@ ole_each_sub(pEnumV)
}
static VALUE
-ole_ienum_free(pEnumV)
- VALUE pEnumV;
+ole_ienum_free(VALUE pEnumV)
{
IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
OLE_RELEASE(pEnum);
@@ -2734,10 +4002,9 @@ ole_ienum_free(pEnumV)
* end
*/
static VALUE
-fole_each(self)
- VALUE self;
+fole_each(VALUE self)
{
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
struct oledata *pole;
@@ -2747,6 +4014,9 @@ fole_each(self)
VARIANT result;
HRESULT hr;
IEnumVARIANT *pEnum = NULL;
+ void *p;
+
+ RETURN_ENUMERATOR(self, 0, 0);
VariantInit(&result);
dispParams.rgvarg = NULL;
@@ -2764,17 +4034,20 @@ fole_each(self)
if (FAILED(hr)) {
VariantClear(&result);
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to get IEnum Interface");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface");
}
- if (V_VT(&result) == VT_UNKNOWN)
+ if (V_VT(&result) == VT_UNKNOWN) {
hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result),
&IID_IEnumVARIANT,
- (void**)&pEnum);
- else if (V_VT(&result) == VT_DISPATCH)
+ &p);
+ pEnum = p;
+ } else if (V_VT(&result) == VT_DISPATCH) {
hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result),
&IID_IEnumVARIANT,
- (void**)&pEnum);
+ &p);
+ pEnum = p;
+ }
if (FAILED(hr) || !pEnum) {
VariantClear(&result);
ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface");
@@ -2792,13 +4065,10 @@ fole_each(self)
* Calls WIN32OLE#invoke method.
*/
static VALUE
-fole_missing(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fole_missing(int argc, VALUE *argv, VALUE self)
{
ID id;
- char* mname;
+ const char* mname;
int n;
id = rb_to_id(argv[0]);
mname = rb_id2name(id);
@@ -2807,22 +4077,18 @@ fole_missing(argc, argv, self)
}
n = strlen(mname);
if(mname[n-1] == '=') {
- argv[0] = rb_str_new(mname, n-1);
+ argv[0] = rb_enc_str_new(mname, n-1, cWIN32OLE_enc);
return ole_propertyput(self, argv[0], argv[1]);
}
else {
- argv[0] = rb_str_new2(mname);
- return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET);
+ argv[0] = rb_enc_str_new(mname, n, cWIN32OLE_enc);
+ return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
}
}
static VALUE
-ole_method_sub(self, pOwnerTypeInfo, pTypeInfo, name)
- VALUE self;
- ITypeInfo *pOwnerTypeInfo;
- ITypeInfo *pTypeInfo;
- VALUE name;
+ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -2833,7 +4099,7 @@ ole_method_sub(self, pOwnerTypeInfo, pTypeInfo, name)
VALUE method = Qnil;
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
}
for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) {
hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
@@ -2859,10 +4125,7 @@ ole_method_sub(self, pOwnerTypeInfo, pTypeInfo, name)
}
static VALUE
-olemethod_from_typeinfo(self, pTypeInfo, name)
- VALUE self;
- ITypeInfo *pTypeInfo;
- VALUE name;
+olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -2872,7 +4135,7 @@ olemethod_from_typeinfo(self, pTypeInfo, name)
VALUE method = Qnil;
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
}
method = ole_method_sub(self, 0, pTypeInfo, name);
if (method != Qnil) {
@@ -2893,11 +4156,7 @@ olemethod_from_typeinfo(self, pTypeInfo, name)
}
static VALUE
-ole_methods_sub(pOwnerTypeInfo, pTypeInfo, methods, mask)
- ITypeInfo *pOwnerTypeInfo;
- ITypeInfo *pTypeInfo;
- VALUE methods;
- int mask;
+ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -2908,7 +4167,7 @@ ole_methods_sub(pOwnerTypeInfo, pTypeInfo, methods, mask)
WORD i;
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
}
for(i = 0; i < pTypeAttr->cFuncs; i++) {
pstr = NULL;
@@ -2937,9 +4196,7 @@ ole_methods_sub(pOwnerTypeInfo, pTypeInfo, methods, mask)
}
static VALUE
-ole_methods_from_typeinfo(pTypeInfo, mask)
- ITypeInfo *pTypeInfo;
- int mask;
+ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -2949,7 +4206,7 @@ ole_methods_from_typeinfo(pTypeInfo, mask)
VALUE methods = rb_ary_new();
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
}
ole_methods_sub(0, pTypeInfo, methods, mask);
@@ -2968,9 +4225,7 @@ ole_methods_from_typeinfo(pTypeInfo, mask)
}
static HRESULT
-typeinfo_from_ole(pole, ppti)
- struct oledata *pole;
- ITypeInfo **ppti;
+typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti)
{
ITypeInfo *pTypeInfo;
ITypeLib *pTypeLib;
@@ -2978,7 +4233,7 @@ typeinfo_from_ole(pole, ppti)
VALUE type;
UINT i;
UINT count;
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
0, lcid, &pTypeInfo);
if(FAILED(hr)) {
@@ -3011,9 +4266,7 @@ typeinfo_from_ole(pole, ppti)
}
static VALUE
-ole_methods(self,mask)
- VALUE self;
- int mask;
+ole_methods(VALUE self, int mask)
{
ITypeInfo *pTypeInfo;
HRESULT hr;
@@ -3043,8 +4296,7 @@ ole_methods(self,mask)
*
*/
static VALUE
-fole_methods( self )
- VALUE self;
+fole_methods(VALUE self)
{
return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
}
@@ -3060,8 +4312,7 @@ fole_methods( self )
* properties = excel.ole_get_methods
*/
static VALUE
-fole_get_methods( self )
- VALUE self;
+fole_get_methods(VALUE self)
{
return ole_methods( self, INVOKE_PROPERTYGET);
}
@@ -3077,10 +4328,9 @@ fole_get_methods( self )
* properties = excel.ole_put_methods
*/
static VALUE
-fole_put_methods( self )
- VALUE self;
+fole_put_methods(VALUE self)
{
- return ole_methods( self, INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
+ return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF);
}
/*
@@ -3088,39 +4338,58 @@ fole_put_methods( self )
* WIN32OLE#ole_func_methods
*
* Returns the array of WIN32OLE_METHOD object .
- * The element of the array is functional method of WIN32OLE object.
+ * The element of the array is property (settable) of WIN32OLE object.
*
* excel = WIN32OLE.new('Excel.Application')
* properties = excel.ole_func_methods
*
*/
static VALUE
-fole_func_methods( self )
- VALUE self;
+fole_func_methods(VALUE self)
{
return ole_methods( self, INVOKE_FUNC);
}
+static VALUE
+ole_type_from_itypeinfo(ITypeInfo *pTypeInfo)
+{
+ ITypeLib *pTypeLib;
+ VALUE type = Qnil;
+ HRESULT hr;
+ unsigned int index;
+ BSTR bstr;
+
+ hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index );
+ if(FAILED(hr)) {
+ return Qnil;
+ }
+ hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index,
+ &bstr, NULL, NULL, NULL);
+ OLE_RELEASE(pTypeLib);
+ if (FAILED(hr)) {
+ return Qnil;
+ }
+ type = foletype_s_allocate(cWIN32OLE_TYPE);
+ oletype_set_member(type, pTypeInfo, WC2VSTR(bstr));
+ return type;
+}
+
/*
* call-seq:
- * WIN32OLE#ole_obj_help
+ * WIN32OLE#ole_type
*
* Returns WIN32OLE_TYPE object.
*
* excel = WIN32OLE.new('Excel.Application')
- * tobj = excel.ole_obj_help
+ * tobj = excel.ole_type
*/
static VALUE
-fole_obj_help( self )
- VALUE self;
+fole_type(VALUE self)
{
- unsigned int index;
ITypeInfo *pTypeInfo;
- ITypeLib *pTypeLib;
HRESULT hr;
struct oledata *pole;
- BSTR bstr;
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
VALUE type = Qnil;
OLEData_Get_Struct(self, pole);
@@ -3129,30 +4398,182 @@ fole_obj_help( self )
if(FAILED(hr)) {
ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
}
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index );
- if(FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib");
+ type = ole_type_from_itypeinfo(pTypeInfo);
+ OLE_RELEASE(pTypeInfo);
+ if (type == Qnil) {
+ rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo");
}
- hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index,
- &bstr, NULL, NULL, NULL);
- if (SUCCEEDED(hr)) {
- type = foletype_s_allocate(cWIN32OLE_TYPE);
- oletype_set_member(type, pTypeInfo, WC2VSTR(bstr));
+ return type;
+}
+
+static VALUE
+make_oletypelib_obj(VALUE guid, VALUE major_version, VALUE minor_version)
+{
+ VALUE args = rb_ary_new();
+ rb_ary_push(args, guid);
+ rb_ary_push(args, major_version);
+ rb_ary_push(args, minor_version);
+ return rb_apply(cWIN32OLE_TYPELIB, rb_intern("new"), args);
+}
+
+static VALUE
+ole_typelib_from_itypelib(ITypeLib *pTypeLib)
+{
+ TLIBATTR *pTLibAttr;
+ OLECHAR bstr[80];
+ VALUE guid = Qnil;
+ VALUE major;
+ VALUE minor;
+ int len = 0;
+ HRESULT hr = S_OK;
+ hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, &pTLibAttr);
+ if (FAILED(hr)) {
+ return Qnil;
}
+ len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
+ if (len > 3) {
+ guid = ole_wc2vstr(bstr, FALSE);
+ }
+ major = INT2NUM(pTLibAttr->wMajorVerNum);
+ minor = INT2NUM(pTLibAttr->wMinorVerNum);
+ pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
+ if (guid == Qnil) {
+ return Qnil;
+ }
+ return make_oletypelib_obj(guid, major, minor);
+}
+
+
+static VALUE
+ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
+{
+ HRESULT hr;
+ ITypeLib *pTypeLib;
+ unsigned int index;
+ VALUE retval = Qnil;
+
+ hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
+ if(FAILED(hr)) {
+ return Qnil;
+ }
+ retval = ole_typelib_from_itypelib(pTypeLib);
OLE_RELEASE(pTypeLib);
+ return retval;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object
+ *
+ * Returns the WIN32OLE_TYPELIB object. The object represents the
+ * type library which contains the WIN32OLE object.
+ *
+ * excel = WIN32OLE.new('Excel.Application')
+ * tlib = excel.ole_typelib
+ * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library'
+ */
+static VALUE
+fole_typelib(VALUE self)
+{
+ struct oledata *pole;
+ HRESULT hr;
+ ITypeInfo *pTypeInfo;
+ LCID lcid = cWIN32OLE_lcid;
+ VALUE vtlib = Qnil;
+
+ OLEData_Get_Struct(self, pole);
+ hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
+ 0, lcid, &pTypeInfo);
+ if(FAILED(hr)) {
+ ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
+ }
+ vtlib = ole_typelib_from_itypeinfo(pTypeInfo);
OLE_RELEASE(pTypeInfo);
+ if (vtlib == Qnil) {
+ rb_raise(rb_eRuntimeError, "failed to get type library info.");
+ }
+ return vtlib;
+}
- return type;
+/*
+ * call-seq:
+ * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object
+ *
+ * Returns WIN32OLE object for a specific dispatch or dual
+ * interface specified by iid.
+ *
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp
+ */
+static VALUE
+fole_query_interface(VALUE self, VALUE str_iid)
+{
+ HRESULT hr;
+ OLECHAR *pBuf;
+ IID iid;
+ struct oledata *pole;
+ IDispatch *pDispatch;
+ void *p;
+
+ pBuf = ole_vstr2wc(str_iid);
+ hr = CLSIDFromString(pBuf, &iid);
+ SysFreeString(pBuf);
+ if(FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError,
+ "invalid iid: `%s'",
+ StringValuePtr(str_iid));
+ }
+
+ OLEData_Get_Struct(self, pole);
+ if(!pole->pDispatch) {
+ rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
+ }
+
+ hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid,
+ &p);
+ if(FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError,
+ "failed to get interface `%s'",
+ StringValuePtr(str_iid));
+ }
+
+ pDispatch = p;
+ return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE#ole_respond_to?(method) -> true or false
+ *
+ * Returns true when OLE object has OLE method, otherwise returns false.
+ *
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ie.ole_respond_to?("gohome") => true
+ */
+static VALUE
+fole_respond_to(VALUE self, VALUE method)
+{
+ struct oledata *pole;
+ BSTR wcmdname;
+ DISPID DispID;
+ HRESULT hr;
+ rb_secure(4);
+ if(TYPE(method) != T_STRING && TYPE(method) != T_SYMBOL) {
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
+ }
+ if (TYPE(method) == T_SYMBOL) {
+ method = rb_sym_to_s(method);
+ }
+ OLEData_Get_Struct(self, pole);
+ wcmdname = ole_vstr2wc(method);
+ hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
+ &wcmdname, 1, cWIN32OLE_lcid, &DispID);
+ SysFreeString(wcmdname);
+ return SUCCEEDED(hr) ? Qtrue : Qfalse;
}
static HRESULT
-ole_docinfo_from_type(pTypeInfo, name, helpstr, helpcontext, helpfile)
- ITypeInfo *pTypeInfo;
- BSTR *name;
- BSTR *helpstr;
- DWORD *helpcontext;
- BSTR *helpfile;
+ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
{
HRESULT hr;
ITypeLib *pTypeLib;
@@ -3175,10 +4596,7 @@ ole_docinfo_from_type(pTypeInfo, name, helpstr, helpcontext, helpfile)
}
static VALUE
-ole_usertype2val(pTypeInfo, pTypeDesc, typedetails)
- ITypeInfo *pTypeInfo;
- TYPEDESC *pTypeDesc;
- VALUE typedetails;
+ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
{
HRESULT hr;
BSTR bstr;
@@ -3202,146 +4620,132 @@ ole_usertype2val(pTypeInfo, pTypeDesc, typedetails)
return type;
}
-static VALUE ole_typedesc2val();
static VALUE
-ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails)
- ITypeInfo *pTypeInfo;
- TYPEDESC *pTypeDesc;
- VALUE typedetails;
+ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
{
TYPEDESC *p = pTypeDesc;
VALUE type = rb_str_new2("");
- while(p->vt == VT_PTR || p->vt == VT_SAFEARRAY) {
+
+ if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) {
p = V_UNION1(p, lptdesc);
- if(strlen(StringValuePtr(type)) == 0) {
- type = ole_typedesc2val(pTypeInfo, p, typedetails);
- } else {
- rb_str_cat(type, ",", 1);
- rb_str_concat(type, ole_typedesc2val(pTypeInfo, p, typedetails));
- }
+ type = ole_typedesc2val(pTypeInfo, p, typedetails);
}
return type;
}
static VALUE
-ole_typedesc2val(pTypeInfo, pTypeDesc, typedetails)
- ITypeInfo *pTypeInfo;
- TYPEDESC *pTypeDesc;
- VALUE typedetails;
+ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
{
VALUE str;
+ VALUE typestr = Qnil;
switch(pTypeDesc->vt) {
case VT_I2:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("I2"));
- return rb_str_new2("I2");
+ typestr = rb_str_new2("I2");
+ break;
case VT_I4:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("I4"));
- return rb_str_new2("I4");
+ typestr = rb_str_new2("I4");
+ break;
case VT_R4:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("R4"));
- return rb_str_new2("R4");
+ typestr = rb_str_new2("R4");
+ break;
case VT_R8:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("R8"));
- return rb_str_new2("R8");
+ typestr = rb_str_new2("R8");
+ break;
case VT_CY:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("CY"));
- return rb_str_new2("CY");
+ typestr = rb_str_new2("CY");
+ break;
case VT_DATE:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("DATE"));
- return rb_str_new2("DATE");
+ typestr = rb_str_new2("DATE");
+ break;
case VT_BSTR:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("BSTR"));
- return rb_str_new2("BSTR");
+ typestr = rb_str_new2("BSTR");
+ break;
case VT_BOOL:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("BOOL"));
- return rb_str_new2("BOOL");
+ typestr = rb_str_new2("BOOL");
+ break;
case VT_VARIANT:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("VARIANT"));
- return rb_str_new2("VARIANT");
+ typestr = rb_str_new2("VARIANT");
+ break;
case VT_DECIMAL:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("DECIMAL"));
- return rb_str_new2("DECIMAL");
+ typestr = rb_str_new2("DECIMAL");
+ break;
case VT_I1:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("I1"));
- return rb_str_new2("I1");
+ typestr = rb_str_new2("I1");
+ break;
case VT_UI1:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("UI1"));
- return rb_str_new2("UI1");
+ typestr = rb_str_new2("UI1");
+ break;
case VT_UI2:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("UI2"));
- return rb_str_new2("UI2");
+ typestr = rb_str_new2("UI2");
+ break;
case VT_UI4:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("UI4"));
- return rb_str_new2("UI4");
+ typestr = rb_str_new2("UI4");
+ break;
+#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
case VT_I8:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("I8"));
- return rb_str_new2("I8");
+ typestr = rb_str_new2("I8");
+ break;
case VT_UI8:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("UI8"));
- return rb_str_new2("UI8");
+ typestr = rb_str_new2("UI8");
+ break;
+#endif
case VT_INT:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("INT"));
- return rb_str_new2("INT");
+ typestr = rb_str_new2("INT");
+ break;
case VT_UINT:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("UINT"));
- return rb_str_new2("UINT");
+ typestr = rb_str_new2("UINT");
+ break;
case VT_VOID:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("VOID"));
- return rb_str_new2("VOID");
+ typestr = rb_str_new2("VOID");
+ break;
case VT_HRESULT:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("HRESULT"));
- return rb_str_new2("HRESULT");
+ typestr = rb_str_new2("HRESULT");
+ break;
case VT_PTR:
+ typestr = rb_str_new2("PTR");
if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("PTR"));
+ rb_ary_push(typedetails, typestr);
return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
case VT_SAFEARRAY:
+ typestr = rb_str_new2("SAFEARRAY");
if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("SAFEARRAY"));
+ rb_ary_push(typedetails, typestr);
return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
case VT_CARRAY:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("CARRAY"));
- return rb_str_new2("CARRAY");
+ typestr = rb_str_new2("CARRAY");
+ break;
case VT_USERDEFINED:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("USERDEFINED"));
+ typestr = rb_str_new2("USERDEFINED");
+ if (typedetails != Qnil)
+ rb_ary_push(typedetails, typestr);
str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails);
if (str != Qnil) {
return str;
}
- return rb_str_new2("USERDEFINED");
+ return typestr;
case VT_UNKNOWN:
- return rb_str_new2("UNKNOWN");
+ typestr = rb_str_new2("UNKNOWN");
+ break;
case VT_DISPATCH:
- if(typedetails != Qnil)
- rb_ary_push(typedetails, rb_str_new2("DISPATCH"));
- return rb_str_new2("DISPATCH");
+ typestr = rb_str_new2("DISPATCH");
+ break;
+ case VT_ERROR:
+ typestr = rb_str_new2("ERROR");
+ break;
+ case VT_LPWSTR:
+ typestr = rb_str_new2("LPWSTR");
+ break;
+ case VT_LPSTR:
+ typestr = rb_str_new2("LPSTR");
+ break;
default:
- str = rb_str_new2("Unknown Type ");
- rb_str_concat(str, rb_fix2str(INT2FIX(pTypeDesc->vt), 10));
- return str;
+ typestr = rb_str_new2("Unknown Type ");
+ rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10));
+ break;
}
+ if (typedetails != Qnil)
+ rb_ary_push(typedetails, typestr);
+ return typestr;
}
/*
@@ -3356,15 +4760,12 @@ ole_typedesc2val(pTypeInfo, pTypeDesc, typedetails)
*
*/
static VALUE
-fole_method_help( self, cmdname )
- VALUE self;
- VALUE cmdname;
+fole_method_help(VALUE self, VALUE cmdname)
{
ITypeInfo *pTypeInfo;
HRESULT hr;
struct oledata *pole;
VALUE method, obj;
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
Check_SafeStr(cmdname);
OLEData_Get_Struct(self, pole);
@@ -3375,45 +4776,78 @@ fole_method_help( self, cmdname )
obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname);
OLE_RELEASE(pTypeInfo);
if (obj == Qnil)
- rb_raise(eWIN32OLE_RUNTIME_ERROR, "not found %s",
+ rb_raise(eWIN32OLERuntimeError, "not found %s",
StringValuePtr(cmdname));
return obj;
}
/*
+ * call-seq:
+ * WIN32OLE#ole_activex_initialize() -> Qnil
+ *
+ * Initialize WIN32OLE object(ActiveX Control) by calling
+ * IPersistMemory::InitNew.
+ *
+ * Before calling OLE method, some kind of the ActiveX controls
+ * created with MFC should be initialized by calling
+ * IPersistXXX::InitNew.
+ *
+ * If and only if you received the exception "HRESULT error code:
+ * 0x8000ffff catastrophic failure", try this method before
+ * invoking any ole_method.
+ *
+ * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control")
+ * obj.ole_activex_initialize
+ * obj.method(...)
+ *
+ */
+static VALUE
+fole_activex_initialize(VALUE self)
+{
+ struct oledata *pole;
+ IPersistMemory *pPersistMemory;
+ void *p;
+
+ HRESULT hr = S_OK;
+
+ OLEData_Get_Struct(self, pole);
+
+ hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p);
+ pPersistMemory = p;
+ if (SUCCEEDED(hr)) {
+ hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory);
+ OLE_RELEASE(pPersistMemory);
+ if (SUCCEEDED(hr)) {
+ return Qnil;
+ }
+ }
+
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control");
+ }
+
+ return Qnil;
+}
+
+/*
* call-seq:
* WIN32OLE_TYPE.ole_classes(typelib)
*
* Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library.
+ * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead.
*/
static VALUE
-foletype_s_ole_classes(self, typelib)
- VALUE self;
- VALUE typelib;
+foletype_s_ole_classes(VALUE self, VALUE typelib)
{
- VALUE file, classes;
- OLECHAR * pbuf;
- ITypeLib *pTypeLib;
- HRESULT hr;
+ VALUE obj;
- rb_secure(4);
- classes = rb_ary_new();
- if(TYPE(typelib) == T_STRING) {
- file = typelib_file(typelib);
- if (file == Qnil) {
- file = typelib;
- }
- pbuf = ole_mb2wc(StringValuePtr(file), -1);
- hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to LoadTypeLibEx");
- SysFreeString(pbuf);
- ole_classes_from_typelib(pTypeLib, classes);
- OLE_RELEASE(pTypeLib);
- } else {
- rb_raise(rb_eTypeError, "1st argument should be TypeLib string");
- }
- return classes;
+ /*
+ rb_warn("%s is obsolete; use %s instead.",
+ "WIN32OLE_TYPE.ole_classes",
+ "WIN32OLE_TYPELIB.new(typelib).ole_types");
+ */
+ obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib);
+ return rb_funcall(obj, rb_intern("ole_types"), 0);
}
/*
@@ -3421,48 +4855,18 @@ foletype_s_ole_classes(self, typelib)
* WIN32OLE_TYPE.typelibs
*
* Returns array of type libraries.
+ * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead.
*
*/
static VALUE
-foletype_s_typelibs(self)
- VALUE self;
+foletype_s_typelibs(VALUE self)
{
- HKEY htypelib, hclsid;
- double fversion;
- DWORD i, j;
- LONG err;
- VALUE clsid;
- VALUE ver;
- VALUE v = Qnil;
- VALUE typelibs = rb_ary_new();
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
- if(err != ERROR_SUCCESS) {
- return typelibs;
- }
- for(i = 0; ; i++) {
- clsid = reg_enum_key(htypelib, i);
- if (clsid == Qnil)
- break;
- err = reg_open_vkey(htypelib, clsid, &hclsid);
- if (err != ERROR_SUCCESS)
- continue;
- fversion = 0;
- for(j = 0; ; j++) {
- ver = reg_enum_key(hclsid, j);
- if (ver == Qnil)
- break;
- if (fversion > atof(StringValuePtr(ver)))
- continue;
- fversion = atof(StringValuePtr(ver));
- if ( (v = reg_get_val(hclsid, StringValuePtr(ver))) != Qnil ) {
- rb_ary_push(typelibs, v);
- }
- }
- RegCloseKey(hclsid);
- }
- RegCloseKey(htypelib);
- return typelibs;
+ /*
+ rb_warn("%s is obsolete. use %s instead.",
+ "WIN32OLE_TYPE.typelibs",
+ "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}");
+ */
+ return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}");
}
/*
@@ -3472,8 +4876,7 @@ foletype_s_typelibs(self)
* Returns array of ProgID.
*/
static VALUE
-foletype_s_progids(self)
- VALUE self;
+foletype_s_progids(VALUE self)
{
HKEY hclsids, hclsid;
DWORD i;
@@ -3493,9 +4896,9 @@ foletype_s_progids(self)
err = reg_open_vkey(hclsids, clsid, &hclsid);
if (err != ERROR_SUCCESS)
continue;
- if ((v = reg_get_val(hclsid, "ProgID")) != Qnil)
+ if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil)
rb_ary_push(progids, v);
- if ((v = reg_get_val(hclsid, "VersionIndependentProgID")) != Qnil)
+ if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil)
rb_ary_push(progids, v);
RegCloseKey(hclsid);
}
@@ -3504,8 +4907,7 @@ foletype_s_progids(self)
}
static VALUE
-foletype_s_allocate(klass)
- VALUE klass;
+foletype_s_allocate(VALUE klass)
{
struct oletypedata *poletype;
VALUE obj;
@@ -3516,10 +4918,7 @@ foletype_s_allocate(klass)
}
static VALUE
-oletype_set_member(self, pTypeInfo, name)
- VALUE self;
- ITypeInfo *pTypeInfo;
- VALUE name;
+oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3530,10 +4929,7 @@ oletype_set_member(self, pTypeInfo, name)
}
static VALUE
-oleclass_from_typelib(self, pTypeLib, oleclass)
- VALUE self;
- ITypeLib *pTypeLib;
- VALUE oleclass;
+oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
{
long count;
@@ -3565,6 +4961,528 @@ oleclass_from_typelib(self, pTypeLib, oleclass)
}
/*
+ * Document-class: WIN32OLE_TYPELIB
+ *
+ * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information.
+ */
+
+
+static VALUE
+oletypelib_set_member(VALUE self, VALUE typelib, VALUE guid, VALUE version)
+{
+ rb_ivar_set(self, rb_intern("name"), typelib);
+ rb_ivar_set(self, rb_intern("guid"), guid);
+ rb_ivar_set(self, rb_intern("version"), version);
+ return self;
+}
+
+/*
+ * call-seq:
+ *
+ * WIN32OLE_TYPELIB.typelibs
+ *
+ * Returns the array of WIN32OLE_TYPELIB object.
+ *
+ * tlibs = WIN32OLE_TYPELIB.typelibs
+ *
+ */
+static VALUE
+foletypelib_s_typelibs(VALUE self)
+{
+ HKEY htypelib, hguid;
+ DWORD i, j;
+ LONG err;
+ VALUE guid;
+ VALUE version;
+ VALUE name = Qnil;
+ VALUE typelibs = rb_ary_new();
+ VALUE typelib = Qnil;
+
+ err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
+ if(err != ERROR_SUCCESS) {
+ return typelibs;
+ }
+ for(i = 0; ; i++) {
+ guid = reg_enum_key(htypelib, i);
+ if (guid == Qnil)
+ break;
+ err = reg_open_vkey(htypelib, guid, &hguid);
+ if (err != ERROR_SUCCESS)
+ continue;
+ for(j = 0; ; j++) {
+ version = reg_enum_key(hguid, j);
+ if (version == Qnil)
+ break;
+ if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) {
+ typelib = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0);
+ oletypelib_set_member(typelib, name, guid, version);
+ rb_ary_push(typelibs, typelib);
+ }
+ }
+ RegCloseKey(hguid);
+ }
+ RegCloseKey(htypelib);
+ return typelibs;
+}
+
+static VALUE
+make_version_str(VALUE major, VALUE minor)
+{
+ VALUE version_str = Qnil;
+ VALUE minor_str = Qnil;
+ if (major == Qnil) {
+ return Qnil;
+ }
+ version_str = rb_String(major);
+ if (minor != Qnil) {
+ minor_str = rb_String(minor);
+ rb_str_cat2(version_str, ".");
+ rb_str_append(version_str, minor_str);
+ }
+ return version_str;
+}
+
+static VALUE
+oletypelib_search_registry2(VALUE self, VALUE args)
+{
+ HKEY htypelib, hguid, hversion;
+ double fver;
+ DWORD j;
+ LONG err;
+ VALUE found = Qfalse;
+ VALUE tlib;
+ VALUE ver;
+ VALUE version_str;
+ VALUE version = Qnil;
+ VALUE typelib = Qnil;
+
+ VALUE guid = rb_ary_entry(args, 0);
+ version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2));
+
+ err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
+ if(err != ERROR_SUCCESS) {
+ return Qfalse;
+ }
+ err = reg_open_vkey(htypelib, guid, &hguid);
+ if (err != ERROR_SUCCESS) {
+ RegCloseKey(htypelib);
+ return Qfalse;
+ }
+ if (version_str != Qnil) {
+ err = reg_open_vkey(hguid, version_str, &hversion);
+ if (err == ERROR_SUCCESS) {
+ tlib = reg_get_val(hversion, NULL);
+ if (tlib != Qnil) {
+ typelib = tlib;
+ version = version_str;
+ }
+ }
+ RegCloseKey(hversion);
+ } else {
+ fver = 0.0;
+ for(j = 0; ;j++) {
+ ver = reg_enum_key(hguid, j);
+ if (ver == Qnil)
+ break;
+ err = reg_open_vkey(hguid, ver, &hversion);
+ if (err != ERROR_SUCCESS)
+ continue;
+ tlib = reg_get_val(hversion, NULL);
+ if (tlib == Qnil) {
+ RegCloseKey(hversion);
+ continue;
+ }
+ if (fver < atof(StringValuePtr(ver))) {
+ fver = atof(StringValuePtr(ver));
+ version = ver;
+ typelib = tlib;
+ }
+ RegCloseKey(hversion);
+ }
+ }
+ RegCloseKey(hguid);
+ RegCloseKey(htypelib);
+ if (typelib != Qnil) {
+ found = Qtrue;
+ oletypelib_set_member(self, typelib, guid, version);
+ }
+ return found;
+}
+
+static VALUE
+oletypelib_search_registry(VALUE self, VALUE typelib)
+{
+ HKEY htypelib, hguid, hversion;
+ DWORD i, j;
+ LONG err;
+ VALUE found = Qfalse;
+ VALUE tlib;
+ VALUE guid;
+ VALUE ver;
+
+ err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
+ if(err != ERROR_SUCCESS) {
+ return Qfalse;
+ }
+ for(i = 0; !found; i++) {
+ guid = reg_enum_key(htypelib, i);
+ if (guid == Qnil)
+ break;
+ err = reg_open_vkey(htypelib, guid, &hguid);
+ if (err != ERROR_SUCCESS)
+ continue;
+ for(j = 0; found == Qfalse; j++) {
+ ver = reg_enum_key(hguid, j);
+ if (ver == Qnil)
+ break;
+ err = reg_open_vkey(hguid, ver, &hversion);
+ if (err != ERROR_SUCCESS)
+ continue;
+ tlib = reg_get_val(hversion, NULL);
+ if (tlib == Qnil) {
+ RegCloseKey(hversion);
+ continue;
+ }
+ if (rb_str_cmp(typelib, tlib) == 0) {
+ oletypelib_set_member(self, typelib, guid, ver);
+ found = Qtrue;
+ }
+ RegCloseKey(hversion);
+ }
+ RegCloseKey(hguid);
+ }
+ RegCloseKey(htypelib);
+ return found;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object
+ *
+ * Returns a new WIN32OLE_TYPELIB object.
+ *
+ * The first argument <i>typelib</i> specifies OLE type library name or GUID or
+ * OLE library file.
+ * The second argument is major version or version of the type library.
+ * The third argument is minor version.
+ * The second argument and third argument are optional.
+ * If the first argument is type library name, then the second and third argument
+ * are ignored.
+ *
+ * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}')
+ * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3)
+ * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
+ * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
+ * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library'
+ * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library'
+ * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library'
+ * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library'
+ * puts tlib5.name # -> 'Microsoft Shell Controls And Automation'
+ *
+ */
+static VALUE
+foletypelib_initialize(VALUE self, VALUE args)
+{
+ VALUE found = Qfalse;
+ VALUE typelib = Qnil;
+ int len = 0;
+ OLECHAR * pbuf;
+ ITypeLib *pTypeLib;
+ VALUE retval;
+ HRESULT hr = S_OK;
+
+ len = RARRAY_LEN(args);
+ if (len < 1 || len > 3) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
+ }
+
+ typelib = rb_ary_entry(args, 0);
+
+ Check_SafeStr(typelib);
+
+ found = oletypelib_search_registry(self, typelib);
+ if (found == Qfalse) {
+ found = oletypelib_search_registry2(self, args);
+ }
+ if (found == Qfalse) {
+ pbuf = ole_vstr2wc(typelib);
+ hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
+ SysFreeString(pbuf);
+ if (SUCCEEDED(hr)) {
+ retval = ole_typelib_from_itypelib(pTypeLib);
+ OLE_RELEASE(pTypeLib);
+ if (retval != Qnil) {
+ found = Qtrue;
+ oletypelib_set_member(self,
+ rb_ivar_get(retval, rb_intern("name")),
+ rb_ivar_get(retval, rb_intern("guid")),
+ rb_ivar_get(retval, rb_intern("version")));
+ }
+ }
+ }
+
+ if (found == Qfalse) {
+ rb_raise(eWIN32OLERuntimeError, "not found type library `%s`",
+ StringValuePtr(typelib));
+ }
+ return self;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#guid -> The guid string.
+ *
+ * Returns guid string which specifies type library.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}'
+ */
+static VALUE
+foletypelib_guid(VALUE self)
+{
+ return rb_ivar_get(self, rb_intern("guid"));
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#name -> The type library name
+ *
+ * Returns the type library name.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library'
+ */
+static VALUE
+foletypelib_name(VALUE self)
+{
+ return rb_ivar_get(self, rb_intern("name"));
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#version -> The type library version.
+ *
+ * Returns the type library version.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * puts tlib.version #-> 1.3
+ */
+static VALUE
+foletypelib_version(VALUE self)
+{
+ VALUE ver = rb_ivar_get(self, rb_intern("version"));
+ return rb_Float(ver);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#major_version -> The type library major version.
+ *
+ * Returns the type library major version.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * puts tlib.major_version # -> 1
+ */
+static VALUE
+foletypelib_major_version(VALUE self)
+{
+ VALUE ver = rb_ivar_get(self, rb_intern("version"));
+ VALUE ary = rb_str_split(ver, ".");
+ return rb_Integer(rb_ary_entry(ary, 0));
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#minor_version -> The type library minor version.
+ *
+ * Returns the type library minor version.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * puts tlib.minor_version # -> 3
+ */
+static VALUE
+foletypelib_minor_version(VALUE self)
+{
+ VALUE ver = rb_ivar_get(self, rb_intern("version"));
+ VALUE ary = rb_str_split(ver, ".");
+ return rb_Integer(rb_ary_entry(ary, 1));
+}
+
+static VALUE
+oletypelib_path(VALUE guid, VALUE version)
+{
+ int k;
+ LONG err;
+ HKEY hkey;
+ HKEY hlang;
+ VALUE lang;
+ VALUE path = Qnil;
+
+ VALUE key = rb_str_new2("TypeLib\\");
+ rb_str_concat(key, guid);
+ rb_str_cat2(key, "\\");
+ rb_str_concat(key, version);
+
+ err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey);
+ if (err != ERROR_SUCCESS) {
+ return Qnil;
+ }
+ for(k = 0; path == Qnil; k++) {
+ lang = reg_enum_key(hkey, k);
+ if (lang == Qnil)
+ break;
+ err = reg_open_vkey(hkey, lang, &hlang);
+ if (err == ERROR_SUCCESS) {
+ path = reg_get_typelib_file_path(hlang);
+ RegCloseKey(hlang);
+ }
+ }
+ RegCloseKey(hkey);
+ return path;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#path -> The type library file path.
+ *
+ * Returns the type library file path.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * puts tlib.path #-> 'C:\...\EXCEL9.OLB'
+ */
+static VALUE
+foletypelib_path(VALUE self)
+{
+ VALUE guid = rb_ivar_get(self, rb_intern("guid"));
+ VALUE version = rb_ivar_get(self, rb_intern("version"));
+ return oletypelib_path(guid, version);
+}
+
+static void
+oletypelib2itypelib(VALUE self, ITypeLib **ppTypeLib)
+{
+ VALUE path = Qnil;
+ OLECHAR *pbuf;
+ HRESULT hr = S_OK;
+ path = rb_funcall(self, rb_intern("path"), 0);
+ if (path != Qnil) {
+ pbuf = ole_vstr2wc(path);
+ hr = LoadTypeLibEx(pbuf, REGKIND_NONE, ppTypeLib);
+ SysFreeString(pbuf);
+ if (FAILED(hr))
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx from `%s'",
+ StringValuePtr(path));
+ } else {
+ rb_raise(eWIN32OLERuntimeError, "failed to get type library path");
+ }
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#visible?
+ *
+ * Returns true if the type library information is not hidden.
+ * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN,
+ * the method returns false, otherwise, returns true.
+ * If the method fails to access the TLIBATTR information, then
+ * WIN32OLERuntimeError is raised.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib.visible? # => true
+ */
+static VALUE
+foletypelib_visible(VALUE self)
+{
+ HRESULT hr;
+ ITypeLib *pTypeLib = NULL;
+ VALUE visible = Qtrue;
+ TLIBATTR *pTLibAttr;
+
+ oletypelib2itypelib(self, &pTypeLib);
+
+ hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, &pTLibAttr);
+ if (FAILED(hr)) {
+ OLE_RELEASE(pTypeLib);
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to get TLIBATTR information");
+ }
+ if ((pTLibAttr->wLibFlags == 0) ||
+ (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) ||
+ (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) {
+ visible = Qfalse;
+ }
+ pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
+ OLE_RELEASE(pTypeLib);
+ return visible;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#library_name
+ *
+ * Returns library name.
+ * If the method fails to access library name, WIN32OLERuntimeError is raised.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib.library_name # => Excel
+ */
+static VALUE
+foletypelib_library_name(VALUE self)
+{
+ HRESULT hr;
+ ITypeLib *pTypeLib = NULL;
+ VALUE libname = Qnil;
+ BSTR bstr;
+
+ oletypelib2itypelib(self, &pTypeLib);
+ hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
+ &bstr, NULL, NULL, NULL);
+ if (FAILED(hr)) {
+ OLE_RELEASE(pTypeLib);
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name");
+ }
+ OLE_RELEASE(pTypeLib);
+ libname = WC2VSTR(bstr);
+ return libname;
+}
+
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library.
+ *
+ * Returns the type library file path.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...]
+ */
+static VALUE
+foletypelib_ole_types(VALUE self)
+{
+ ITypeLib *pTypeLib = NULL;
+ VALUE classes = rb_ary_new();
+ oletypelib2itypelib(self, &pTypeLib);
+ ole_types_from_typelib(pTypeLib, classes);
+ OLE_RELEASE(pTypeLib);
+ return classes;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPELIB#inspect -> String
+ *
+ * Returns the type library name with class name.
+ *
+ * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>"
+ */
+static VALUE
+foletypelib_inspect(VALUE self)
+{
+ return default_inspect(self, "WIN32OLE_TYPELIB");
+}
+
+/*
* Document-class: WIN32OLE_TYPE
*
* <code>WIN32OLE_TYPE</code> objects represent OLE type libarary information.
@@ -3582,10 +5500,7 @@ oleclass_from_typelib(self, pTypeLib, oleclass)
* # => WIN32OLE_TYPE object of Application class of Excel.
*/
static VALUE
-foletype_initialize(self, typelib, oleclass)
- VALUE self;
- VALUE typelib;
- VALUE oleclass;
+foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
{
VALUE file;
OLECHAR * pbuf;
@@ -3598,14 +5513,14 @@ foletype_initialize(self, typelib, oleclass)
if (file == Qnil) {
file = typelib;
}
- pbuf = ole_mb2wc(StringValuePtr(file), -1);
+ pbuf = ole_vstr2wc(file);
hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to LoadTypeLibEx");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
SysFreeString(pbuf);
if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) {
OLE_RELEASE(pTypeLib);
- rb_raise(eWIN32OLE_RUNTIME_ERROR, "not found `%s` in `%s`",
+ rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`",
StringValuePtr(oleclass), StringValuePtr(typelib));
}
OLE_RELEASE(pTypeLib);
@@ -3621,15 +5536,13 @@ foletype_initialize(self, typelib, oleclass)
* puts tobj.name # => Application
*/
static VALUE
-foletype_name(self)
- VALUE self;
+foletype_name(VALUE self)
{
return rb_ivar_get(self, rb_intern("name"));
}
static VALUE
-ole_ole_type(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_ole_type(ITypeInfo *pTypeInfo)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -3683,8 +5596,7 @@ ole_ole_type(pTypeInfo)
* puts tobj.ole_type # => Class
*/
static VALUE
-foletype_ole_type(self)
- VALUE self;
+foletype_ole_type(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3692,8 +5604,7 @@ foletype_ole_type(self)
}
static VALUE
-ole_type_guid(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_guid(ITypeInfo *pTypeInfo)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -3720,8 +5631,7 @@ ole_type_guid(pTypeInfo)
* puts tobj.guid # => {00024500-0000-0000-C000-000000000046}
*/
static VALUE
-foletype_guid(self)
- VALUE self;
+foletype_guid(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3729,8 +5639,7 @@ foletype_guid(self)
}
static VALUE
-ole_type_progid(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_progid(ITypeInfo *pTypeInfo)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -3740,7 +5649,7 @@ ole_type_progid(pTypeInfo)
if (FAILED(hr))
return progid;
hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf);
- if (SUCCEEDED(hr)) {
+ if (SUCCEEDED(hr)) {
progid = ole_wc2vstr(pbuf, FALSE);
CoTaskMemFree(pbuf);
}
@@ -3757,8 +5666,7 @@ ole_type_progid(pTypeInfo)
* puts tobj.progid # => Excel.Application.9
*/
static VALUE
-foletype_progid(self)
- VALUE self;
+foletype_progid(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3767,8 +5675,7 @@ foletype_progid(self)
static VALUE
-ole_type_visible(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_visible(ITypeInfo *pTypeInfo)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -3794,8 +5701,7 @@ ole_type_visible(pTypeInfo)
* puts tobj.visible # => true
*/
static VALUE
-foletype_visible(self)
- VALUE self;
+foletype_visible(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3803,15 +5709,14 @@ foletype_visible(self)
}
static VALUE
-ole_type_major_version(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_major_version(ITypeInfo *pTypeInfo)
{
VALUE ver;
TYPEATTR *pTypeAttr;
HRESULT hr;
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
ver = INT2FIX(pTypeAttr->wMajorVerNum);
OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
return ver;
@@ -3826,8 +5731,7 @@ ole_type_major_version(pTypeInfo)
* puts tobj.major_version # => 8
*/
static VALUE
-foletype_major_version(self)
- VALUE self;
+foletype_major_version(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3835,15 +5739,14 @@ foletype_major_version(self)
}
static VALUE
-ole_type_minor_version(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_minor_version(ITypeInfo *pTypeInfo)
{
VALUE ver;
TYPEATTR *pTypeAttr;
HRESULT hr;
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
ver = INT2FIX(pTypeAttr->wMinorVerNum);
OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
return ver;
@@ -3858,8 +5761,7 @@ ole_type_minor_version(pTypeInfo)
* puts tobj.minor_version # => 2
*/
static VALUE
-foletype_minor_version(self)
- VALUE self;
+foletype_minor_version(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3867,15 +5769,14 @@ foletype_minor_version(self)
}
static VALUE
-ole_type_typekind(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_typekind(ITypeInfo *pTypeInfo)
{
VALUE typekind;
TYPEATTR *pTypeAttr;
HRESULT hr;
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
typekind = INT2FIX(pTypeAttr->typekind);
OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
return typekind;
@@ -3891,8 +5792,7 @@ ole_type_typekind(pTypeInfo)
*
*/
static VALUE
-foletype_typekind(self)
- VALUE self;
+foletype_typekind(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3900,8 +5800,7 @@ foletype_typekind(self)
}
static VALUE
-ole_type_helpstring(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_helpstring(ITypeInfo *pTypeInfo)
{
HRESULT hr;
BSTR bhelpstr;
@@ -3921,8 +5820,7 @@ ole_type_helpstring(pTypeInfo)
* puts tobj.helpstring # => Web Browser interface
*/
static VALUE
-foletype_helpstring(self)
- VALUE self;
+foletype_helpstring(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3930,8 +5828,7 @@ foletype_helpstring(self)
}
static VALUE
-ole_type_src_type(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_src_type(ITypeInfo *pTypeInfo)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -3958,8 +5855,7 @@ ole_type_src_type(pTypeInfo)
*
*/
static VALUE
-foletype_src_type(self)
- VALUE self;
+foletype_src_type(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3967,8 +5863,7 @@ foletype_src_type(self)
}
static VALUE
-ole_type_helpfile(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_helpfile(ITypeInfo *pTypeInfo)
{
HRESULT hr;
BSTR bhelpfile;
@@ -3989,8 +5884,7 @@ ole_type_helpfile(pTypeInfo)
*
*/
static VALUE
-foletype_helpfile(self)
- VALUE self;
+foletype_helpfile(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -3998,8 +5892,7 @@ foletype_helpfile(self)
}
static VALUE
-ole_type_helpcontext(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_helpcontext(ITypeInfo *pTypeInfo)
{
HRESULT hr;
DWORD helpcontext;
@@ -4019,17 +5912,158 @@ ole_type_helpcontext(pTypeInfo)
* puts tobj.helpfile # => 131185
*/
static VALUE
-foletype_helpcontext(self)
- VALUE self;
+foletype_helpcontext(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
return ole_type_helpcontext(ptype->pTypeInfo);
}
+/*
+ * call-seq:
+ * WIN32OLE_TYPE#ole_typelib
+ *
+ * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE
+ * object. If it is not found, then returns nil.
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library'
+ */
+static VALUE
+foletype_ole_typelib(VALUE self)
+{
+ struct oletypedata *ptype;
+ Data_Get_Struct(self, struct oletypedata, ptype);
+ return ole_typelib_from_itypeinfo(ptype->pTypeInfo);
+}
+
static VALUE
-ole_variables(pTypeInfo)
- ITypeInfo *pTypeInfo;
+ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
+{
+ HRESULT hr;
+ ITypeInfo *pRefTypeInfo;
+ HREFTYPE href;
+ WORD i;
+ VALUE type;
+ TYPEATTR *pTypeAttr;
+ int flags;
+
+ VALUE types = rb_ary_new();
+ hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
+ if (FAILED(hr)) {
+ return types;
+ }
+ for (i = 0; i < pTypeAttr->cImplTypes; i++) {
+ hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
+ if (FAILED(hr))
+ continue;
+
+ hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
+ if (FAILED(hr))
+ continue;
+ hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
+ if (FAILED(hr))
+ continue;
+
+ if ((flags & implflags) == implflags) {
+ type = ole_type_from_itypeinfo(pRefTypeInfo);
+ if (type != Qnil) {
+ rb_ary_push(types, type);
+ }
+ }
+
+ OLE_RELEASE(pRefTypeInfo);
+ }
+ OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
+ return types;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPE#implemented_ole_types
+ *
+ * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * object.
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * p tobj.implemented_ole_types # => [_Worksheet, DocEvents]
+ */
+static VALUE
+foletype_impl_ole_types(VALUE self)
+{
+ struct oletypedata *ptype;
+ Data_Get_Struct(self, struct oletypedata, ptype);
+ return ole_type_impl_ole_types(ptype->pTypeInfo, 0);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPE#source_ole_types
+ *
+ * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * object and having IMPLTYPEFLAG_FSOURCE.
+ * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
+ * p tobj.source_ole_types
+ * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>]
+ */
+static VALUE
+foletype_source_ole_types(VALUE self)
+{
+ struct oletypedata *ptype;
+ Data_Get_Struct(self, struct oletypedata, ptype);
+ return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPE#default_event_sources
+ *
+ * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT.
+ * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
+ * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>]
+ */
+static VALUE
+foletype_default_event_sources(VALUE self)
+{
+ struct oletypedata *ptype;
+ Data_Get_Struct(self, struct oletypedata, ptype);
+ return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPE#default_ole_types
+ *
+ * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * object and having IMPLTYPEFLAG_FDEFAULT.
+ * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
+ * p tobj.default_ole_types
+ * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>]
+ */
+static VALUE
+foletype_default_ole_types(VALUE self)
+{
+ struct oletypedata *ptype;
+ Data_Get_Struct(self, struct oletypedata, ptype);
+ return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_TYPE#inspect -> String
+ *
+ * Returns the type name with class name.
+ *
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2>
+ */
+static VALUE
+foletype_inspect(VALUE self)
+{
+ return default_inspect(self, "WIN32OLE_TYPE");
+}
+
+static VALUE
+ole_variables(ITypeInfo *pTypeInfo)
{
HRESULT hr;
TYPEATTR *pTypeAttr;
@@ -4043,7 +6077,7 @@ ole_variables(pTypeInfo)
VALUE variables = rb_ary_new();
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetTypeAttr");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
}
for(i = 0; i < pTypeAttr->cVars; i++) {
@@ -4093,8 +6127,7 @@ ole_variables(pTypeInfo)
*
*/
static VALUE
-foletype_variables(self)
- VALUE self;
+foletype_variables(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -4114,10 +6147,7 @@ foletype_variables(self)
* # => ['Activate', 'Copy', 'Delete',....]
*/
static VALUE
-foletype_methods(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+foletype_methods(VALUE self)
{
struct oletypedata *ptype;
Data_Get_Struct(self, struct oletypedata, ptype);
@@ -4151,23 +6181,20 @@ foletype_methods(argc, argv, self)
*
*/
static VALUE
-folevariable_name(self)
- VALUE self;
+folevariable_name(VALUE self)
{
return rb_ivar_get(self, rb_intern("name"));
}
static VALUE
-ole_variable_ole_type(pTypeInfo, var_index)
- ITypeInfo *pTypeInfo;
- UINT var_index;
+ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
{
VARDESC *pVarDesc;
HRESULT hr;
VALUE type;
hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetVarDesc");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil);
pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
return type;
@@ -4194,8 +6221,7 @@ ole_variable_ole_type(pTypeInfo, var_index)
*
*/
static VALUE
-folevariable_ole_type(self)
- VALUE self;
+folevariable_ole_type(VALUE self)
{
struct olevariabledata *pvar;
Data_Get_Struct(self, struct olevariabledata, pvar);
@@ -4203,16 +6229,14 @@ folevariable_ole_type(self)
}
static VALUE
-ole_variable_ole_type_detail(pTypeInfo, var_index)
- ITypeInfo *pTypeInfo;
- UINT var_index;
+ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
{
VARDESC *pVarDesc;
HRESULT hr;
VALUE type = rb_ary_new();
hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetVarDesc");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type);
pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
return type;
@@ -4231,8 +6255,7 @@ ole_variable_ole_type_detail(pTypeInfo, var_index)
*
*/
static VALUE
-folevariable_ole_type_detail(self)
- VALUE self;
+folevariable_ole_type_detail(VALUE self)
{
struct olevariabledata *pvar;
Data_Get_Struct(self, struct olevariabledata, pvar);
@@ -4240,9 +6263,7 @@ folevariable_ole_type_detail(self)
}
static VALUE
-ole_variable_value(pTypeInfo, var_index)
- ITypeInfo *pTypeInfo;
- UINT var_index;
+ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
{
VARDESC *pVarDesc;
HRESULT hr;
@@ -4266,7 +6287,7 @@ ole_variable_value(pTypeInfo, var_index)
* tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
- * puts "#{variable.name} = #{variable.value}"
+ * puts "#{variable.name} #{variable.value}"
* end
*
* The result of above script is following:
@@ -4278,8 +6299,7 @@ ole_variable_value(pTypeInfo, var_index)
*
*/
static VALUE
-folevariable_value(self)
- VALUE self;
+folevariable_value(VALUE self)
{
struct olevariabledata *pvar;
Data_Get_Struct(self, struct olevariabledata, pvar);
@@ -4287,9 +6307,7 @@ folevariable_value(self)
}
static VALUE
-ole_variable_visible(pTypeInfo, var_index)
- ITypeInfo *pTypeInfo;
- UINT var_index;
+ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
{
VARDESC *pVarDesc;
HRESULT hr;
@@ -4327,8 +6345,7 @@ ole_variable_visible(pTypeInfo, var_index)
*
*/
static VALUE
-folevariable_visible(self)
- VALUE self;
+folevariable_visible(VALUE self)
{
struct olevariabledata *pvar;
Data_Get_Struct(self, struct olevariabledata, pvar);
@@ -4336,9 +6353,7 @@ folevariable_visible(self)
}
static VALUE
-ole_variable_kind(pTypeInfo, var_index)
- ITypeInfo *pTypeInfo;
- UINT var_index;
+ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
{
VARDESC *pVarDesc;
HRESULT hr;
@@ -4386,8 +6401,7 @@ ole_variable_kind(pTypeInfo, var_index)
* xlWorksheet CONSTANT
*/
static VALUE
-folevariable_variable_kind(self)
- VALUE self;
+folevariable_variable_kind(VALUE self)
{
struct olevariabledata *pvar;
Data_Get_Struct(self, struct olevariabledata, pvar);
@@ -4395,9 +6409,7 @@ folevariable_variable_kind(self)
}
static VALUE
-ole_variable_varkind(pTypeInfo, var_index)
- ITypeInfo *pTypeInfo;
- UINT var_index;
+ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
{
VARDESC *pVarDesc;
HRESULT hr;
@@ -4429,8 +6441,7 @@ ole_variable_varkind(pTypeInfo, var_index)
* xlWorksheet 2
*/
static VALUE
-folevariable_varkind(self)
- VALUE self;
+folevariable_varkind(VALUE self)
{
struct olevariabledata *pvar;
Data_Get_Struct(self, struct olevariabledata, pvar);
@@ -4438,18 +6449,29 @@ folevariable_varkind(self)
}
/*
+ * call-seq:
+ * WIN32OLE_VARIABLE#inspect -> String
+ *
+ * Returns the OLE variable name and the value with class name.
+ *
+ */
+static VALUE
+folevariable_inspect(VALUE self)
+{
+ VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
+ rb_str_cat2(detail, "=");
+ rb_str_concat(detail, rb_funcall(rb_funcall(self, rb_intern("value"), 0), rb_intern("inspect"), 0));
+ return make_inspect("WIN32OLE_VARIABLE", detail);
+}
+
+/*
* Document-class: WIN32OLE_METHOD
*
* <code>WIN32OLE_METHOD</code> objects represent OLE method information.
*/
static VALUE
-olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, index, name)
- VALUE self;
- ITypeInfo *pTypeInfo;
- ITypeInfo *pOwnerTypeInfo;
- int index;
- VALUE name;
+olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4463,8 +6485,7 @@ olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, index, name)
}
static VALUE
-folemethod_s_allocate(klass)
- VALUE klass;
+folemethod_s_allocate(VALUE klass)
{
struct olemethoddata *pmethod;
VALUE obj;
@@ -4491,10 +6512,7 @@ folemethod_s_allocate(klass)
* method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
*/
static VALUE
-folemethod_initialize(self, oletype, method)
- VALUE self;
- VALUE oletype;
- VALUE method;
+folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
{
struct oletypedata *ptype;
VALUE obj = Qnil;
@@ -4503,7 +6521,7 @@ folemethod_initialize(self, oletype, method)
Data_Get_Struct(oletype, struct oletypedata, ptype);
obj = olemethod_from_typeinfo(self, ptype->pTypeInfo, method);
if (obj == Qnil) {
- rb_raise(eWIN32OLE_RUNTIME_ERROR, "not found %s",
+ rb_raise(eWIN32OLERuntimeError, "not found %s",
StringValuePtr(method));
}
}
@@ -4525,16 +6543,13 @@ folemethod_initialize(self, oletype, method)
*
*/
static VALUE
-folemethod_name(self)
- VALUE self;
+folemethod_name(VALUE self)
{
return rb_ivar_get(self, rb_intern("name"));
}
static VALUE
-ole_method_return_type(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -4542,7 +6557,7 @@ ole_method_return_type(pTypeInfo, method_index)
hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetFuncDesc");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil);
pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
@@ -4560,8 +6575,7 @@ ole_method_return_type(pTypeInfo, method_index)
*
*/
static VALUE
-folemethod_return_type(self)
- VALUE self;
+folemethod_return_type(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4569,21 +6583,19 @@ folemethod_return_type(self)
}
static VALUE
-ole_method_return_vtype(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
- VALUE vt;
+ VALUE vvt;
hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
if (FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetFuncDesc");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
- vt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt);
+ vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt);
pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return vt;
+ return vvt;
}
/*
@@ -4597,8 +6609,7 @@ ole_method_return_vtype(pTypeInfo, method_index)
*
*/
static VALUE
-folemethod_return_vtype(self)
- VALUE self;
+folemethod_return_vtype(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4606,9 +6617,7 @@ folemethod_return_vtype(self)
}
static VALUE
-ole_method_return_type_detail(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -4634,8 +6643,7 @@ ole_method_return_type_detail(pTypeInfo, method_index)
* p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"]
*/
static VALUE
-folemethod_return_type_detail(self)
- VALUE self;
+folemethod_return_type_detail(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4643,25 +6651,21 @@ folemethod_return_type_detail(self)
}
static VALUE
-ole_method_invkind(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
VALUE invkind;
hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
if(FAILED(hr))
- ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, "failed to GetFuncDesc");
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
invkind = INT2FIX(pFuncDesc->invkind);
pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
return invkind;
}
static VALUE
-ole_method_invoke_kind(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- WORD method_index;
+ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
{
VALUE type = rb_str_new2("UNKNOWN");
VALUE invkind = ole_method_invkind(pTypeInfo, method_index);
@@ -4691,8 +6695,7 @@ ole_method_invoke_kind(pTypeInfo, method_index)
*
*/
static VALUE
-folemethod_invkind(self)
- VALUE self;
+folemethod_invkind(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4711,8 +6714,7 @@ folemethod_invkind(self)
* puts method.invoke_kind # => "FUNC"
*/
static VALUE
-folemethod_invoke_kind(self)
- VALUE self;
+folemethod_invoke_kind(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4720,9 +6722,7 @@ folemethod_invoke_kind(self)
}
static VALUE
-ole_method_visible(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -4751,8 +6751,7 @@ ole_method_visible(pTypeInfo, method_index)
* puts method.visible? # => true
*/
static VALUE
-folemethod_visible(self)
- VALUE self;
+folemethod_visible(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4760,10 +6759,7 @@ folemethod_visible(self)
}
static VALUE
-ole_method_event(pTypeInfo, method_index, method_name)
- ITypeInfo *pTypeInfo;
- WORD method_index;
- VALUE method_name;
+ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
{
TYPEATTR *pTypeAttr;
HRESULT hr;
@@ -4837,8 +6833,7 @@ ole_method_event(pTypeInfo, method_index, method_name)
*
*/
static VALUE
-folemethod_event(self)
- VALUE self;
+folemethod_event(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4859,8 +6854,7 @@ folemethod_event(self)
* puts method.event_interface # => WorkbookEvents
*/
static VALUE
-folemethod_event_interface(self)
- VALUE self;
+folemethod_event_interface(VALUE self)
{
BSTR name;
struct olemethoddata *pmethod;
@@ -4875,14 +6869,14 @@ folemethod_event_interface(self)
}
static VALUE
-ole_method_docinfo_from_type(pTypeInfo, method_index, name, helpstr,
- helpcontext, helpfile)
- ITypeInfo *pTypeInfo;
- UINT method_index;
- BSTR *name;
- BSTR *helpstr;
- DWORD *helpcontext;
- BSTR *helpfile;
+ole_method_docinfo_from_type(
+ ITypeInfo *pTypeInfo,
+ UINT method_index,
+ BSTR *name,
+ BSTR *helpstr,
+ DWORD *helpcontext,
+ BSTR *helpfile
+ )
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -4897,9 +6891,7 @@ ole_method_docinfo_from_type(pTypeInfo, method_index, name, helpstr,
}
static VALUE
-ole_method_helpstring(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
{
HRESULT hr;
BSTR bhelpstring;
@@ -4922,8 +6914,7 @@ ole_method_helpstring(pTypeInfo, method_index)
*
*/
static VALUE
-folemethod_helpstring(self)
- VALUE self;
+folemethod_helpstring(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4931,9 +6922,7 @@ folemethod_helpstring(self)
}
static VALUE
-ole_method_helpfile(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
{
HRESULT hr;
BSTR bhelpfile;
@@ -4955,8 +6944,7 @@ ole_method_helpfile(pTypeInfo, method_index)
* puts method.helpfile # => C:\...\VBAXL9.CHM
*/
static VALUE
-folemethod_helpfile(self)
- VALUE self;
+folemethod_helpfile(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4965,9 +6953,7 @@ folemethod_helpfile(self)
}
static VALUE
-ole_method_helpcontext(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
{
HRESULT hr;
DWORD helpcontext = 0;
@@ -4988,8 +6974,7 @@ ole_method_helpcontext(pTypeInfo, method_index)
* puts method.helpcontext # => 65717
*/
static VALUE
-folemethod_helpcontext(self)
- VALUE self;
+folemethod_helpcontext(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -4997,9 +6982,7 @@ folemethod_helpcontext(self)
}
static VALUE
-ole_method_dispid(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5022,8 +7005,7 @@ ole_method_dispid(pTypeInfo, method_index)
* puts method.dispid # => 181
*/
static VALUE
-folemethod_dispid(self)
- VALUE self;
+folemethod_dispid(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -5031,9 +7013,7 @@ folemethod_dispid(self)
}
static VALUE
-ole_method_offset_vtbl(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5056,8 +7036,7 @@ ole_method_offset_vtbl(pTypeInfo, method_index)
* puts method.offset_vtbl # => 40
*/
static VALUE
-folemethod_offset_vtbl(self)
- VALUE self;
+folemethod_offset_vtbl(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -5065,9 +7044,7 @@ folemethod_offset_vtbl(self)
}
static VALUE
-ole_method_size_params(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5091,8 +7068,7 @@ ole_method_size_params(pTypeInfo, method_index)
*
*/
static VALUE
-folemethod_size_params(self)
- VALUE self;
+folemethod_size_params(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -5100,9 +7076,7 @@ folemethod_size_params(self)
}
static VALUE
-ole_method_size_opt_params(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5125,8 +7099,7 @@ ole_method_size_opt_params(pTypeInfo, method_index)
* puts method.size_opt_params # => 4
*/
static VALUE
-folemethod_size_opt_params(self)
- VALUE self;
+folemethod_size_opt_params(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -5134,9 +7107,7 @@ folemethod_size_opt_params(self)
}
static VALUE
-ole_method_params(pTypeInfo, method_index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
+ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5175,6 +7146,7 @@ ole_method_params(pTypeInfo, method_index)
return params;
}
+
/*
* call-seq:
* WIN32OLE_METHOD#params
@@ -5188,8 +7160,7 @@ ole_method_params(pTypeInfo, method_index)
* TextVisualLayout]
*/
static VALUE
-folemethod_params(self)
- VALUE self;
+folemethod_params(VALUE self)
{
struct olemethoddata *pmethod;
Data_Get_Struct(self, struct olemethoddata, pmethod);
@@ -5197,6 +7168,19 @@ folemethod_params(self)
}
/*
+ * call-seq:
+ * WIN32OLE_METHOD#inspect -> String
+ *
+ * Returns the method name with class name.
+ *
+ */
+static VALUE
+folemethod_inspect(VALUE self)
+{
+ return default_inspect(self, "WIN32OLE_METHOD");
+}
+
+/*
* Document-class: WIN32OLE_PARAM
*
* <code>WIN32OLE_PARAM</code> objects represent param information of
@@ -5214,21 +7198,17 @@ folemethod_params(self)
* puts param1.name # => Filename
*/
static VALUE
-foleparam_name(self)
- VALUE self;
+foleparam_name(VALUE self)
{
return rb_ivar_get(self, rb_intern("name"));
}
static VALUE
-ole_param_ole_type(pTypeInfo, method_index, index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
- UINT index;
+ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
- VALUE type = rb_str_new2("UNKNOWN");
+ VALUE type = rb_str_new2("unknown type");
hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
if (FAILED(hr))
return type;
@@ -5249,8 +7229,7 @@ ole_param_ole_type(pTypeInfo, method_index, index)
* puts param1.ole_type # => VARIANT
*/
static VALUE
-foleparam_ole_type(self)
- VALUE self;
+foleparam_ole_type(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5259,10 +7238,7 @@ foleparam_ole_type(self)
}
static VALUE
-ole_param_ole_type_detail(pTypeInfo, method_index, index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
- UINT index;
+ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5287,8 +7263,7 @@ ole_param_ole_type_detail(pTypeInfo, method_index, index)
* p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"]
*/
static VALUE
-foleparam_ole_type_detail(self)
- VALUE self;
+foleparam_ole_type_detail(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5297,11 +7272,7 @@ foleparam_ole_type_detail(self)
}
static VALUE
-ole_param_flag_mask(pTypeInfo, method_index, index, mask)
- ITypeInfo *pTypeInfo;
- UINT method_index;
- UINT index;
- USHORT mask;
+ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask)
{
FUNCDESC *pFuncDesc;
HRESULT hr;
@@ -5325,8 +7296,7 @@ ole_param_flag_mask(pTypeInfo, method_index, index, mask)
* param1 = method.params[0]
* puts param1.input? # => true
*/
-static VALUE foleparam_input(self)
- VALUE self;
+static VALUE foleparam_input(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5353,8 +7323,7 @@ static VALUE foleparam_input(self)
* Headers false
* Processed true
*/
-static VALUE foleparam_output(self)
- VALUE self;
+static VALUE foleparam_output(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5372,8 +7341,7 @@ static VALUE foleparam_output(self)
* param1 = method.params[0]
* puts "#{param1.name} #{param1.optional?}" # => Filename true
*/
-static VALUE foleparam_optional(self)
- VALUE self;
+static VALUE foleparam_optional(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5392,8 +7360,7 @@ static VALUE foleparam_optional(self)
* param = method.params[0]
* puts "#{param.name} #{param.retval?}" # => name true
*/
-static VALUE foleparam_retval(self)
- VALUE self;
+static VALUE foleparam_retval(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5402,10 +7369,7 @@ static VALUE foleparam_retval(self)
}
static VALUE
-ole_param_default(pTypeInfo, method_index, index)
- ITypeInfo *pTypeInfo;
- UINT method_index;
- UINT index;
+ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
{
FUNCDESC *pFuncDesc;
ELEMDESC *pElemDesc;
@@ -5456,8 +7420,7 @@ ole_param_default(pTypeInfo, method_index, index)
* TextCodepage
* TextVisualLayout
*/
-static VALUE foleparam_default(self)
- VALUE self;
+static VALUE foleparam_default(VALUE self)
{
struct oleparamdata *pparam;
Data_Get_Struct(self, struct oleparamdata, pparam);
@@ -5465,7 +7428,26 @@ static VALUE foleparam_default(self)
pparam->index);
}
-
+/*
+ * call-seq:
+ * WIN32OLE_PARAM#inspect -> String
+ *
+ * Returns the parameter name with class name. If the parameter has default value,
+ * then returns name=value string with class name.
+ *
+ */
+static VALUE
+foleparam_inspect(VALUE self)
+{
+ VALUE detail = foleparam_name(self);
+ VALUE defval = foleparam_default(self);
+ if (defval != Qnil) {
+ rb_str_cat2(detail, "=");
+ rb_str_concat(detail, rb_funcall(defval, rb_intern("inspect"), 0));
+ }
+ return make_inspect("WIN32OLE_PARAM", detail);
+}
+
/*
* Document-class: WIN32OLE_EVENT
*
@@ -5534,20 +7516,24 @@ STDMETHODIMP EVENTSINK_GetTypeInfo(
}
STDMETHODIMP EVENTSINK_GetIDsOfNames(
- PEVENTSINK pEV,
+ PEVENTSINK pEventSink,
REFIID riid,
OLECHAR **szNames,
UINT cNames,
LCID lcid,
DISPID *pDispID
) {
+ ITypeInfo *pTypeInfo;
+ PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
+ pTypeInfo = pEV->pTypeInfo;
+ if (pTypeInfo) {
+ return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
+ }
return DISP_E_UNKNOWNNAME;
}
static long
-ole_search_event_at(ary, ev)
- VALUE ary;
- VALUE ev;
+ole_search_event_at(VALUE ary, VALUE ev)
{
VALUE event;
VALUE def_event;
@@ -5555,7 +7541,7 @@ ole_search_event_at(ary, ev)
long i, len;
long ret = -1;
def_event = Qnil;
- len = RARRAY(ary)->len;
+ len = RARRAY_LEN(ary);
for(i = 0; i < len; i++) {
event = rb_ary_entry(ary, i);
event_name = rb_ary_entry(event, 1);
@@ -5574,18 +7560,15 @@ ole_search_event_at(ary, ev)
}
static VALUE
-ole_search_event(ary, ev, is_default)
- VALUE ary;
- VALUE ev;
- BOOL *is_default;
+ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
{
VALUE event;
VALUE def_event;
VALUE event_name;
- long i, len;
+ int i, len;
*is_default = FALSE;
def_event = Qnil;
- len = RARRAY(ary)->len;
+ len = RARRAY_LEN(ary);
for(i = 0; i < len; i++) {
event = rb_ary_entry(ary, i);
event_name = rb_ary_entry(event, 1);
@@ -5600,92 +7583,114 @@ ole_search_event(ary, ev, is_default)
}
return def_event;
}
+static VALUE
+ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
+{
+ VALUE mid;
+
+ *is_default_handler = FALSE;
+ mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev)));
+ if (rb_respond_to(handler, mid)) {
+ return mid;
+ }
+ mid = rb_intern("method_missing");
+ if (rb_respond_to(handler, mid)) {
+ *is_default_handler = TRUE;
+ return mid;
+ }
+ return Qnil;
+}
static void
-val2ptr_variant(val, var)
- VALUE val;
- VARIANT *var;
+ole_delete_event(VALUE ary, VALUE ev)
{
- switch (TYPE(val)) {
- case T_STRING:
- if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
- *V_BSTRREF(var) = ole_mb2wc(StringValuePtr(val), -1);
- }
- break;
- case T_FIXNUM:
- switch(V_VT(var)) {
- case (VT_UI1 | VT_BYREF) :
- *V_UI1REF(var) = NUM2CHR(val);
- break;
- case (VT_I2 | VT_BYREF) :
- *V_I2REF(var) = (short)NUM2INT(val);
- break;
- case (VT_I4 | VT_BYREF) :
- *V_I4REF(var) = NUM2INT(val);
- break;
- case (VT_R4 | VT_BYREF) :
- *V_R4REF(var) = (float)NUM2INT(val);
- break;
- case (VT_R8 | VT_BYREF) :
- *V_R8REF(var) = NUM2INT(val);
- break;
- default:
- break;
- }
- break;
- case T_FLOAT:
- switch(V_VT(var)) {
- case (VT_I2 | VT_BYREF) :
- *V_I2REF(var) = (short)NUM2INT(val);
- break;
- case (VT_I4 | VT_BYREF) :
- *V_I4REF(var) = NUM2INT(val);
- break;
- case (VT_R4 | VT_BYREF) :
- *V_R4REF(var) = (float)NUM2DBL(val);
- break;
- case (VT_R8 | VT_BYREF) :
- *V_R8REF(var) = NUM2DBL(val);
- break;
- default:
- break;
- }
- break;
- case T_BIGNUM:
- if (V_VT(var) == (VT_R8 | VT_BYREF)) {
- *V_R8REF(var) = rb_big2dbl(val);
- }
- break;
- case T_TRUE:
- if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
- *V_BOOLREF(var) = VARIANT_TRUE;
- }
- break;
- case T_FALSE:
- if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
- *V_BOOLREF(var) = VARIANT_FALSE;
- }
- break;
- default:
- break;
+ long at = -1;
+ at = ole_search_event_at(ary, ev);
+ if (at >= 0) {
+ rb_ary_delete_at(ary, at);
+ }
+}
+
+static void
+hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
+{
+ BSTR *bstrs;
+ HRESULT hr;
+ UINT len, i;
+ VARIANT *pvar;
+ VALUE val;
+ VALUE key;
+ len = 0;
+ bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
+ hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
+ bstrs, pdispparams->cArgs + 1,
+ &len);
+ if (FAILED(hr))
+ return;
+
+ for (i = 0; i < len - 1; i++) {
+ key = WC2VSTR(bstrs[i + 1]);
+ val = rb_hash_aref(hash, INT2FIX(i));
+ if (val == Qnil)
+ val = rb_hash_aref(hash, key);
+ if (val == Qnil)
+ val = rb_hash_aref(hash, rb_str_intern(key));
+ pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
+ ole_val2ptr_variant(val, pvar);
}
}
+static VALUE
+hash2result(VALUE hash)
+{
+ VALUE ret = Qnil;
+ ret = rb_hash_aref(hash, rb_str_new2("return"));
+ if (ret == Qnil)
+ ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
+ return ret;
+}
+
static void
-ary2ptr_dispparams(ary, pdispparams)
- VALUE ary;
- DISPPARAMS *pdispparams;
+ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
{
int i;
VALUE v;
VARIANT *pvar;
- for(i = 0; i < RARRAY(ary)->len && (unsigned int) i < pdispparams->cArgs; i++) {
+ for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) {
v = rb_ary_entry(ary, i);
pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
- val2ptr_variant(v, pvar);
+ ole_val2ptr_variant(v, pvar);
}
}
+static VALUE
+exec_callback(VALUE arg)
+{
+ VALUE *parg = (VALUE *)arg;
+ VALUE handler = parg[0];
+ VALUE mid = parg[1];
+ VALUE args = parg[2];
+ return rb_apply(handler, mid, args);
+}
+
+static VALUE
+rescue_callback(VALUE arg)
+{
+
+ VALUE error;
+ VALUE e = rb_errinfo();
+ VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
+ VALUE msg = rb_funcall(e, rb_intern("message"), 0);
+ bt = rb_ary_entry(bt, 0);
+ error = rb_sprintf("%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e));
+ rb_write_error(StringValuePtr(error));
+ rb_backtrace();
+ ruby_finalize();
+ exit(-1);
+
+ return Qnil;
+}
+
STDMETHODIMP EVENTSINK_Invoke(
PEVENTSINK pEventSink,
DISPID dispid,
@@ -5704,13 +7709,17 @@ STDMETHODIMP EVENTSINK_Invoke(
unsigned int i;
ITypeInfo *pTypeInfo;
VARIANT *pvar;
- VALUE ary, obj, event, handler, args, argv, ev, result;
+ VALUE ary, obj, event, args, outargv, ev, result;
+ VALUE handler = Qnil;
+ VALUE arg[3];
+ VALUE mid;
+ VALUE is_outarg = Qfalse;
BOOL is_default_handler = FALSE;
+ int state;
PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
pTypeInfo = pEV->pTypeInfo;
-
- obj = rb_ary_entry(ary_ole_event, pEV->m_event_id);
+ obj = evs_entry(pEV->m_event_id);
if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
return NOERROR;
}
@@ -5726,9 +7735,21 @@ STDMETHODIMP EVENTSINK_Invoke(
}
ev = WC2VSTR(bstr);
event = ole_search_event(ary, ev, &is_default_handler);
- if (NIL_P(event)) {
- return NOERROR;
+ if (TYPE(event) == T_ARRAY) {
+ handler = rb_ary_entry(event, 0);
+ mid = rb_intern("call");
+ is_outarg = rb_ary_entry(event, 3);
+ } else {
+ handler = rb_ivar_get(obj, rb_intern("handler"));
+ if (handler == Qnil) {
+ return NOERROR;
+ }
+ mid = ole_search_handler_method(handler, ev, &is_default_handler);
+ }
+ if (handler == Qnil || mid == Qnil) {
+ return NOERROR;
}
+
args = rb_ary_new();
if (is_default_handler) {
rb_ary_push(args, ev);
@@ -5739,16 +7760,31 @@ STDMETHODIMP EVENTSINK_Invoke(
pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
rb_ary_push(args, ole_variant2val(pvar));
}
- handler = rb_ary_entry(event, 0);
+ outargv = Qnil;
+ if (is_outarg == Qtrue) {
+ outargv = rb_ary_new();
+ rb_ary_push(args, outargv);
+ }
- if (rb_ary_entry(event, 3) == Qtrue) {
- argv = rb_ary_new();
- rb_ary_push(args, argv);
- result = rb_apply(handler, rb_intern("call"), args);
- ary2ptr_dispparams(argv, pdispparams);
+ /*
+ * if exception raised in event callback,
+ * then you receive cfp consistency error.
+ * to avoid this error we use begin rescue end.
+ * and the exception raised then error message print
+ * and exit ruby process by Win32OLE itself.
+ */
+ arg[0] = handler;
+ arg[1] = mid;
+ arg[2] = args;
+ result = rb_protect(exec_callback, (VALUE)arg, &state);
+ if (state != 0) {
+ rescue_callback(Qnil);
}
- else {
- result = rb_apply(handler, rb_intern("call"), args);
+ if(TYPE(result) == T_HASH) {
+ hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
+ result = hash2result(result);
+ }else if (is_outarg == Qtrue && TYPE(outargv) == T_ARRAY) {
+ ary2ptr_dispparams(outargv, pdispparams);
}
if (pvarResult) {
@@ -5777,10 +7813,7 @@ EVENTSINK_Constructor() {
pEv->lpVtbl = &vtEventSink;
pEv->m_cRef = 0;
pEv->m_event_id = 0;
- pEv->m_dwCookie = 0;
- pEv->pConnectionPoint = NULL;
pEv->pTypeInfo = NULL;
- pEv->ptr_freed = NULL;
return pEv;
}
@@ -5788,17 +7821,14 @@ void EVENTSINK_Destructor(
PIEVENTSINKOBJ pEVObj
) {
if(pEVObj != NULL) {
- *(pEVObj->ptr_freed) = 1;
+ OLE_RELEASE(pEVObj->pTypeInfo);
free(pEVObj);
+ pEVObj = NULL;
}
}
static HRESULT
-find_iid(ole, pitf, piid, ppTypeInfo)
- VALUE ole;
- char *pitf;
- IID *piid;
- ITypeInfo **ppTypeInfo;
+find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
{
HRESULT hr;
IDispatch *pDispatch;
@@ -5817,7 +7847,7 @@ find_iid(ole, pitf, piid, ppTypeInfo)
char *pstr;
BOOL is_found = FALSE;
- LCID lcid = LOCALE_SYSTEM_DEFAULT;
+ LCID lcid = cWIN32OLE_lcid;
OLEData_Get_Struct(ole, pole);
@@ -5908,22 +7938,130 @@ find_iid(ole, pitf, piid, ppTypeInfo)
return hr;
}
+static HRESULT
+find_coclass(
+ ITypeInfo *pTypeInfo,
+ TYPEATTR *pTypeAttr,
+ ITypeInfo **pCOTypeInfo,
+ TYPEATTR **pCOTypeAttr)
+{
+ HRESULT hr = E_NOINTERFACE;
+ ITypeLib *pTypeLib;
+ int count;
+ BOOL found = FALSE;
+ ITypeInfo *pTypeInfo2;
+ TYPEATTR *pTypeAttr2;
+ int flags;
+ int i,j;
+ HREFTYPE href;
+ ITypeInfo *pRefTypeInfo;
+ TYPEATTR *pRefTypeAttr;
+
+ hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
+ for (i = 0; i < count && !found; i++) {
+ hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
+ if (FAILED(hr))
+ continue;
+ hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
+ if (FAILED(hr)) {
+ OLE_RELEASE(pTypeInfo2);
+ continue;
+ }
+ if (pTypeAttr2->typekind != TKIND_COCLASS) {
+ OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
+ OLE_RELEASE(pTypeInfo2);
+ continue;
+ }
+ for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
+ hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
+ if (FAILED(hr))
+ continue;
+ if (!(flags & IMPLTYPEFLAG_FDEFAULT))
+ continue;
+ hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
+ if (FAILED(hr))
+ continue;
+ hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
+ if (FAILED(hr))
+ continue;
+ hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
+ if (FAILED(hr)) {
+ OLE_RELEASE(pRefTypeInfo);
+ continue;
+ }
+ if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
+ found = TRUE;
+ }
+ }
+ if (!found) {
+ OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
+ OLE_RELEASE(pTypeInfo2);
+ }
+ }
+ OLE_RELEASE(pTypeLib);
+ if (found) {
+ *pCOTypeInfo = pTypeInfo2;
+ *pCOTypeAttr = pTypeAttr2;
+ hr = S_OK;
+ } else {
+ hr = E_NOINTERFACE;
+ }
+ return hr;
+}
+
static HRESULT
-find_default_source(ole, piid, ppTypeInfo)
- VALUE ole;
- IID *piid;
- ITypeInfo **ppTypeInfo;
+find_default_source_from_typeinfo(
+ ITypeInfo *pTypeInfo,
+ TYPEATTR *pTypeAttr,
+ ITypeInfo **ppTypeInfo)
+{
+ int i = 0;
+ HRESULT hr = E_NOINTERFACE;
+ int flags;
+ HREFTYPE hRefType;
+ /* Enumerate all implemented types of the COCLASS */
+ for (i = 0; i < pTypeAttr->cImplTypes; i++) {
+ hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
+ if (FAILED(hr))
+ continue;
+
+ /*
+ looking for the [default] [source]
+ we just hope that it is a dispinterface :-)
+ */
+ if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
+ (flags & IMPLTYPEFLAG_FSOURCE)) {
+
+ hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
+ i, &hRefType);
+ if (FAILED(hr))
+ continue;
+ hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
+ hRefType, ppTypeInfo);
+ if (SUCCEEDED(hr))
+ break;
+ }
+ }
+ return hr;
+}
+
+static HRESULT
+find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
{
HRESULT hr;
IProvideClassInfo2 *pProvideClassInfo2;
IProvideClassInfo *pProvideClassInfo;
+ void *p;
IDispatch *pDispatch;
ITypeInfo *pTypeInfo;
+ ITypeInfo *pTypeInfo2 = NULL;
TYPEATTR *pTypeAttr;
- int i;
- int iFlags;
- HREFTYPE hRefType;
+ TYPEATTR *pTypeAttr2 = NULL;
struct oledata *pole;
@@ -5931,58 +8069,52 @@ find_default_source(ole, piid, ppTypeInfo)
pDispatch = pole->pDispatch;
hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
&IID_IProvideClassInfo2,
- (void**)&pProvideClassInfo2);
+ &p);
if (SUCCEEDED(hr)) {
+ pProvideClassInfo2 = p;
hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
GUIDKIND_DEFAULT_SOURCE_DISP_IID,
piid);
OLE_RELEASE(pProvideClassInfo2);
- return find_iid(ole, NULL, piid, ppTypeInfo);
+ if (SUCCEEDED(hr)) {
+ hr = find_iid(ole, NULL, piid, ppTypeInfo);
+ }
+ }
+ if (SUCCEEDED(hr)) {
+ return hr;
}
hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
&IID_IProvideClassInfo,
- (void**)&pProvideClassInfo);
- if (FAILED(hr))
- return hr;
-
- hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
- &pTypeInfo);
- OLE_RELEASE(pProvideClassInfo);
+ &p);
+ if (SUCCEEDED(hr)) {
+ pProvideClassInfo = p;
+ hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
+ &pTypeInfo);
+ OLE_RELEASE(pProvideClassInfo);
+ }
+ if (FAILED(hr)) {
+ hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
+ }
if (FAILED(hr))
return hr;
-
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
if (FAILED(hr)) {
OLE_RELEASE(pTypeInfo);
return hr;
}
- /* Enumerate all implemented types of the COCLASS */
- for (i = 0; i < pTypeAttr->cImplTypes; i++) {
- hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &iFlags);
- if (FAILED(hr))
- continue;
-
- /*
- looking for the [default] [source]
- we just hope that it is a dispinterface :-)
- */
- if ((iFlags & IMPLTYPEFLAG_FDEFAULT) &&
- (iFlags & IMPLTYPEFLAG_FSOURCE)) {
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
- i, &hRefType);
- if (FAILED(hr))
- continue;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
- hRefType, ppTypeInfo);
- if (SUCCEEDED(hr))
- break;
- }
+ *ppTypeInfo = 0;
+ hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
+ if (!*ppTypeInfo) {
+ hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
+ if (SUCCEEDED(hr)) {
+ hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
+ OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
+ OLE_RELEASE(pTypeInfo2);
+ }
}
-
OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
OLE_RELEASE(pTypeInfo);
-
/* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
if (!*ppTypeInfo) {
if (SUCCEEDED(hr))
@@ -6004,72 +8136,45 @@ find_default_source(ole, piid, ppTypeInfo)
}
static void
-ole_event_free(poleev)
- struct oleeventdata *poleev;
+ole_event_free(struct oleeventdata *poleev)
{
- ITypeInfo *pti = NULL;
- IConnectionPoint *pcp = NULL;
-
- if (poleev->freed == 1) {
- /*
- * this return create memory leak.
- * but poleev->pEvent->pConnectionPoint shoul'd not be freed
- * until poleev-> freed == 0.
- */
- return;
- }
- if(poleev->pEvent) {
- pti = poleev->pEvent->pTypeInfo;
- if(pti) OLE_RELEASE(pti);
- pcp = poleev->pEvent->pConnectionPoint;
- if(pcp) {
- pcp->lpVtbl->Unadvise(pcp, poleev->pEvent->m_dwCookie);
- OLE_RELEASE(pcp);
- }
- free(poleev);
+ if (poleev->pConnectionPoint) {
+ poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
+ OLE_RELEASE(poleev->pConnectionPoint);
+ poleev->pConnectionPoint = NULL;
}
+ free(poleev);
}
-static VALUE fev_s_allocate _((VALUE));
static VALUE
-fev_s_allocate(klass)
- VALUE klass;
+fev_s_allocate(VALUE klass)
{
VALUE obj;
struct oleeventdata *poleev;
obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev);
- poleev->pEvent = NULL;
+ poleev->dwCookie = 0;
+ poleev->pConnectionPoint = NULL;
+ poleev->event_id = 0;
return obj;
}
-/*
- * call-seq:
- * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
- *
- * Returns OLE event object.
- * The first argument specifies WIN32OLE object.
- * The second argument specifies OLE event name.
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
- */
static VALUE
-fev_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+ev_advise(int argc, VALUE *argv, VALUE self)
{
+
VALUE ole, itf;
struct oledata *pole;
char *pitf;
HRESULT hr;
IID iid;
- ITypeInfo *pTypeInfo;
+ ITypeInfo *pTypeInfo = 0;
IDispatch *pDispatch;
IConnectionPointContainer *pContainer;
IConnectionPoint *pConnectionPoint;
IEVENTSINKOBJ *pIEV;
- DWORD dwCookie = 0;
+ DWORD dwCookie;
struct oleeventdata *poleev;
+ void *p;
rb_secure(4);
rb_scan_args(argc, argv, "11", &ole, &itf);
@@ -6079,7 +8184,7 @@ fev_initialize(argc, argv, self)
}
if(TYPE(itf) != T_NIL) {
- if (ruby_safe_level > 0 && OBJ_TAINTED(itf)) {
+ if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) {
rb_raise(rb_eSecurityError, "Insecure Event Creation - %s",
StringValuePtr(itf));
}
@@ -6098,12 +8203,13 @@ fev_initialize(argc, argv, self)
pDispatch = pole->pDispatch;
hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
&IID_IConnectionPointContainer,
- (void**)&pContainer);
+ &p);
if (FAILED(hr)) {
OLE_RELEASE(pTypeInfo);
ole_raise(hr, rb_eRuntimeError,
"failed to query IConnectionPointContainer");
}
+ pContainer = p;
hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
&iid,
@@ -6123,15 +8229,33 @@ fev_initialize(argc, argv, self)
}
Data_Get_Struct(self, struct oleeventdata, poleev);
- poleev->pEvent = pIEV;
- poleev->pEvent->m_event_id
- = NUM2INT(rb_funcall(ary_ole_event, rb_intern("length"), 0));
- poleev->pEvent->pConnectionPoint = pConnectionPoint;
- poleev->pEvent->pTypeInfo = pTypeInfo;
- poleev->pEvent->m_dwCookie = dwCookie;
- poleev->freed = 0;
- poleev->pEvent->ptr_freed = &(poleev->freed);
- rb_ary_push(ary_ole_event, self);
+ pIEV->m_event_id
+ = NUM2INT(evs_length());
+ pIEV->pTypeInfo = pTypeInfo;
+ poleev->dwCookie = dwCookie;
+ poleev->pConnectionPoint = pConnectionPoint;
+ poleev->event_id = pIEV->m_event_id;
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
+ *
+ * Returns OLE event object.
+ * The first argument specifies WIN32OLE object.
+ * The second argument specifies OLE event name.
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
+ */
+static VALUE
+fev_initialize(int argc, VALUE *argv, VALUE self)
+{
+ ev_advise(argc, argv, self);
+ evs_push(self);
+ rb_ivar_set(self, id_events, rb_ary_new());
+ fev_set_handler(self, Qnil);
return self;
}
@@ -6142,8 +8266,7 @@ fev_initialize(argc, argv, self)
* Translates and dispatches Windows message.
*/
static VALUE
-fev_s_msg_loop(klass)
- VALUE klass;
+fev_s_msg_loop(VALUE klass)
{
ole_msg_loop();
return Qnil;
@@ -6151,35 +8274,34 @@ fev_s_msg_loop(klass)
static void
-add_event_call_back(obj, event, data)
- VALUE obj;
- VALUE event;
- VALUE data;
+add_event_call_back(VALUE obj, VALUE event, VALUE data)
{
- long at;
VALUE events = rb_ivar_get(obj, id_events);
if (NIL_P(events) || TYPE(events) != T_ARRAY) {
events = rb_ary_new();
rb_ivar_set(obj, id_events, events);
}
- at = ole_search_event_at(events, event);
- if (at > -1) {
- rb_ary_delete_at(events, at);
- }
+ ole_delete_event(events, event);
rb_ary_push(events, data);
}
static VALUE
-ev_on_event(argc, argv, self, is_ary_arg)
- int argc;
- VALUE *argv;
- VALUE self;
- VALUE is_ary_arg;
+ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
{
+ struct oleeventdata *poleev;
VALUE event, args, data;
+ Data_Get_Struct(self, struct oleeventdata, poleev);
+ if (poleev->pConnectionPoint == NULL) {
+ rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
+ }
rb_scan_args(argc, argv, "01*", &event, &args);
if(!NIL_P(event)) {
- Check_SafeStr(event);
+ if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) {
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
+ }
+ if (TYPE(event) == T_SYMBOL) {
+ event = rb_sym_to_s(event);
+ }
}
data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
add_event_call_back(self, event, data);
@@ -6192,15 +8314,31 @@ ev_on_event(argc, argv, self, is_ary_arg)
*
* Defines the callback event.
* If argument is omitted, this method defines the callback of all events.
+ * If you want to modify reference argument in callback, return hash in
+ * callback. If you want to return value to OLE server as result of callback
+ * use `return' or :return.
+ *
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
+ * ev = WIN32OLE_EVENT.new(ie)
* ev.on_event("NavigateComplete") {|url| puts url}
+ * ev.on_event() {|ev, *args| puts "#{ev} fired"}
+ *
+ * ev.on_event("BeforeNavigate2") {|*args|
+ * ...
+ * # set true to BeforeNavigate reference argument `Cancel'.
+ * # Cancel is 7-th argument of BeforeNavigate,
+ * # so you can use 6 as key of hash instead of 'Cancel'.
+ * # The argument is counted from 0.
+ * # The hash key of 0 means first argument.)
+ * {:Cancel => true} # or {'Cancel' => true} or {6 => true}
+ * }
+ *
+ * ev.on_event(...) {|*args|
+ * {:return => 1, :xxx => yyy}
+ * }
*/
static VALUE
-fev_on_event(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fev_on_event(int argc, VALUE *argv, VALUE self)
{
return ev_on_event(argc, argv, self, Qfalse);
}
@@ -6211,26 +8349,619 @@ fev_on_event(argc, argv, self)
*
* Defines the callback of event.
* If you want modify argument in callback,
- * you should use this method instead of WIN32OLE_EVENT#on_event.
+ * you could use this method instead of WIN32OLE_EVENT#on_event.
+ *
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ev = WIN32OLE_EVENT.new(ie)
+ * ev.on_event_with_outargs('BeforeNavigate2') {|*args|
+ * args.last[6] = true
+ * }
*/
static VALUE
-fev_on_event_with_outargs(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
+fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
{
return ev_on_event(argc, argv, self, Qtrue);
}
+/*
+ * call-seq:
+ * WIN32OLE_EVENT#off_event([event])
+ *
+ * removes the callback of event.
+ *
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ev = WIN32OLE_EVENT.new(ie)
+ * ev.on_event('BeforeNavigate2') {|*args|
+ * args.last[6] = true
+ * }
+ * ...
+ * ev.off_event('BeforeNavigate2')
+ * ...
+ */
+static VALUE
+fev_off_event(int argc, VALUE *argv, VALUE self)
+{
+ VALUE event = Qnil;
+ VALUE events;
+
+ rb_secure(4);
+ rb_scan_args(argc, argv, "01", &event);
+ if(!NIL_P(event)) {
+ if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) {
+ rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
+ }
+ if (TYPE(event) == T_SYMBOL) {
+ event = rb_sym_to_s(event);
+ }
+ }
+ events = rb_ivar_get(self, id_events);
+ if (NIL_P(events)) {
+ return Qnil;
+ }
+ ole_delete_event(events, event);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_EVENT#unadvise -> nil
+ *
+ * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
+ * does not receive the OLE server event any more.
+ * This method is trial implementation.
+ *
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ev = WIN32OLE_EVENT.new(ie)
+ * ev.on_event() {...}
+ * ...
+ * ev.unadvise
+ *
+ */
+static VALUE
+fev_unadvise(VALUE self)
+{
+ struct oleeventdata *poleev;
+ Data_Get_Struct(self, struct oleeventdata, poleev);
+ if (poleev->pConnectionPoint) {
+ ole_msg_loop();
+ evs_delete(poleev->event_id);
+ poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
+ OLE_RELEASE(poleev->pConnectionPoint);
+ poleev->pConnectionPoint = NULL;
+ }
+ return Qnil;
+}
+
+static VALUE
+evs_push(VALUE ev)
+{
+ return rb_ary_push(ary_ole_event, ev);
+}
+
+static VALUE
+evs_delete(long i)
+{
+ rb_ary_store(ary_ole_event, i, Qnil);
+ return Qnil;
+}
+
+static VALUE
+evs_entry(long i)
+{
+ return rb_ary_entry(ary_ole_event, i);
+}
+
+static VALUE
+evs_length()
+{
+ return rb_funcall(ary_ole_event, rb_intern("length"), 0);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_EVENT#handler=
+ *
+ * sets event handler object. If handler object has onXXX
+ * method according to XXX event, then onXXX method is called
+ * when XXX event occurs.
+ *
+ * If handler object has method_missing and there is no
+ * method according to the event, then method_missing
+ * called and 1-st argument is event name.
+ *
+ * If handler object has onXXX method and there is block
+ * defined by WIN32OLE_EVENT#on_event('XXX'){},
+ * then block is executed but handler object method is not called
+ * when XXX event occurs.
+ *
+ * class Handler
+ * def onStatusTextChange(text)
+ * puts "StatusTextChanged"
+ * end
+ * def onPropertyChange(prop)
+ * puts "PropertyChanged"
+ * end
+ * def method_missing(ev, *arg)
+ * puts "other event #{ev}"
+ * end
+ * end
+ *
+ * handler = Handler.new
+ * ie = WIN32OLE.new('InternetExplorer.Application')
+ * ev = WIN32OLE_EVENT.new(ie)
+ * ev.on_event("StatusTextChange") {|*args|
+ * puts "this block executed."
+ * puts "handler.onStatusTextChange method is not called."
+ * }
+ * ev.handler = handler
+ *
+ */
+static VALUE
+fev_set_handler(VALUE self, VALUE val)
+{
+ return rb_ivar_set(self, rb_intern("handler"), val);
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_EVENT#handler
+ *
+ * returns handler object.
+ *
+ */
+static VALUE
+fev_get_handler(VALUE self)
+{
+ return rb_ivar_get(self, rb_intern("handler"));
+}
+
+static void
+olevariant_free(struct olevariantdata *pvar)
+{
+ VariantClear(&(pvar->realvar));
+ VariantClear(&(pvar->var));
+ free(pvar);
+}
+
+static VALUE
+folevariant_s_allocate(VALUE klass)
+{
+ struct olevariantdata *pvar;
+ VALUE obj;
+ ole_initialize();
+ obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar);
+ VariantInit(&(pvar->var));
+ VariantInit(&(pvar->realvar));
+ return obj;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT.array(ary, vt)
+ *
+ * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
+ * The first argument should be Array object which specifies dimensions
+ * and each size of dimensions of OLE array.
+ * The second argument specifies variant type of the element of OLE array.
+ *
+ * The following create 2 dimensions OLE array. The first dimensions size
+ * is 3, and the second is 4.
+ *
+ * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
+ * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
+ *
+ */
+static VALUE
+folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
+{
+ VALUE obj = Qnil;
+ VARTYPE vt;
+ struct olevariantdata *pvar;
+ SAFEARRAYBOUND *psab = NULL;
+ SAFEARRAY *psa = NULL;
+ UINT dim = 0;
+ UINT i = 0;
+
+ ole_initialize();
+
+ vt = NUM2UINT(vvt);
+ vt = (vt | VT_ARRAY);
+ Check_Type(elems, T_ARRAY);
+ obj = folevariant_s_allocate(klass);
+
+ Data_Get_Struct(obj, struct olevariantdata, pvar);
+ dim = RARRAY_LEN(elems);
+
+ psab = ALLOC_N(SAFEARRAYBOUND, dim);
+
+ if(!psab) {
+ rb_raise(rb_eRuntimeError, "memory allocation error");
+ }
+
+ for (i = 0; i < dim; i++) {
+ psab[i].cElements = FIX2INT(rb_ary_entry(elems, i));
+ psab[i].lLbound = 0;
+ }
+
+ psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
+ if (psa == NULL) {
+ if (psab) free(psab);
+ rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
+ }
+
+ V_VT(&(pvar->var)) = vt;
+ if (vt & VT_BYREF) {
+ V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
+ V_ARRAY(&(pvar->realvar)) = psa;
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
+ } else {
+ V_ARRAY(&(pvar->var)) = psa;
+ }
+ if (psab) free(psab);
+ return obj;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object.
+ *
+ * Returns Ruby object wrapping OLE variant.
+ * The first argument specifies Ruby object to convert OLE variant variable.
+ * The second argument specifies VARIANT type.
+ * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method
+ *
+ * shell = WIN32OLE.new("Shell.Application")
+ * folder = shell.NameSpace("C:\\Windows")
+ * item = folder.ParseName("tmp.txt")
+ * # You can't use Ruby String object to call FolderItem.InvokeVerb.
+ * # Instead, you have to use WIN32OLE_VARIANT object to call the method.
+ * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
+ * item.invokeVerb(shortcut)
+ *
+ */
+static VALUE
+folevariant_initialize(VALUE self, VALUE args)
+{
+ int len = 0;
+ VARIANT var;
+ VALUE val;
+ VALUE vvt;
+ VARTYPE vt;
+ struct olevariantdata *pvar;
+
+ len = RARRAY_LEN(args);
+ if (len < 1 || len > 3) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
+ }
+ VariantInit(&var);
+ val = rb_ary_entry(args, 0);
+
+ if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
+ !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
+ !rb_obj_is_kind_of(val, rb_cTime)) {
+ switch (TYPE(val)) {
+ case T_ARRAY:
+ case T_STRING:
+ case T_FIXNUM:
+ case T_BIGNUM:
+ case T_FLOAT:
+ case T_TRUE:
+ case T_FALSE:
+ case T_NIL:
+ break;
+ default:
+ rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
+ rb_obj_classname(val));
+ }
+ }
+
+ Data_Get_Struct(self, struct olevariantdata, pvar);
+ if (len == 1) {
+ ole_val2variant(val, &(pvar->var));
+ } else {
+ vvt = rb_ary_entry(args, 1);
+ vt = NUM2INT(vvt);
+ ole_val2olevariantdata(val, vt, pvar);
+ }
+ vt = V_VT(&pvar->var);
+ return self;
+}
+
+static SAFEARRAY *
+get_locked_safe_array(VALUE val)
+{
+ struct olevariantdata *pvar;
+ SAFEARRAY *psa = NULL;
+ HRESULT hr;
+ Data_Get_Struct(val, struct olevariantdata, pvar);
+ if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
+ rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
+ }
+ psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
+ if (psa == NULL) {
+ return psa;
+ }
+ hr = SafeArrayLock(psa);
+ if (FAILED(hr)) {
+ ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
+ }
+ return psa;
+}
+
+static long *
+ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
+{
+ long dim;
+ long *pid;
+ long i;
+ dim = SafeArrayGetDim(psa);
+ if (dim != ary_size) {
+ rb_raise(rb_eArgError, "unmatch number of indices");
+ }
+ pid = ALLOC_N(long, dim);
+ if (pid == NULL) {
+ rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
+ }
+ for (i = 0; i < dim; i++) {
+ pid[i] = NUM2INT(ary[i]);
+ }
+ return pid;
+}
+
+static void
+unlock_safe_array(SAFEARRAY *psa)
+{
+ HRESULT hr;
+ hr = SafeArrayUnlock(psa);
+ if (FAILED(hr)) {
+ ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
+ }
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array.
+ *
+ * Returns the element of WIN32OLE_VARIANT object(OLE array).
+ * This method is available only when the variant type of
+ * WIN32OLE_VARIANT object is VT_ARRAY.
+ *
+ * REMARK:
+ * The all indicies should be 0 or natural number and
+ * lower than or equal to max indicies.
+ * (This point is different with Ruby Array indicies.)
+ *
+ * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
+ * p obj[0,0] # => 1
+ * p obj[1,0] # => 4
+ * p obj[2,0] # => WIN32OLERuntimeError
+ * p obj[0, -1] # => WIN32OLERuntimeError
+ *
+ */
+static VALUE
+folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
+{
+ struct olevariantdata *pvar;
+ SAFEARRAY *psa;
+ VALUE val = Qnil;
+ VARIANT variant;
+ long *pid;
+ HRESULT hr;
+
+ Data_Get_Struct(self, struct olevariantdata, pvar);
+ if (!V_ISARRAY(&(pvar->var))) {
+ rb_raise(eWIN32OLERuntimeError,
+ "`[]' is not available for this variant type object");
+ }
+ psa = get_locked_safe_array(self);
+ if (psa == NULL) {
+ return val;
+ }
+
+ pid = ary2safe_array_index(argc, argv, psa);
+
+ VariantInit(&variant);
+ V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF;
+ hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex");
+ }
+ val = ole_variant2val(&variant);
+
+ unlock_safe_array(psa);
+ if (pid) free(pid);
+ return val;
+}
+
+static VOID *
+val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
+{
+ VOID *p = NULL;
+ HRESULT hr = S_OK;
+ ole_val2variant_ex(val, var, vt);
+ if ((vt & ~VT_BYREF) == VT_VARIANT) {
+ p = var;
+ } else {
+ if ( (vt & ~VT_BYREF) != V_VT(var)) {
+ hr = VariantChangeTypeEx(var, var,
+ cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
+ if (FAILED(hr)) {
+ ole_raise(hr, rb_eRuntimeError, "failed to change type");
+ }
+ }
+ p = get_ptr_of_variant(var);
+ }
+ if (p == NULL) {
+ rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
+ }
+ return p;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array
+ *
+ * Set the element of WIN32OLE_VARIANT object(OLE array) to val.
+ * This method is available only when the variant type of
+ * WIN32OLE_VARIANT object is VT_ARRAY.
+ *
+ * REMARK:
+ * The all indicies should be 0 or natural number and
+ * lower than or equal to max indicies.
+ * (This point is different with Ruby Array indicies.)
+ *
+ * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
+ * obj[0,0] = 7
+ * obj[1,0] = 8
+ * p obj.value # => [[7,2,3], [8,5,6]]
+ * obj[2,0] = 9 # => WIN32OLERuntimeError
+ * obj[0, -1] = 9 # => WIN32OLERuntimeError
+ *
+ */
+static VALUE
+folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
+{
+ struct olevariantdata *pvar;
+ SAFEARRAY *psa;
+ VARIANT var;
+ VARTYPE vt;
+ long *pid;
+ HRESULT hr;
+ VOID *p = NULL;
+
+ Data_Get_Struct(self, struct olevariantdata, pvar);
+ if (!V_ISARRAY(&(pvar->var))) {
+ rb_raise(eWIN32OLERuntimeError,
+ "`[]' is not available for this variant type object");
+ }
+ psa = get_locked_safe_array(self);
+ if (psa == NULL) {
+ rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
+ }
+
+ pid = ary2safe_array_index(argc-1, argv, psa);
+
+ VariantInit(&var);
+ vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
+ p = val2variant_ptr(argv[argc-1], &var, vt);
+ if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
+ (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
+ rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
+ }
+ hr = SafeArrayPutElement(psa, pid, p);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
+ }
+
+ unlock_safe_array(psa);
+ if (pid) free(pid);
+ return argv[argc-1];
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT.value #=> Ruby object.
+ *
+ * Returns Ruby object value from OLE variant.
+ * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR)
+ * obj.value # => "1" (not Fixnum object, but String object "1")
+ *
+ */
+static VALUE
+folevariant_value(VALUE self)
+{
+ struct olevariantdata *pvar;
+ VALUE val = Qnil;
+ VARTYPE vt;
+ int dim;
+ SAFEARRAY *psa;
+ Data_Get_Struct(self, struct olevariantdata, pvar);
+
+ val = ole_variant2val(&(pvar->var));
+ vt = V_VT(&(pvar->var));
+
+ if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) {
+ if (vt & VT_BYREF) {
+ psa = *V_ARRAYREF(&(pvar->var));
+ } else {
+ psa = V_ARRAY(&(pvar->var));
+ }
+ if (!psa) {
+ return val;
+ }
+ dim = SafeArrayGetDim(psa);
+ if (dim == 1) {
+ val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*"));
+ }
+ }
+ return val;
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT.vartype #=> OLE variant type.
+ *
+ * Returns OLE variant type.
+ * obj = WIN32OLE_VARIANT.new("string")
+ * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
+ *
+ */
+static VALUE
+folevariant_vartype(VALUE self)
+{
+ struct olevariantdata *pvar;
+ Data_Get_Struct(self, struct olevariantdata, pvar);
+ return INT2FIX(V_VT(&pvar->var));
+}
+
+/*
+ * call-seq:
+ * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
+ *
+ * Sets variant value to val. If the val type does not match variant value
+ * type(vartype), then val is changed to match variant value type(vartype)
+ * before setting val.
+ * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
+ * If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
+ *
+ * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
+ * obj.value = 3.2 # 3.2 is changed to 3 when setting value.
+ * p obj.value # => 3
+ */
+static VALUE
+folevariant_set_value(VALUE self, VALUE val)
+{
+ struct olevariantdata *pvar;
+ VARTYPE vt;
+ Data_Get_Struct(self, struct olevariantdata, pvar);
+ vt = V_VT(&(pvar->var));
+ if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) {
+ rb_raise(eWIN32OLERuntimeError,
+ "`value=' is not available for this variant type object");
+ }
+ ole_val2olevariantdata(val, vt, pvar);
+ return Qnil;
+}
+
+static void
+init_enc2cp()
+{
+ enc2cp_table = st_init_numtable();
+}
+
+static void
+free_enc2cp()
+{
+ st_free_table(enc2cp_table);
+}
void
Init_win32ole()
{
- rb_global_variable(&ary_ole_event);
ary_ole_event = rb_ary_new();
+ rb_gc_register_mark_object(ary_ole_event);
id_events = rb_intern("events");
- rb_global_variable(&com_hash);
com_vtbl.QueryInterface = QueryInterface;
com_vtbl.AddRef = AddRef;
com_vtbl.Release = Release;
@@ -6245,8 +8976,9 @@ Init_win32ole()
message_filter.HandleInComingCall = mf_HandleInComingCall;
message_filter.RetryRejectedCall = mf_RetryRejectedCall;
message_filter.MessagePending = mf_MessagePending;
-
+
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
+ rb_gc_register_mark_object(com_hash);
cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
@@ -6262,16 +8994,18 @@ Init_win32ole()
rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1);
rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0);
rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1);
-
+ rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0);
+ rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1);
+ rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0);
rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1);
- rb_define_method(cWIN32OLE, "[]", fole_getproperty, -1);
+ rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1);
rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3);
rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3);
rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3);
/* support propput method that takes an argument */
- rb_define_method(cWIN32OLE, "[]=", fole_setproperty, -1);
+ rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1);
rb_define_method(cWIN32OLE, "ole_free", fole_free, 0);
@@ -6288,19 +9022,30 @@ Init_win32ole()
rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1);
rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method");
- rb_define_method(cWIN32OLE, "ole_obj_help", fole_obj_help, 0);
+ rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0);
+ rb_define_method(cWIN32OLE, "ole_type", fole_type, 0);
+ rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type");
+ rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0);
+ rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1);
+ rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1);
rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION));
rb_define_const(cWIN32OLE, "ARGV", rb_ary_new());
- rb_define_const(cWIN32OLE, "CP_ACP" ,INT2FIX(CP_ACP));
- rb_define_const(cWIN32OLE, "CP_OEMCP" ,INT2FIX(CP_OEMCP));
- rb_define_const(cWIN32OLE, "CP_MACCP" ,INT2FIX(CP_MACCP));
- rb_define_const(cWIN32OLE, "CP_THREAD_ACP",INT2FIX(CP_THREAD_ACP));
- rb_define_const(cWIN32OLE, "CP_SYMBOL" ,INT2FIX(CP_SYMBOL));
- rb_define_const(cWIN32OLE, "CP_UTF7" ,INT2FIX(CP_UTF7));
- rb_define_const(cWIN32OLE, "CP_UTF8" ,INT2FIX(CP_UTF8));
+
+ rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP));
+ rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP));
+ rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP));
+ rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP));
+ rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL));
+ rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7));
+ rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8));
+
+ rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT));
+ rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT));
mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT");
+ rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY));
+ rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL));
rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2));
rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4));
rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4));
@@ -6319,10 +9064,30 @@ Init_win32ole()
rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1));
rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2));
rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4));
+#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
+ rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8));
+ rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8));
+#endif
rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT));
rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT));
rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY));
rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF));
+
+ cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject);
+ rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2);
+ rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0);
+ rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types");
+ rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0);
+ rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0);
+ rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name");
+ rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0);
cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject);
rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1);
@@ -6336,7 +9101,6 @@ Init_win32ole()
rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0);
rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0);
rb_define_alias(cWIN32OLE_TYPE, "to_s", "name");
-
rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0);
rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0);
rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0);
@@ -6345,7 +9109,13 @@ Init_win32ole()
rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0);
rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0);
rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0);
- rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, -1);
+ rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0);
+ rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0);
+ rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0);
+ rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0);
+ rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0);
+ rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0);
+ rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0);
cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject);
rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0);
@@ -6355,12 +9125,12 @@ Init_win32ole()
rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0);
rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0);
rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0);
+ rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0);
rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name");
cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject);
rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate);
rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2);
-
rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0);
rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0);
rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0);
@@ -6379,6 +9149,7 @@ Init_win32ole()
rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0);
rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0);
rb_define_alias(cWIN32OLE_METHOD, "to_s", "name");
+ rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0);
cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject);
rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0);
@@ -6390,14 +9161,35 @@ Init_win32ole()
rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0);
rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0);
rb_define_alias(cWIN32OLE_PARAM, "to_s", "name");
+ rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0);
cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
-
+ rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
- rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
-
rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
- eWIN32OLE_RUNTIME_ERROR = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError);
+ rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
+ rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
+ rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
+ rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
+
+ cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
+ rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
+ rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
+ rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
+ rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
+ rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
+ rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
+ rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
+ rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
+ rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY)));
+ rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL)));
+ rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH)));
+
+ eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError);
+
+ init_enc2cp();
+ atexit((void (*)(void))free_enc2cp);
+ ole_init_cp();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment