win32ole 1.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +56 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/win32ole/depend +12 -0
- data/ext/win32ole/extconf.rb +45 -0
- data/ext/win32ole/sample/excel1.rb +37 -0
- data/ext/win32ole/sample/excel2.rb +31 -0
- data/ext/win32ole/sample/excel3.rb +21 -0
- data/ext/win32ole/sample/ie.rb +12 -0
- data/ext/win32ole/sample/ieconst.rb +33 -0
- data/ext/win32ole/sample/ienavi.rb +41 -0
- data/ext/win32ole/sample/ienavi2.rb +41 -0
- data/ext/win32ole/sample/oledirs.rb +24 -0
- data/ext/win32ole/sample/olegen.rb +348 -0
- data/ext/win32ole/sample/xml.rb +7307 -0
- data/ext/win32ole/win32ole.c +4140 -0
- data/ext/win32ole/win32ole.h +155 -0
- data/ext/win32ole/win32ole_error.c +84 -0
- data/ext/win32ole/win32ole_error.h +9 -0
- data/ext/win32ole/win32ole_event.c +1277 -0
- data/ext/win32ole/win32ole_event.h +6 -0
- data/ext/win32ole/win32ole_method.c +950 -0
- data/ext/win32ole/win32ole_method.h +16 -0
- data/ext/win32ole/win32ole_param.c +438 -0
- data/ext/win32ole/win32ole_param.h +8 -0
- data/ext/win32ole/win32ole_record.c +604 -0
- data/ext/win32ole/win32ole_record.h +10 -0
- data/ext/win32ole/win32ole_type.c +915 -0
- data/ext/win32ole/win32ole_type.h +8 -0
- data/ext/win32ole/win32ole_typelib.c +844 -0
- data/ext/win32ole/win32ole_typelib.h +11 -0
- data/ext/win32ole/win32ole_variable.c +380 -0
- data/ext/win32ole/win32ole_variable.h +8 -0
- data/ext/win32ole/win32ole_variant.c +733 -0
- data/ext/win32ole/win32ole_variant.h +9 -0
- data/ext/win32ole/win32ole_variant_m.c +149 -0
- data/ext/win32ole/win32ole_variant_m.h +7 -0
- data/lib/win32ole.rb +33 -0
- data/lib/win32ole/property.rb +17 -0
- data/win32ole.gemspec +22 -0
- metadata +91 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
#ifndef WIN32OLE_H
|
2
|
+
#define WIN32OLE_H 1
|
3
|
+
#include "ruby/ruby.h"
|
4
|
+
#include "ruby/st.h"
|
5
|
+
#include "ruby/encoding.h"
|
6
|
+
|
7
|
+
#define GNUC_OLDER_3_4_4 \
|
8
|
+
((__GNUC__ < 3) || \
|
9
|
+
((__GNUC__ <= 3) && (__GNUC_MINOR__ < 4)) || \
|
10
|
+
((__GNUC__ <= 3) && (__GNUC_MINOR__ <= 4) && (__GNUC_PATCHLEVEL__ <= 4)))
|
11
|
+
|
12
|
+
#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
|
13
|
+
#ifndef NONAMELESSUNION
|
14
|
+
#define NONAMELESSUNION 1
|
15
|
+
#endif
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#include <ctype.h>
|
19
|
+
|
20
|
+
#include <windows.h>
|
21
|
+
#include <ocidl.h>
|
22
|
+
#include <olectl.h>
|
23
|
+
#include <ole2.h>
|
24
|
+
#if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE)
|
25
|
+
#include <mlang.h>
|
26
|
+
#endif
|
27
|
+
#include <stdlib.h>
|
28
|
+
#include <math.h>
|
29
|
+
#ifdef HAVE_STDARG_PROTOTYPES
|
30
|
+
#include <stdarg.h>
|
31
|
+
#define va_init_list(a,b) va_start(a,b)
|
32
|
+
#else
|
33
|
+
#include <varargs.h>
|
34
|
+
#define va_init_list(a,b) va_start(a)
|
35
|
+
#endif
|
36
|
+
#include <objidl.h>
|
37
|
+
|
38
|
+
#define DOUT fprintf(stderr,"%s(%d)\n", __FILE__, __LINE__)
|
39
|
+
#define DOUTS(x) fprintf(stderr,"%s(%d):" #x "=%s\n",__FILE__, __LINE__,x)
|
40
|
+
#define DOUTMSG(x) fprintf(stderr, "%s(%d):" #x "\n",__FILE__, __LINE__)
|
41
|
+
#define DOUTI(x) fprintf(stderr, "%s(%d):" #x "=%d\n",__FILE__, __LINE__,x)
|
42
|
+
#define DOUTD(x) fprintf(stderr, "%s(%d):" #x "=%f\n",__FILE__, __LINE__,x)
|
43
|
+
|
44
|
+
#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
|
45
|
+
#define V_UNION1(X, Y) ((X)->u.Y)
|
46
|
+
#else
|
47
|
+
#define V_UNION1(X, Y) ((X)->Y)
|
48
|
+
#endif
|
49
|
+
|
50
|
+
#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
|
51
|
+
#undef V_UNION
|
52
|
+
#define V_UNION(X,Y) ((X)->n1.n2.n3.Y)
|
53
|
+
|
54
|
+
#undef V_VT
|
55
|
+
#define V_VT(X) ((X)->n1.n2.vt)
|
56
|
+
|
57
|
+
#undef V_BOOL
|
58
|
+
#define V_BOOL(X) V_UNION(X,boolVal)
|
59
|
+
#endif
|
60
|
+
|
61
|
+
#ifndef V_I1REF
|
62
|
+
#define V_I1REF(X) V_UNION(X, pcVal)
|
63
|
+
#endif
|
64
|
+
|
65
|
+
#ifndef V_UI2REF
|
66
|
+
#define V_UI2REF(X) V_UNION(X, puiVal)
|
67
|
+
#endif
|
68
|
+
|
69
|
+
#ifndef V_INT
|
70
|
+
#define V_INT(X) V_UNION(X, intVal)
|
71
|
+
#endif
|
72
|
+
|
73
|
+
#ifndef V_INTREF
|
74
|
+
#define V_INTREF(X) V_UNION(X, pintVal)
|
75
|
+
#endif
|
76
|
+
|
77
|
+
#ifndef V_UINT
|
78
|
+
#define V_UINT(X) V_UNION(X, uintVal)
|
79
|
+
#endif
|
80
|
+
|
81
|
+
#ifndef V_UINTREF
|
82
|
+
#define V_UINTREF(X) V_UNION(X, puintVal)
|
83
|
+
#endif
|
84
|
+
|
85
|
+
#ifdef HAVE_LONG_LONG
|
86
|
+
#define I8_2_NUM LL2NUM
|
87
|
+
#define UI8_2_NUM ULL2NUM
|
88
|
+
#define NUM2I8 RB_NUM2LL
|
89
|
+
#define NUM2UI8 RB_NUM2ULL
|
90
|
+
#else
|
91
|
+
#define I8_2_NUM RB_INT2NUM
|
92
|
+
#define UI8_2_NUM RB_UINT2NUM
|
93
|
+
#define NUM2I8 RB_NUM2INT
|
94
|
+
#define NUM2UI8 RB_NUM2UINT
|
95
|
+
#endif
|
96
|
+
|
97
|
+
#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
|
98
|
+
#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
|
99
|
+
#define OLE_FREE(x) {\
|
100
|
+
if(ole_initialized() == TRUE) {\
|
101
|
+
if(x) {\
|
102
|
+
OLE_RELEASE(x);\
|
103
|
+
(x) = 0;\
|
104
|
+
}\
|
105
|
+
}\
|
106
|
+
}
|
107
|
+
|
108
|
+
#define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y)))
|
109
|
+
#define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y)))
|
110
|
+
|
111
|
+
struct oledata {
|
112
|
+
IDispatch *pDispatch;
|
113
|
+
};
|
114
|
+
|
115
|
+
VALUE cWIN32OLE;
|
116
|
+
LCID cWIN32OLE_lcid;
|
117
|
+
|
118
|
+
struct oledata *oledata_get_struct(VALUE obj);
|
119
|
+
LPWSTR ole_vstr2wc(VALUE vstr);
|
120
|
+
LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey);
|
121
|
+
LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey);
|
122
|
+
VALUE reg_enum_key(HKEY hkey, DWORD i);
|
123
|
+
VALUE reg_get_val(HKEY hkey, const char *subkey);
|
124
|
+
VALUE reg_get_val2(HKEY hkey, const char *subkey);
|
125
|
+
void ole_initialize(void);
|
126
|
+
VALUE default_inspect(VALUE self, const char *class_name);
|
127
|
+
char *ole_wc2mb(LPWSTR pw);
|
128
|
+
VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree);
|
129
|
+
|
130
|
+
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
|
131
|
+
|
132
|
+
BOOL ole_initialized(void);
|
133
|
+
HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
|
134
|
+
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
|
135
|
+
VALUE make_inspect(const char *class_name, VALUE detail);
|
136
|
+
void ole_val2variant(VALUE val, VARIANT *var);
|
137
|
+
void ole_val2variant2(VALUE val, VARIANT *var);
|
138
|
+
void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
|
139
|
+
VALUE ole_variant2val(VARIANT *pvar);
|
140
|
+
HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
|
141
|
+
VOID *val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
|
142
|
+
HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib);
|
143
|
+
|
144
|
+
#include "win32ole_variant_m.h"
|
145
|
+
#include "win32ole_typelib.h"
|
146
|
+
#include "win32ole_type.h"
|
147
|
+
#include "win32ole_variable.h"
|
148
|
+
#include "win32ole_method.h"
|
149
|
+
#include "win32ole_param.h"
|
150
|
+
#include "win32ole_event.h"
|
151
|
+
#include "win32ole_variant.h"
|
152
|
+
#include "win32ole_record.h"
|
153
|
+
#include "win32ole_error.h"
|
154
|
+
|
155
|
+
#endif
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#include "win32ole.h"
|
2
|
+
|
3
|
+
static VALUE ole_hresult2msg(HRESULT hr);
|
4
|
+
|
5
|
+
static VALUE
|
6
|
+
ole_hresult2msg(HRESULT hr)
|
7
|
+
{
|
8
|
+
VALUE msg = Qnil;
|
9
|
+
char *p_msg = NULL;
|
10
|
+
char *term = NULL;
|
11
|
+
DWORD dwCount;
|
12
|
+
|
13
|
+
char strhr[100];
|
14
|
+
sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr);
|
15
|
+
msg = rb_str_new2(strhr);
|
16
|
+
dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
17
|
+
FORMAT_MESSAGE_FROM_SYSTEM |
|
18
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
19
|
+
NULL, hr,
|
20
|
+
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
21
|
+
(LPTSTR)&p_msg, 0, NULL);
|
22
|
+
if (dwCount == 0) {
|
23
|
+
dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
24
|
+
FORMAT_MESSAGE_FROM_SYSTEM |
|
25
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
26
|
+
NULL, hr, cWIN32OLE_lcid,
|
27
|
+
(LPTSTR)&p_msg, 0, NULL);
|
28
|
+
}
|
29
|
+
if (dwCount > 0) {
|
30
|
+
term = p_msg + strlen(p_msg);
|
31
|
+
while (p_msg < term) {
|
32
|
+
term--;
|
33
|
+
if (*term == '\r' || *term == '\n')
|
34
|
+
*term = '\0';
|
35
|
+
else break;
|
36
|
+
}
|
37
|
+
if (p_msg[0] != '\0') {
|
38
|
+
rb_str_cat2(msg, p_msg);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
LocalFree(p_msg);
|
42
|
+
return msg;
|
43
|
+
}
|
44
|
+
|
45
|
+
void
|
46
|
+
ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...)
|
47
|
+
{
|
48
|
+
va_list args;
|
49
|
+
VALUE msg;
|
50
|
+
VALUE err_msg;
|
51
|
+
va_init_list(args, fmt);
|
52
|
+
msg = rb_vsprintf(fmt, args);
|
53
|
+
va_end(args);
|
54
|
+
|
55
|
+
err_msg = ole_hresult2msg(hr);
|
56
|
+
if(err_msg != Qnil) {
|
57
|
+
rb_str_cat2(msg, "\n");
|
58
|
+
rb_str_append(msg, err_msg);
|
59
|
+
}
|
60
|
+
rb_exc_raise(rb_exc_new_str(ecs, msg));
|
61
|
+
}
|
62
|
+
|
63
|
+
void
|
64
|
+
Init_win32ole_error(void)
|
65
|
+
{
|
66
|
+
/*
|
67
|
+
* Document-class: WIN32OLERuntimeError
|
68
|
+
*
|
69
|
+
* Raised when OLE processing failed.
|
70
|
+
*
|
71
|
+
* EX:
|
72
|
+
*
|
73
|
+
* obj = WIN32OLE.new("NonExistProgID")
|
74
|
+
*
|
75
|
+
* raises the exception:
|
76
|
+
*
|
77
|
+
* WIN32OLERuntimeError: unknown OLE server: `NonExistProgID'
|
78
|
+
* HRESULT error code:0x800401f3
|
79
|
+
* Invalid class string
|
80
|
+
*
|
81
|
+
*/
|
82
|
+
eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError);
|
83
|
+
eWIN32OLEQueryInterfaceError = rb_define_class("WIN32OLEQueryInterfaceError", eWIN32OLERuntimeError);
|
84
|
+
}
|
@@ -0,0 +1,1277 @@
|
|
1
|
+
#include "win32ole.h"
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Document-class: WIN32OLE_EVENT
|
5
|
+
*
|
6
|
+
* <code>WIN32OLE_EVENT</code> objects controls OLE event.
|
7
|
+
*/
|
8
|
+
|
9
|
+
RUBY_EXTERN void rb_write_error_str(VALUE mesg);
|
10
|
+
|
11
|
+
typedef struct {
|
12
|
+
struct IEventSinkVtbl * lpVtbl;
|
13
|
+
} IEventSink, *PEVENTSINK;
|
14
|
+
|
15
|
+
typedef struct IEventSinkVtbl IEventSinkVtbl;
|
16
|
+
|
17
|
+
struct IEventSinkVtbl {
|
18
|
+
STDMETHOD(QueryInterface)(
|
19
|
+
PEVENTSINK,
|
20
|
+
REFIID,
|
21
|
+
LPVOID *);
|
22
|
+
STDMETHOD_(ULONG, AddRef)(PEVENTSINK);
|
23
|
+
STDMETHOD_(ULONG, Release)(PEVENTSINK);
|
24
|
+
|
25
|
+
STDMETHOD(GetTypeInfoCount)(
|
26
|
+
PEVENTSINK,
|
27
|
+
UINT *);
|
28
|
+
STDMETHOD(GetTypeInfo)(
|
29
|
+
PEVENTSINK,
|
30
|
+
UINT,
|
31
|
+
LCID,
|
32
|
+
ITypeInfo **);
|
33
|
+
STDMETHOD(GetIDsOfNames)(
|
34
|
+
PEVENTSINK,
|
35
|
+
REFIID,
|
36
|
+
OLECHAR **,
|
37
|
+
UINT,
|
38
|
+
LCID,
|
39
|
+
DISPID *);
|
40
|
+
STDMETHOD(Invoke)(
|
41
|
+
PEVENTSINK,
|
42
|
+
DISPID,
|
43
|
+
REFIID,
|
44
|
+
LCID,
|
45
|
+
WORD,
|
46
|
+
DISPPARAMS *,
|
47
|
+
VARIANT *,
|
48
|
+
EXCEPINFO *,
|
49
|
+
UINT *);
|
50
|
+
};
|
51
|
+
|
52
|
+
typedef struct tagIEVENTSINKOBJ {
|
53
|
+
const IEventSinkVtbl *lpVtbl;
|
54
|
+
DWORD m_cRef;
|
55
|
+
IID m_iid;
|
56
|
+
long m_event_id;
|
57
|
+
ITypeInfo *pTypeInfo;
|
58
|
+
}IEVENTSINKOBJ, *PIEVENTSINKOBJ;
|
59
|
+
|
60
|
+
struct oleeventdata {
|
61
|
+
DWORD dwCookie;
|
62
|
+
IConnectionPoint *pConnectionPoint;
|
63
|
+
IDispatch *pDispatch;
|
64
|
+
long event_id;
|
65
|
+
};
|
66
|
+
|
67
|
+
static VALUE ary_ole_event;
|
68
|
+
static ID id_events;
|
69
|
+
|
70
|
+
VALUE cWIN32OLE_EVENT;
|
71
|
+
|
72
|
+
STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID*);
|
73
|
+
STDMETHODIMP_(ULONG) EVENTSINK_AddRef(PEVENTSINK);
|
74
|
+
STDMETHODIMP_(ULONG) EVENTSINK_Release(PEVENTSINK);
|
75
|
+
STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK, UINT*);
|
76
|
+
STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK, UINT, LCID, ITypeInfo**);
|
77
|
+
STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK, REFIID, OLECHAR**, UINT, LCID, DISPID*);
|
78
|
+
STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK, DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
|
79
|
+
|
80
|
+
static const IEventSinkVtbl vtEventSink = {
|
81
|
+
EVENTSINK_QueryInterface,
|
82
|
+
EVENTSINK_AddRef,
|
83
|
+
EVENTSINK_Release,
|
84
|
+
EVENTSINK_GetTypeInfoCount,
|
85
|
+
EVENTSINK_GetTypeInfo,
|
86
|
+
EVENTSINK_GetIDsOfNames,
|
87
|
+
EVENTSINK_Invoke,
|
88
|
+
};
|
89
|
+
|
90
|
+
void EVENTSINK_Destructor(PIEVENTSINKOBJ);
|
91
|
+
static void ole_val2ptr_variant(VALUE val, VARIANT *var);
|
92
|
+
static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
|
93
|
+
static VALUE hash2result(VALUE hash);
|
94
|
+
static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
|
95
|
+
static VALUE exec_callback(VALUE arg);
|
96
|
+
static VALUE rescue_callback(VALUE arg);
|
97
|
+
static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
|
98
|
+
static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
|
99
|
+
static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
|
100
|
+
static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
|
101
|
+
static long ole_search_event_at(VALUE ary, VALUE ev);
|
102
|
+
static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
|
103
|
+
static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
|
104
|
+
static void ole_delete_event(VALUE ary, VALUE ev);
|
105
|
+
static void oleevent_free(void *ptr);
|
106
|
+
static size_t oleevent_size(const void *ptr);
|
107
|
+
static VALUE fev_s_allocate(VALUE klass);
|
108
|
+
static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
|
109
|
+
static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
|
110
|
+
static void ole_msg_loop(void);
|
111
|
+
static VALUE fev_s_msg_loop(VALUE klass);
|
112
|
+
static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
|
113
|
+
static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
|
114
|
+
static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
|
115
|
+
static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
|
116
|
+
static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
|
117
|
+
static VALUE fev_unadvise(VALUE self);
|
118
|
+
static VALUE fev_set_handler(VALUE self, VALUE val);
|
119
|
+
static VALUE fev_get_handler(VALUE self);
|
120
|
+
static VALUE evs_push(VALUE ev);
|
121
|
+
static VALUE evs_delete(long i);
|
122
|
+
static VALUE evs_entry(long i);
|
123
|
+
static long evs_length(void);
|
124
|
+
|
125
|
+
|
126
|
+
static const rb_data_type_t oleevent_datatype = {
|
127
|
+
"win32ole_event",
|
128
|
+
{NULL, oleevent_free, oleevent_size,},
|
129
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
130
|
+
};
|
131
|
+
|
132
|
+
STDMETHODIMP EVENTSINK_Invoke(
|
133
|
+
PEVENTSINK pEventSink,
|
134
|
+
DISPID dispid,
|
135
|
+
REFIID riid,
|
136
|
+
LCID lcid,
|
137
|
+
WORD wFlags,
|
138
|
+
DISPPARAMS *pdispparams,
|
139
|
+
VARIANT *pvarResult,
|
140
|
+
EXCEPINFO *pexcepinfo,
|
141
|
+
UINT *puArgErr
|
142
|
+
) {
|
143
|
+
|
144
|
+
HRESULT hr;
|
145
|
+
BSTR bstr;
|
146
|
+
unsigned int count;
|
147
|
+
unsigned int i;
|
148
|
+
ITypeInfo *pTypeInfo;
|
149
|
+
VARIANT *pvar;
|
150
|
+
VALUE ary, obj, event, args, outargv, ev, result;
|
151
|
+
VALUE handler = Qnil;
|
152
|
+
VALUE arg[3];
|
153
|
+
VALUE mid;
|
154
|
+
VALUE is_outarg = Qfalse;
|
155
|
+
BOOL is_default_handler = FALSE;
|
156
|
+
int state;
|
157
|
+
|
158
|
+
PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
|
159
|
+
pTypeInfo = pEV->pTypeInfo;
|
160
|
+
obj = evs_entry(pEV->m_event_id);
|
161
|
+
if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
|
162
|
+
return NOERROR;
|
163
|
+
}
|
164
|
+
|
165
|
+
ary = rb_ivar_get(obj, id_events);
|
166
|
+
if (NIL_P(ary) || !RB_TYPE_P(ary, T_ARRAY)) {
|
167
|
+
return NOERROR;
|
168
|
+
}
|
169
|
+
hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
|
170
|
+
&bstr, 1, &count);
|
171
|
+
if (FAILED(hr)) {
|
172
|
+
return NOERROR;
|
173
|
+
}
|
174
|
+
ev = WC2VSTR(bstr);
|
175
|
+
event = ole_search_event(ary, ev, &is_default_handler);
|
176
|
+
if (RB_TYPE_P(event, T_ARRAY)) {
|
177
|
+
handler = rb_ary_entry(event, 0);
|
178
|
+
mid = rb_intern("call");
|
179
|
+
is_outarg = rb_ary_entry(event, 3);
|
180
|
+
} else {
|
181
|
+
handler = rb_ivar_get(obj, rb_intern("handler"));
|
182
|
+
if (handler == Qnil) {
|
183
|
+
return NOERROR;
|
184
|
+
}
|
185
|
+
mid = ole_search_handler_method(handler, ev, &is_default_handler);
|
186
|
+
}
|
187
|
+
if (handler == Qnil || mid == Qnil) {
|
188
|
+
return NOERROR;
|
189
|
+
}
|
190
|
+
|
191
|
+
args = rb_ary_new();
|
192
|
+
if (is_default_handler) {
|
193
|
+
rb_ary_push(args, ev);
|
194
|
+
}
|
195
|
+
|
196
|
+
/* make argument of event handler */
|
197
|
+
for (i = 0; i < pdispparams->cArgs; ++i) {
|
198
|
+
pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
|
199
|
+
rb_ary_push(args, ole_variant2val(pvar));
|
200
|
+
}
|
201
|
+
outargv = Qnil;
|
202
|
+
if (is_outarg == Qtrue) {
|
203
|
+
outargv = rb_ary_new();
|
204
|
+
rb_ary_push(args, outargv);
|
205
|
+
}
|
206
|
+
|
207
|
+
/*
|
208
|
+
* if exception raised in event callback,
|
209
|
+
* then you receive cfp consistency error.
|
210
|
+
* to avoid this error we use begin rescue end.
|
211
|
+
* and the exception raised then error message print
|
212
|
+
* and exit ruby process by Win32OLE itself.
|
213
|
+
*/
|
214
|
+
arg[0] = handler;
|
215
|
+
arg[1] = mid;
|
216
|
+
arg[2] = args;
|
217
|
+
result = rb_protect(exec_callback, (VALUE)arg, &state);
|
218
|
+
if (state != 0) {
|
219
|
+
rescue_callback(Qnil);
|
220
|
+
}
|
221
|
+
if(RB_TYPE_P(result, T_HASH)) {
|
222
|
+
hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
|
223
|
+
result = hash2result(result);
|
224
|
+
}else if (is_outarg == Qtrue && RB_TYPE_P(outargv, T_ARRAY)) {
|
225
|
+
ary2ptr_dispparams(outargv, pdispparams);
|
226
|
+
}
|
227
|
+
|
228
|
+
if (pvarResult) {
|
229
|
+
VariantInit(pvarResult);
|
230
|
+
ole_val2variant(result, pvarResult);
|
231
|
+
}
|
232
|
+
|
233
|
+
return NOERROR;
|
234
|
+
}
|
235
|
+
|
236
|
+
STDMETHODIMP
|
237
|
+
EVENTSINK_QueryInterface(
|
238
|
+
PEVENTSINK pEV,
|
239
|
+
REFIID iid,
|
240
|
+
LPVOID* ppv
|
241
|
+
) {
|
242
|
+
if (IsEqualIID(iid, &IID_IUnknown) ||
|
243
|
+
IsEqualIID(iid, &IID_IDispatch) ||
|
244
|
+
IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) {
|
245
|
+
*ppv = pEV;
|
246
|
+
}
|
247
|
+
else {
|
248
|
+
*ppv = NULL;
|
249
|
+
return E_NOINTERFACE;
|
250
|
+
}
|
251
|
+
((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
|
252
|
+
return NOERROR;
|
253
|
+
}
|
254
|
+
|
255
|
+
STDMETHODIMP_(ULONG)
|
256
|
+
EVENTSINK_AddRef(
|
257
|
+
PEVENTSINK pEV
|
258
|
+
){
|
259
|
+
PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
|
260
|
+
return ++pEVObj->m_cRef;
|
261
|
+
}
|
262
|
+
|
263
|
+
STDMETHODIMP_(ULONG) EVENTSINK_Release(
|
264
|
+
PEVENTSINK pEV
|
265
|
+
) {
|
266
|
+
PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
|
267
|
+
--pEVObj->m_cRef;
|
268
|
+
if(pEVObj->m_cRef != 0)
|
269
|
+
return pEVObj->m_cRef;
|
270
|
+
EVENTSINK_Destructor(pEVObj);
|
271
|
+
return 0;
|
272
|
+
}
|
273
|
+
|
274
|
+
STDMETHODIMP EVENTSINK_GetTypeInfoCount(
|
275
|
+
PEVENTSINK pEV,
|
276
|
+
UINT *pct
|
277
|
+
) {
|
278
|
+
*pct = 0;
|
279
|
+
return NOERROR;
|
280
|
+
}
|
281
|
+
|
282
|
+
STDMETHODIMP EVENTSINK_GetTypeInfo(
|
283
|
+
PEVENTSINK pEV,
|
284
|
+
UINT info,
|
285
|
+
LCID lcid,
|
286
|
+
ITypeInfo **pInfo
|
287
|
+
) {
|
288
|
+
*pInfo = NULL;
|
289
|
+
return DISP_E_BADINDEX;
|
290
|
+
}
|
291
|
+
|
292
|
+
STDMETHODIMP EVENTSINK_GetIDsOfNames(
|
293
|
+
PEVENTSINK pEventSink,
|
294
|
+
REFIID riid,
|
295
|
+
OLECHAR **szNames,
|
296
|
+
UINT cNames,
|
297
|
+
LCID lcid,
|
298
|
+
DISPID *pDispID
|
299
|
+
) {
|
300
|
+
ITypeInfo *pTypeInfo;
|
301
|
+
PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
|
302
|
+
pTypeInfo = pEV->pTypeInfo;
|
303
|
+
if (pTypeInfo) {
|
304
|
+
return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
|
305
|
+
}
|
306
|
+
return DISP_E_UNKNOWNNAME;
|
307
|
+
}
|
308
|
+
|
309
|
+
PIEVENTSINKOBJ
|
310
|
+
EVENTSINK_Constructor(void)
|
311
|
+
{
|
312
|
+
PIEVENTSINKOBJ pEv;
|
313
|
+
pEv = ALLOC_N(IEVENTSINKOBJ, 1);
|
314
|
+
if(pEv == NULL) return NULL;
|
315
|
+
pEv->lpVtbl = &vtEventSink;
|
316
|
+
pEv->m_cRef = 0;
|
317
|
+
pEv->m_event_id = 0;
|
318
|
+
pEv->pTypeInfo = NULL;
|
319
|
+
return pEv;
|
320
|
+
}
|
321
|
+
|
322
|
+
void
|
323
|
+
EVENTSINK_Destructor(
|
324
|
+
PIEVENTSINKOBJ pEVObj
|
325
|
+
) {
|
326
|
+
if(pEVObj != NULL) {
|
327
|
+
OLE_RELEASE(pEVObj->pTypeInfo);
|
328
|
+
free(pEVObj);
|
329
|
+
pEVObj = NULL;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
static void
|
334
|
+
ole_val2ptr_variant(VALUE val, VARIANT *var)
|
335
|
+
{
|
336
|
+
switch (TYPE(val)) {
|
337
|
+
case T_STRING:
|
338
|
+
if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
|
339
|
+
*V_BSTRREF(var) = ole_vstr2wc(val);
|
340
|
+
}
|
341
|
+
break;
|
342
|
+
case T_FIXNUM:
|
343
|
+
switch(V_VT(var)) {
|
344
|
+
case (VT_UI1 | VT_BYREF) :
|
345
|
+
*V_UI1REF(var) = RB_NUM2CHR(val);
|
346
|
+
break;
|
347
|
+
case (VT_I2 | VT_BYREF) :
|
348
|
+
*V_I2REF(var) = (short)RB_NUM2INT(val);
|
349
|
+
break;
|
350
|
+
case (VT_I4 | VT_BYREF) :
|
351
|
+
*V_I4REF(var) = RB_NUM2INT(val);
|
352
|
+
break;
|
353
|
+
case (VT_R4 | VT_BYREF) :
|
354
|
+
*V_R4REF(var) = (float)RB_NUM2INT(val);
|
355
|
+
break;
|
356
|
+
case (VT_R8 | VT_BYREF) :
|
357
|
+
*V_R8REF(var) = RB_NUM2INT(val);
|
358
|
+
break;
|
359
|
+
default:
|
360
|
+
break;
|
361
|
+
}
|
362
|
+
break;
|
363
|
+
case T_FLOAT:
|
364
|
+
switch(V_VT(var)) {
|
365
|
+
case (VT_I2 | VT_BYREF) :
|
366
|
+
*V_I2REF(var) = (short)RB_NUM2INT(val);
|
367
|
+
break;
|
368
|
+
case (VT_I4 | VT_BYREF) :
|
369
|
+
*V_I4REF(var) = RB_NUM2INT(val);
|
370
|
+
break;
|
371
|
+
case (VT_R4 | VT_BYREF) :
|
372
|
+
*V_R4REF(var) = (float)NUM2DBL(val);
|
373
|
+
break;
|
374
|
+
case (VT_R8 | VT_BYREF) :
|
375
|
+
*V_R8REF(var) = NUM2DBL(val);
|
376
|
+
break;
|
377
|
+
default:
|
378
|
+
break;
|
379
|
+
}
|
380
|
+
break;
|
381
|
+
case T_BIGNUM:
|
382
|
+
if (V_VT(var) == (VT_R8 | VT_BYREF)) {
|
383
|
+
*V_R8REF(var) = rb_big2dbl(val);
|
384
|
+
}
|
385
|
+
break;
|
386
|
+
case T_TRUE:
|
387
|
+
if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
|
388
|
+
*V_BOOLREF(var) = VARIANT_TRUE;
|
389
|
+
}
|
390
|
+
break;
|
391
|
+
case T_FALSE:
|
392
|
+
if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
|
393
|
+
*V_BOOLREF(var) = VARIANT_FALSE;
|
394
|
+
}
|
395
|
+
break;
|
396
|
+
default:
|
397
|
+
break;
|
398
|
+
}
|
399
|
+
}
|
400
|
+
|
401
|
+
static void
|
402
|
+
hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
|
403
|
+
{
|
404
|
+
BSTR *bstrs;
|
405
|
+
HRESULT hr;
|
406
|
+
UINT len, i;
|
407
|
+
VARIANT *pvar;
|
408
|
+
VALUE val;
|
409
|
+
VALUE key;
|
410
|
+
len = 0;
|
411
|
+
bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
|
412
|
+
hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
|
413
|
+
bstrs, pdispparams->cArgs + 1,
|
414
|
+
&len);
|
415
|
+
if (FAILED(hr))
|
416
|
+
return;
|
417
|
+
|
418
|
+
for (i = 0; i < len - 1; i++) {
|
419
|
+
key = WC2VSTR(bstrs[i + 1]);
|
420
|
+
val = rb_hash_aref(hash, RB_UINT2NUM(i));
|
421
|
+
if (val == Qnil)
|
422
|
+
val = rb_hash_aref(hash, key);
|
423
|
+
if (val == Qnil)
|
424
|
+
val = rb_hash_aref(hash, rb_str_intern(key));
|
425
|
+
pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
|
426
|
+
ole_val2ptr_variant(val, pvar);
|
427
|
+
}
|
428
|
+
}
|
429
|
+
|
430
|
+
static VALUE
|
431
|
+
hash2result(VALUE hash)
|
432
|
+
{
|
433
|
+
VALUE ret = Qnil;
|
434
|
+
ret = rb_hash_aref(hash, rb_str_new2("return"));
|
435
|
+
if (ret == Qnil)
|
436
|
+
ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
|
437
|
+
return ret;
|
438
|
+
}
|
439
|
+
|
440
|
+
static void
|
441
|
+
ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
|
442
|
+
{
|
443
|
+
int i;
|
444
|
+
VALUE v;
|
445
|
+
VARIANT *pvar;
|
446
|
+
for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) {
|
447
|
+
v = rb_ary_entry(ary, i);
|
448
|
+
pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
|
449
|
+
ole_val2ptr_variant(v, pvar);
|
450
|
+
}
|
451
|
+
}
|
452
|
+
|
453
|
+
static VALUE
|
454
|
+
exec_callback(VALUE arg)
|
455
|
+
{
|
456
|
+
VALUE *parg = (VALUE *)arg;
|
457
|
+
VALUE handler = parg[0];
|
458
|
+
VALUE mid = parg[1];
|
459
|
+
VALUE args = parg[2];
|
460
|
+
return rb_apply(handler, mid, args);
|
461
|
+
}
|
462
|
+
|
463
|
+
static VALUE
|
464
|
+
rescue_callback(VALUE arg)
|
465
|
+
{
|
466
|
+
|
467
|
+
VALUE error;
|
468
|
+
VALUE e = rb_errinfo();
|
469
|
+
VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
|
470
|
+
VALUE msg = rb_funcall(e, rb_intern("message"), 0);
|
471
|
+
bt = rb_ary_entry(bt, 0);
|
472
|
+
error = rb_sprintf("%"PRIsVALUE": %"PRIsVALUE" (%s)\n", bt, msg, rb_obj_classname(e));
|
473
|
+
rb_write_error_str(error);
|
474
|
+
rb_backtrace();
|
475
|
+
ruby_finalize();
|
476
|
+
exit(-1);
|
477
|
+
|
478
|
+
return Qnil;
|
479
|
+
}
|
480
|
+
|
481
|
+
static HRESULT
|
482
|
+
find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
|
483
|
+
{
|
484
|
+
HRESULT hr;
|
485
|
+
IDispatch *pDispatch;
|
486
|
+
ITypeInfo *pTypeInfo;
|
487
|
+
ITypeLib *pTypeLib;
|
488
|
+
TYPEATTR *pTypeAttr;
|
489
|
+
HREFTYPE RefType;
|
490
|
+
ITypeInfo *pImplTypeInfo;
|
491
|
+
TYPEATTR *pImplTypeAttr;
|
492
|
+
|
493
|
+
struct oledata *pole = NULL;
|
494
|
+
unsigned int index;
|
495
|
+
unsigned int count;
|
496
|
+
int type;
|
497
|
+
BSTR bstr;
|
498
|
+
char *pstr;
|
499
|
+
|
500
|
+
BOOL is_found = FALSE;
|
501
|
+
LCID lcid = cWIN32OLE_lcid;
|
502
|
+
|
503
|
+
pole = oledata_get_struct(ole);
|
504
|
+
|
505
|
+
pDispatch = pole->pDispatch;
|
506
|
+
|
507
|
+
hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo);
|
508
|
+
if (FAILED(hr))
|
509
|
+
return hr;
|
510
|
+
|
511
|
+
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
|
512
|
+
&pTypeLib,
|
513
|
+
&index);
|
514
|
+
OLE_RELEASE(pTypeInfo);
|
515
|
+
if (FAILED(hr))
|
516
|
+
return hr;
|
517
|
+
|
518
|
+
if (!pitf) {
|
519
|
+
hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
|
520
|
+
piid,
|
521
|
+
ppTypeInfo);
|
522
|
+
OLE_RELEASE(pTypeLib);
|
523
|
+
return hr;
|
524
|
+
}
|
525
|
+
count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
|
526
|
+
for (index = 0; index < count; index++) {
|
527
|
+
hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
|
528
|
+
index,
|
529
|
+
&pTypeInfo);
|
530
|
+
if (FAILED(hr))
|
531
|
+
break;
|
532
|
+
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
|
533
|
+
|
534
|
+
if(FAILED(hr)) {
|
535
|
+
OLE_RELEASE(pTypeInfo);
|
536
|
+
break;
|
537
|
+
}
|
538
|
+
if(pTypeAttr->typekind == TKIND_COCLASS) {
|
539
|
+
for (type = 0; type < pTypeAttr->cImplTypes; type++) {
|
540
|
+
hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
|
541
|
+
type,
|
542
|
+
&RefType);
|
543
|
+
if (FAILED(hr))
|
544
|
+
break;
|
545
|
+
hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
|
546
|
+
RefType,
|
547
|
+
&pImplTypeInfo);
|
548
|
+
if (FAILED(hr))
|
549
|
+
break;
|
550
|
+
|
551
|
+
hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo,
|
552
|
+
-1,
|
553
|
+
&bstr,
|
554
|
+
NULL, NULL, NULL);
|
555
|
+
if (FAILED(hr)) {
|
556
|
+
OLE_RELEASE(pImplTypeInfo);
|
557
|
+
break;
|
558
|
+
}
|
559
|
+
pstr = ole_wc2mb(bstr);
|
560
|
+
if (strcmp(pitf, pstr) == 0) {
|
561
|
+
hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo,
|
562
|
+
&pImplTypeAttr);
|
563
|
+
if (SUCCEEDED(hr)) {
|
564
|
+
is_found = TRUE;
|
565
|
+
*piid = pImplTypeAttr->guid;
|
566
|
+
if (ppTypeInfo) {
|
567
|
+
*ppTypeInfo = pImplTypeInfo;
|
568
|
+
(*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo));
|
569
|
+
}
|
570
|
+
pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo,
|
571
|
+
pImplTypeAttr);
|
572
|
+
}
|
573
|
+
}
|
574
|
+
free(pstr);
|
575
|
+
OLE_RELEASE(pImplTypeInfo);
|
576
|
+
if (is_found || FAILED(hr))
|
577
|
+
break;
|
578
|
+
}
|
579
|
+
}
|
580
|
+
|
581
|
+
OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
|
582
|
+
OLE_RELEASE(pTypeInfo);
|
583
|
+
if (is_found || FAILED(hr))
|
584
|
+
break;
|
585
|
+
}
|
586
|
+
OLE_RELEASE(pTypeLib);
|
587
|
+
if(!is_found)
|
588
|
+
return E_NOINTERFACE;
|
589
|
+
return hr;
|
590
|
+
}
|
591
|
+
|
592
|
+
static HRESULT
|
593
|
+
find_coclass(
|
594
|
+
ITypeInfo *pTypeInfo,
|
595
|
+
TYPEATTR *pTypeAttr,
|
596
|
+
ITypeInfo **pCOTypeInfo,
|
597
|
+
TYPEATTR **pCOTypeAttr)
|
598
|
+
{
|
599
|
+
HRESULT hr = E_NOINTERFACE;
|
600
|
+
ITypeLib *pTypeLib;
|
601
|
+
int count;
|
602
|
+
BOOL found = FALSE;
|
603
|
+
ITypeInfo *pTypeInfo2;
|
604
|
+
TYPEATTR *pTypeAttr2;
|
605
|
+
int flags;
|
606
|
+
int i,j;
|
607
|
+
HREFTYPE href;
|
608
|
+
ITypeInfo *pRefTypeInfo;
|
609
|
+
TYPEATTR *pRefTypeAttr;
|
610
|
+
|
611
|
+
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
|
612
|
+
if (FAILED(hr)) {
|
613
|
+
return hr;
|
614
|
+
}
|
615
|
+
count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
|
616
|
+
for (i = 0; i < count && !found; i++) {
|
617
|
+
hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
|
618
|
+
if (FAILED(hr))
|
619
|
+
continue;
|
620
|
+
hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
|
621
|
+
if (FAILED(hr)) {
|
622
|
+
OLE_RELEASE(pTypeInfo2);
|
623
|
+
continue;
|
624
|
+
}
|
625
|
+
if (pTypeAttr2->typekind != TKIND_COCLASS) {
|
626
|
+
OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
|
627
|
+
OLE_RELEASE(pTypeInfo2);
|
628
|
+
continue;
|
629
|
+
}
|
630
|
+
for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
|
631
|
+
hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
|
632
|
+
if (FAILED(hr))
|
633
|
+
continue;
|
634
|
+
if (!(flags & IMPLTYPEFLAG_FDEFAULT))
|
635
|
+
continue;
|
636
|
+
hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
|
637
|
+
if (FAILED(hr))
|
638
|
+
continue;
|
639
|
+
hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
|
640
|
+
if (FAILED(hr))
|
641
|
+
continue;
|
642
|
+
hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
|
643
|
+
if (FAILED(hr)) {
|
644
|
+
OLE_RELEASE(pRefTypeInfo);
|
645
|
+
continue;
|
646
|
+
}
|
647
|
+
if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
|
648
|
+
found = TRUE;
|
649
|
+
}
|
650
|
+
}
|
651
|
+
if (!found) {
|
652
|
+
OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
|
653
|
+
OLE_RELEASE(pTypeInfo2);
|
654
|
+
}
|
655
|
+
}
|
656
|
+
OLE_RELEASE(pTypeLib);
|
657
|
+
if (found) {
|
658
|
+
*pCOTypeInfo = pTypeInfo2;
|
659
|
+
*pCOTypeAttr = pTypeAttr2;
|
660
|
+
hr = S_OK;
|
661
|
+
} else {
|
662
|
+
hr = E_NOINTERFACE;
|
663
|
+
}
|
664
|
+
return hr;
|
665
|
+
}
|
666
|
+
|
667
|
+
static HRESULT
|
668
|
+
find_default_source_from_typeinfo(
|
669
|
+
ITypeInfo *pTypeInfo,
|
670
|
+
TYPEATTR *pTypeAttr,
|
671
|
+
ITypeInfo **ppTypeInfo)
|
672
|
+
{
|
673
|
+
int i = 0;
|
674
|
+
HRESULT hr = E_NOINTERFACE;
|
675
|
+
int flags;
|
676
|
+
HREFTYPE hRefType;
|
677
|
+
/* Enumerate all implemented types of the COCLASS */
|
678
|
+
for (i = 0; i < pTypeAttr->cImplTypes; i++) {
|
679
|
+
hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
|
680
|
+
if (FAILED(hr))
|
681
|
+
continue;
|
682
|
+
|
683
|
+
/*
|
684
|
+
looking for the [default] [source]
|
685
|
+
we just hope that it is a dispinterface :-)
|
686
|
+
*/
|
687
|
+
if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
|
688
|
+
(flags & IMPLTYPEFLAG_FSOURCE)) {
|
689
|
+
|
690
|
+
hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
|
691
|
+
i, &hRefType);
|
692
|
+
if (FAILED(hr))
|
693
|
+
continue;
|
694
|
+
hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
|
695
|
+
hRefType, ppTypeInfo);
|
696
|
+
if (SUCCEEDED(hr))
|
697
|
+
break;
|
698
|
+
}
|
699
|
+
}
|
700
|
+
return hr;
|
701
|
+
}
|
702
|
+
|
703
|
+
static HRESULT
|
704
|
+
find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
|
705
|
+
{
|
706
|
+
HRESULT hr;
|
707
|
+
IProvideClassInfo2 *pProvideClassInfo2;
|
708
|
+
IProvideClassInfo *pProvideClassInfo;
|
709
|
+
void *p;
|
710
|
+
|
711
|
+
IDispatch *pDispatch;
|
712
|
+
ITypeInfo *pTypeInfo;
|
713
|
+
ITypeInfo *pTypeInfo2 = NULL;
|
714
|
+
TYPEATTR *pTypeAttr;
|
715
|
+
TYPEATTR *pTypeAttr2 = NULL;
|
716
|
+
|
717
|
+
struct oledata *pole = NULL;
|
718
|
+
|
719
|
+
pole = oledata_get_struct(ole);
|
720
|
+
pDispatch = pole->pDispatch;
|
721
|
+
hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
|
722
|
+
&IID_IProvideClassInfo2,
|
723
|
+
&p);
|
724
|
+
if (SUCCEEDED(hr)) {
|
725
|
+
pProvideClassInfo2 = p;
|
726
|
+
hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
|
727
|
+
GUIDKIND_DEFAULT_SOURCE_DISP_IID,
|
728
|
+
piid);
|
729
|
+
OLE_RELEASE(pProvideClassInfo2);
|
730
|
+
if (SUCCEEDED(hr)) {
|
731
|
+
hr = find_iid(ole, NULL, piid, ppTypeInfo);
|
732
|
+
}
|
733
|
+
}
|
734
|
+
if (SUCCEEDED(hr)) {
|
735
|
+
return hr;
|
736
|
+
}
|
737
|
+
hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
|
738
|
+
&IID_IProvideClassInfo,
|
739
|
+
&p);
|
740
|
+
if (SUCCEEDED(hr)) {
|
741
|
+
pProvideClassInfo = p;
|
742
|
+
hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
|
743
|
+
&pTypeInfo);
|
744
|
+
OLE_RELEASE(pProvideClassInfo);
|
745
|
+
}
|
746
|
+
if (FAILED(hr)) {
|
747
|
+
hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
|
748
|
+
}
|
749
|
+
if (FAILED(hr))
|
750
|
+
return hr;
|
751
|
+
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
|
752
|
+
if (FAILED(hr)) {
|
753
|
+
OLE_RELEASE(pTypeInfo);
|
754
|
+
return hr;
|
755
|
+
}
|
756
|
+
|
757
|
+
*ppTypeInfo = 0;
|
758
|
+
hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
|
759
|
+
if (!*ppTypeInfo) {
|
760
|
+
hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
|
761
|
+
if (SUCCEEDED(hr)) {
|
762
|
+
hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
|
763
|
+
OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
|
764
|
+
OLE_RELEASE(pTypeInfo2);
|
765
|
+
}
|
766
|
+
}
|
767
|
+
OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
|
768
|
+
OLE_RELEASE(pTypeInfo);
|
769
|
+
/* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
|
770
|
+
if (!*ppTypeInfo) {
|
771
|
+
if (SUCCEEDED(hr))
|
772
|
+
hr = E_UNEXPECTED;
|
773
|
+
return hr;
|
774
|
+
}
|
775
|
+
|
776
|
+
/* Determine IID of default source interface */
|
777
|
+
hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr);
|
778
|
+
if (SUCCEEDED(hr)) {
|
779
|
+
*piid = pTypeAttr->guid;
|
780
|
+
(*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr);
|
781
|
+
}
|
782
|
+
else
|
783
|
+
OLE_RELEASE(*ppTypeInfo);
|
784
|
+
|
785
|
+
return hr;
|
786
|
+
}
|
787
|
+
|
788
|
+
static long
|
789
|
+
ole_search_event_at(VALUE ary, VALUE ev)
|
790
|
+
{
|
791
|
+
VALUE event;
|
792
|
+
VALUE event_name;
|
793
|
+
long i, len;
|
794
|
+
long ret = -1;
|
795
|
+
len = RARRAY_LEN(ary);
|
796
|
+
for(i = 0; i < len; i++) {
|
797
|
+
event = rb_ary_entry(ary, i);
|
798
|
+
event_name = rb_ary_entry(event, 1);
|
799
|
+
if(NIL_P(event_name) && NIL_P(ev)) {
|
800
|
+
ret = i;
|
801
|
+
break;
|
802
|
+
}
|
803
|
+
else if (RB_TYPE_P(ev, T_STRING) &&
|
804
|
+
RB_TYPE_P(event_name, T_STRING) &&
|
805
|
+
rb_str_cmp(ev, event_name) == 0) {
|
806
|
+
ret = i;
|
807
|
+
break;
|
808
|
+
}
|
809
|
+
}
|
810
|
+
return ret;
|
811
|
+
}
|
812
|
+
|
813
|
+
static VALUE
|
814
|
+
ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
|
815
|
+
{
|
816
|
+
VALUE event;
|
817
|
+
VALUE def_event;
|
818
|
+
VALUE event_name;
|
819
|
+
int i, len;
|
820
|
+
*is_default = FALSE;
|
821
|
+
def_event = Qnil;
|
822
|
+
len = RARRAY_LEN(ary);
|
823
|
+
for(i = 0; i < len; i++) {
|
824
|
+
event = rb_ary_entry(ary, i);
|
825
|
+
event_name = rb_ary_entry(event, 1);
|
826
|
+
if(NIL_P(event_name)) {
|
827
|
+
*is_default = TRUE;
|
828
|
+
def_event = event;
|
829
|
+
}
|
830
|
+
else if (rb_str_cmp(ev, event_name) == 0) {
|
831
|
+
*is_default = FALSE;
|
832
|
+
return event;
|
833
|
+
}
|
834
|
+
}
|
835
|
+
return def_event;
|
836
|
+
}
|
837
|
+
|
838
|
+
static VALUE
|
839
|
+
ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
|
840
|
+
{
|
841
|
+
VALUE mid;
|
842
|
+
|
843
|
+
*is_default_handler = FALSE;
|
844
|
+
mid = rb_to_id(rb_sprintf("on%"PRIsVALUE, ev));
|
845
|
+
if (rb_respond_to(handler, mid)) {
|
846
|
+
return mid;
|
847
|
+
}
|
848
|
+
mid = rb_intern("method_missing");
|
849
|
+
if (rb_respond_to(handler, mid)) {
|
850
|
+
*is_default_handler = TRUE;
|
851
|
+
return mid;
|
852
|
+
}
|
853
|
+
return Qnil;
|
854
|
+
}
|
855
|
+
|
856
|
+
static void
|
857
|
+
ole_delete_event(VALUE ary, VALUE ev)
|
858
|
+
{
|
859
|
+
long at = -1;
|
860
|
+
at = ole_search_event_at(ary, ev);
|
861
|
+
if (at >= 0) {
|
862
|
+
rb_ary_delete_at(ary, at);
|
863
|
+
}
|
864
|
+
}
|
865
|
+
|
866
|
+
|
867
|
+
static void
|
868
|
+
oleevent_free(void *ptr)
|
869
|
+
{
|
870
|
+
struct oleeventdata *poleev = ptr;
|
871
|
+
if (poleev->pConnectionPoint) {
|
872
|
+
poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
|
873
|
+
OLE_RELEASE(poleev->pConnectionPoint);
|
874
|
+
poleev->pConnectionPoint = NULL;
|
875
|
+
}
|
876
|
+
OLE_RELEASE(poleev->pDispatch);
|
877
|
+
free(poleev);
|
878
|
+
}
|
879
|
+
|
880
|
+
static size_t
|
881
|
+
oleevent_size(const void *ptr)
|
882
|
+
{
|
883
|
+
return ptr ? sizeof(struct oleeventdata) : 0;
|
884
|
+
}
|
885
|
+
|
886
|
+
static VALUE
|
887
|
+
fev_s_allocate(VALUE klass)
|
888
|
+
{
|
889
|
+
VALUE obj;
|
890
|
+
struct oleeventdata *poleev;
|
891
|
+
obj = TypedData_Make_Struct(klass, struct oleeventdata, &oleevent_datatype, poleev);
|
892
|
+
poleev->dwCookie = 0;
|
893
|
+
poleev->pConnectionPoint = NULL;
|
894
|
+
poleev->event_id = 0;
|
895
|
+
poleev->pDispatch = NULL;
|
896
|
+
return obj;
|
897
|
+
}
|
898
|
+
|
899
|
+
static VALUE
|
900
|
+
ev_advise(int argc, VALUE *argv, VALUE self)
|
901
|
+
{
|
902
|
+
|
903
|
+
VALUE ole, itf;
|
904
|
+
struct oledata *pole = NULL;
|
905
|
+
char *pitf;
|
906
|
+
HRESULT hr;
|
907
|
+
IID iid;
|
908
|
+
ITypeInfo *pTypeInfo = 0;
|
909
|
+
IDispatch *pDispatch;
|
910
|
+
IConnectionPointContainer *pContainer;
|
911
|
+
IConnectionPoint *pConnectionPoint;
|
912
|
+
IEVENTSINKOBJ *pIEV;
|
913
|
+
DWORD dwCookie;
|
914
|
+
struct oleeventdata *poleev;
|
915
|
+
void *p;
|
916
|
+
|
917
|
+
rb_scan_args(argc, argv, "11", &ole, &itf);
|
918
|
+
|
919
|
+
if (!rb_obj_is_kind_of(ole, cWIN32OLE)) {
|
920
|
+
rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object");
|
921
|
+
}
|
922
|
+
|
923
|
+
if(!RB_TYPE_P(itf, T_NIL)) {
|
924
|
+
pitf = StringValuePtr(itf);
|
925
|
+
hr = find_iid(ole, pitf, &iid, &pTypeInfo);
|
926
|
+
}
|
927
|
+
else {
|
928
|
+
hr = find_default_source(ole, &iid, &pTypeInfo);
|
929
|
+
}
|
930
|
+
if (FAILED(hr)) {
|
931
|
+
ole_raise(hr, rb_eRuntimeError, "interface not found");
|
932
|
+
}
|
933
|
+
|
934
|
+
pole = oledata_get_struct(ole);
|
935
|
+
pDispatch = pole->pDispatch;
|
936
|
+
hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
|
937
|
+
&IID_IConnectionPointContainer,
|
938
|
+
&p);
|
939
|
+
if (FAILED(hr)) {
|
940
|
+
OLE_RELEASE(pTypeInfo);
|
941
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError,
|
942
|
+
"failed to query IConnectionPointContainer");
|
943
|
+
}
|
944
|
+
pContainer = p;
|
945
|
+
|
946
|
+
hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
|
947
|
+
&iid,
|
948
|
+
&pConnectionPoint);
|
949
|
+
OLE_RELEASE(pContainer);
|
950
|
+
if (FAILED(hr)) {
|
951
|
+
OLE_RELEASE(pTypeInfo);
|
952
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to query IConnectionPoint");
|
953
|
+
}
|
954
|
+
pIEV = EVENTSINK_Constructor();
|
955
|
+
pIEV->m_iid = iid;
|
956
|
+
hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
|
957
|
+
(IUnknown*)pIEV,
|
958
|
+
&dwCookie);
|
959
|
+
if (FAILED(hr)) {
|
960
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "Advise Error");
|
961
|
+
}
|
962
|
+
|
963
|
+
TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
|
964
|
+
pIEV->m_event_id = evs_length();
|
965
|
+
pIEV->pTypeInfo = pTypeInfo;
|
966
|
+
poleev->dwCookie = dwCookie;
|
967
|
+
poleev->pConnectionPoint = pConnectionPoint;
|
968
|
+
poleev->event_id = pIEV->m_event_id;
|
969
|
+
poleev->pDispatch = pDispatch;
|
970
|
+
OLE_ADDREF(pDispatch);
|
971
|
+
|
972
|
+
return self;
|
973
|
+
}
|
974
|
+
|
975
|
+
/*
|
976
|
+
* call-seq:
|
977
|
+
* WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
|
978
|
+
*
|
979
|
+
* Returns OLE event object.
|
980
|
+
* The first argument specifies WIN32OLE object.
|
981
|
+
* The second argument specifies OLE event name.
|
982
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
983
|
+
* ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
|
984
|
+
*/
|
985
|
+
static VALUE
|
986
|
+
fev_initialize(int argc, VALUE *argv, VALUE self)
|
987
|
+
{
|
988
|
+
ev_advise(argc, argv, self);
|
989
|
+
evs_push(self);
|
990
|
+
rb_ivar_set(self, id_events, rb_ary_new());
|
991
|
+
fev_set_handler(self, Qnil);
|
992
|
+
return self;
|
993
|
+
}
|
994
|
+
|
995
|
+
static void
|
996
|
+
ole_msg_loop(void)
|
997
|
+
{
|
998
|
+
MSG msg;
|
999
|
+
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
|
1000
|
+
TranslateMessage(&msg);
|
1001
|
+
DispatchMessage(&msg);
|
1002
|
+
}
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
/*
|
1006
|
+
* call-seq:
|
1007
|
+
* WIN32OLE_EVENT.message_loop
|
1008
|
+
*
|
1009
|
+
* Translates and dispatches Windows message.
|
1010
|
+
*/
|
1011
|
+
static VALUE
|
1012
|
+
fev_s_msg_loop(VALUE klass)
|
1013
|
+
{
|
1014
|
+
ole_msg_loop();
|
1015
|
+
return Qnil;
|
1016
|
+
}
|
1017
|
+
|
1018
|
+
static void
|
1019
|
+
add_event_call_back(VALUE obj, VALUE event, VALUE data)
|
1020
|
+
{
|
1021
|
+
VALUE events = rb_ivar_get(obj, id_events);
|
1022
|
+
if (NIL_P(events) || !RB_TYPE_P(events, T_ARRAY)) {
|
1023
|
+
events = rb_ary_new();
|
1024
|
+
rb_ivar_set(obj, id_events, events);
|
1025
|
+
}
|
1026
|
+
ole_delete_event(events, event);
|
1027
|
+
rb_ary_push(events, data);
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
static VALUE
|
1031
|
+
ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
|
1032
|
+
{
|
1033
|
+
struct oleeventdata *poleev;
|
1034
|
+
VALUE event, args, data;
|
1035
|
+
TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
|
1036
|
+
if (poleev->pConnectionPoint == NULL) {
|
1037
|
+
rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
|
1038
|
+
}
|
1039
|
+
rb_scan_args(argc, argv, "01*", &event, &args);
|
1040
|
+
if(!NIL_P(event)) {
|
1041
|
+
if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
|
1042
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
|
1043
|
+
}
|
1044
|
+
if (RB_TYPE_P(event, T_SYMBOL)) {
|
1045
|
+
event = rb_sym2str(event);
|
1046
|
+
}
|
1047
|
+
}
|
1048
|
+
data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
|
1049
|
+
add_event_call_back(self, event, data);
|
1050
|
+
return Qnil;
|
1051
|
+
}
|
1052
|
+
|
1053
|
+
/*
|
1054
|
+
* call-seq:
|
1055
|
+
* WIN32OLE_EVENT#on_event([event]){...}
|
1056
|
+
*
|
1057
|
+
* Defines the callback event.
|
1058
|
+
* If argument is omitted, this method defines the callback of all events.
|
1059
|
+
* If you want to modify reference argument in callback, return hash in
|
1060
|
+
* callback. If you want to return value to OLE server as result of callback
|
1061
|
+
* use `return' or :return.
|
1062
|
+
*
|
1063
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
1064
|
+
* ev = WIN32OLE_EVENT.new(ie)
|
1065
|
+
* ev.on_event("NavigateComplete") {|url| puts url}
|
1066
|
+
* ev.on_event() {|ev, *args| puts "#{ev} fired"}
|
1067
|
+
*
|
1068
|
+
* ev.on_event("BeforeNavigate2") {|*args|
|
1069
|
+
* ...
|
1070
|
+
* # set true to BeforeNavigate reference argument `Cancel'.
|
1071
|
+
* # Cancel is 7-th argument of BeforeNavigate,
|
1072
|
+
* # so you can use 6 as key of hash instead of 'Cancel'.
|
1073
|
+
* # The argument is counted from 0.
|
1074
|
+
* # The hash key of 0 means first argument.)
|
1075
|
+
* {:Cancel => true} # or {'Cancel' => true} or {6 => true}
|
1076
|
+
* }
|
1077
|
+
*
|
1078
|
+
* ev.on_event(...) {|*args|
|
1079
|
+
* {:return => 1, :xxx => yyy}
|
1080
|
+
* }
|
1081
|
+
*/
|
1082
|
+
static VALUE
|
1083
|
+
fev_on_event(int argc, VALUE *argv, VALUE self)
|
1084
|
+
{
|
1085
|
+
return ev_on_event(argc, argv, self, Qfalse);
|
1086
|
+
}
|
1087
|
+
|
1088
|
+
/*
|
1089
|
+
* call-seq:
|
1090
|
+
* WIN32OLE_EVENT#on_event_with_outargs([event]){...}
|
1091
|
+
*
|
1092
|
+
* Defines the callback of event.
|
1093
|
+
* If you want modify argument in callback,
|
1094
|
+
* you could use this method instead of WIN32OLE_EVENT#on_event.
|
1095
|
+
*
|
1096
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
1097
|
+
* ev = WIN32OLE_EVENT.new(ie)
|
1098
|
+
* ev.on_event_with_outargs('BeforeNavigate2') {|*args|
|
1099
|
+
* args.last[6] = true
|
1100
|
+
* }
|
1101
|
+
*/
|
1102
|
+
static VALUE
|
1103
|
+
fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
|
1104
|
+
{
|
1105
|
+
return ev_on_event(argc, argv, self, Qtrue);
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
/*
|
1109
|
+
* call-seq:
|
1110
|
+
* WIN32OLE_EVENT#off_event([event])
|
1111
|
+
*
|
1112
|
+
* removes the callback of event.
|
1113
|
+
*
|
1114
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
1115
|
+
* ev = WIN32OLE_EVENT.new(ie)
|
1116
|
+
* ev.on_event('BeforeNavigate2') {|*args|
|
1117
|
+
* args.last[6] = true
|
1118
|
+
* }
|
1119
|
+
* ...
|
1120
|
+
* ev.off_event('BeforeNavigate2')
|
1121
|
+
* ...
|
1122
|
+
*/
|
1123
|
+
static VALUE
|
1124
|
+
fev_off_event(int argc, VALUE *argv, VALUE self)
|
1125
|
+
{
|
1126
|
+
VALUE event = Qnil;
|
1127
|
+
VALUE events;
|
1128
|
+
|
1129
|
+
rb_scan_args(argc, argv, "01", &event);
|
1130
|
+
if(!NIL_P(event)) {
|
1131
|
+
if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
|
1132
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
|
1133
|
+
}
|
1134
|
+
if (RB_TYPE_P(event, T_SYMBOL)) {
|
1135
|
+
event = rb_sym2str(event);
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
events = rb_ivar_get(self, id_events);
|
1139
|
+
if (NIL_P(events)) {
|
1140
|
+
return Qnil;
|
1141
|
+
}
|
1142
|
+
ole_delete_event(events, event);
|
1143
|
+
return Qnil;
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
/*
|
1147
|
+
* call-seq:
|
1148
|
+
* WIN32OLE_EVENT#unadvise -> nil
|
1149
|
+
*
|
1150
|
+
* disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
|
1151
|
+
* does not receive the OLE server event any more.
|
1152
|
+
* This method is trial implementation.
|
1153
|
+
*
|
1154
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
1155
|
+
* ev = WIN32OLE_EVENT.new(ie)
|
1156
|
+
* ev.on_event() {...}
|
1157
|
+
* ...
|
1158
|
+
* ev.unadvise
|
1159
|
+
*
|
1160
|
+
*/
|
1161
|
+
static VALUE
|
1162
|
+
fev_unadvise(VALUE self)
|
1163
|
+
{
|
1164
|
+
struct oleeventdata *poleev;
|
1165
|
+
TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
|
1166
|
+
if (poleev->pConnectionPoint) {
|
1167
|
+
ole_msg_loop();
|
1168
|
+
evs_delete(poleev->event_id);
|
1169
|
+
poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
|
1170
|
+
OLE_RELEASE(poleev->pConnectionPoint);
|
1171
|
+
poleev->pConnectionPoint = NULL;
|
1172
|
+
}
|
1173
|
+
OLE_FREE(poleev->pDispatch);
|
1174
|
+
return Qnil;
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
static VALUE
|
1178
|
+
evs_push(VALUE ev)
|
1179
|
+
{
|
1180
|
+
return rb_ary_push(ary_ole_event, ev);
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
static VALUE
|
1184
|
+
evs_delete(long i)
|
1185
|
+
{
|
1186
|
+
rb_ary_store(ary_ole_event, i, Qnil);
|
1187
|
+
return Qnil;
|
1188
|
+
}
|
1189
|
+
|
1190
|
+
static VALUE
|
1191
|
+
evs_entry(long i)
|
1192
|
+
{
|
1193
|
+
return rb_ary_entry(ary_ole_event, i);
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
static long
|
1197
|
+
evs_length(void)
|
1198
|
+
{
|
1199
|
+
return RARRAY_LEN(ary_ole_event);
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
/*
|
1203
|
+
* call-seq:
|
1204
|
+
* WIN32OLE_EVENT#handler=
|
1205
|
+
*
|
1206
|
+
* sets event handler object. If handler object has onXXX
|
1207
|
+
* method according to XXX event, then onXXX method is called
|
1208
|
+
* when XXX event occurs.
|
1209
|
+
*
|
1210
|
+
* If handler object has method_missing and there is no
|
1211
|
+
* method according to the event, then method_missing
|
1212
|
+
* called and 1-st argument is event name.
|
1213
|
+
*
|
1214
|
+
* If handler object has onXXX method and there is block
|
1215
|
+
* defined by WIN32OLE_EVENT#on_event('XXX'){},
|
1216
|
+
* then block is executed but handler object method is not called
|
1217
|
+
* when XXX event occurs.
|
1218
|
+
*
|
1219
|
+
* class Handler
|
1220
|
+
* def onStatusTextChange(text)
|
1221
|
+
* puts "StatusTextChanged"
|
1222
|
+
* end
|
1223
|
+
* def onPropertyChange(prop)
|
1224
|
+
* puts "PropertyChanged"
|
1225
|
+
* end
|
1226
|
+
* def method_missing(ev, *arg)
|
1227
|
+
* puts "other event #{ev}"
|
1228
|
+
* end
|
1229
|
+
* end
|
1230
|
+
*
|
1231
|
+
* handler = Handler.new
|
1232
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
1233
|
+
* ev = WIN32OLE_EVENT.new(ie)
|
1234
|
+
* ev.on_event("StatusTextChange") {|*args|
|
1235
|
+
* puts "this block executed."
|
1236
|
+
* puts "handler.onStatusTextChange method is not called."
|
1237
|
+
* }
|
1238
|
+
* ev.handler = handler
|
1239
|
+
*
|
1240
|
+
*/
|
1241
|
+
static VALUE
|
1242
|
+
fev_set_handler(VALUE self, VALUE val)
|
1243
|
+
{
|
1244
|
+
return rb_ivar_set(self, rb_intern("handler"), val);
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
/*
|
1248
|
+
* call-seq:
|
1249
|
+
* WIN32OLE_EVENT#handler
|
1250
|
+
*
|
1251
|
+
* returns handler object.
|
1252
|
+
*
|
1253
|
+
*/
|
1254
|
+
static VALUE
|
1255
|
+
fev_get_handler(VALUE self)
|
1256
|
+
{
|
1257
|
+
return rb_ivar_get(self, rb_intern("handler"));
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
void
|
1261
|
+
Init_win32ole_event(void)
|
1262
|
+
{
|
1263
|
+
#undef rb_intern
|
1264
|
+
ary_ole_event = rb_ary_new();
|
1265
|
+
rb_gc_register_mark_object(ary_ole_event);
|
1266
|
+
id_events = rb_intern("events");
|
1267
|
+
cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
|
1268
|
+
rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
|
1269
|
+
rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
|
1270
|
+
rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
|
1271
|
+
rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
|
1272
|
+
rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
|
1273
|
+
rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
|
1274
|
+
rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
|
1275
|
+
rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
|
1276
|
+
rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
|
1277
|
+
}
|