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,4140 @@
|
|
1
|
+
/*
|
2
|
+
* (c) 1995 Microsoft Corporation. All rights reserved.
|
3
|
+
* Developed by ActiveWare Internet Corp., now known as
|
4
|
+
* ActiveState Tool Corp., http://www.ActiveState.com
|
5
|
+
*
|
6
|
+
* Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy
|
7
|
+
* <gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net>
|
8
|
+
*
|
9
|
+
* You may distribute under the terms of either the GNU General Public
|
10
|
+
* License or the Artistic License, as specified in the README file
|
11
|
+
* of the Perl distribution.
|
12
|
+
*
|
13
|
+
*/
|
14
|
+
|
15
|
+
/*
|
16
|
+
modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@nifty.ne.jp>
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include "win32ole.h"
|
20
|
+
|
21
|
+
/*
|
22
|
+
* unfortunately IID_IMultiLanguage2 is not included in any libXXX.a
|
23
|
+
* in Cygwin(mingw32).
|
24
|
+
*/
|
25
|
+
#if defined(__CYGWIN__) || defined(__MINGW32__)
|
26
|
+
#undef IID_IMultiLanguage2
|
27
|
+
const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}};
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#define WIN32OLE_VERSION "1.8.8"
|
31
|
+
|
32
|
+
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
|
33
|
+
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
|
34
|
+
|
35
|
+
typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile,
|
36
|
+
UINT uCommand, DWORD dwData);
|
37
|
+
typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD);
|
38
|
+
VALUE cWIN32OLE;
|
39
|
+
|
40
|
+
#if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__))
|
41
|
+
static RB_THREAD_SPECIFIC BOOL g_ole_initialized;
|
42
|
+
# define g_ole_initialized_init() ((void)0)
|
43
|
+
# define g_ole_initialized_set(val) (g_ole_initialized = (val))
|
44
|
+
#else
|
45
|
+
static volatile DWORD g_ole_initialized_key = TLS_OUT_OF_INDEXES;
|
46
|
+
# define g_ole_initialized (TlsGetValue(g_ole_initialized_key)!=0)
|
47
|
+
# define g_ole_initialized_init() (g_ole_initialized_key = TlsAlloc())
|
48
|
+
# define g_ole_initialized_set(val) TlsSetValue(g_ole_initialized_key, (void*)(val))
|
49
|
+
#endif
|
50
|
+
|
51
|
+
static BOOL g_uninitialize_hooked = FALSE;
|
52
|
+
static BOOL g_cp_installed = FALSE;
|
53
|
+
static BOOL g_lcid_installed = FALSE;
|
54
|
+
static BOOL g_running_nano = FALSE;
|
55
|
+
static HINSTANCE ghhctrl = NULL;
|
56
|
+
static HINSTANCE gole32 = NULL;
|
57
|
+
static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL;
|
58
|
+
static VALUE com_hash;
|
59
|
+
static VALUE enc2cp_hash;
|
60
|
+
static IDispatchVtbl com_vtbl;
|
61
|
+
static UINT cWIN32OLE_cp = CP_ACP;
|
62
|
+
static rb_encoding *cWIN32OLE_enc;
|
63
|
+
static UINT g_cp_to_check = CP_ACP;
|
64
|
+
static char g_lcid_to_check[8 + 1];
|
65
|
+
static VARTYPE g_nil_to = VT_ERROR;
|
66
|
+
static IMessageFilterVtbl message_filter;
|
67
|
+
static IMessageFilter imessage_filter = { &message_filter };
|
68
|
+
static IMessageFilter* previous_filter;
|
69
|
+
|
70
|
+
#if defined(HAVE_TYPE_IMULTILANGUAGE2)
|
71
|
+
static IMultiLanguage2 *pIMultiLanguage = NULL;
|
72
|
+
#elif defined(HAVE_TYPE_IMULTILANGUAGE)
|
73
|
+
static IMultiLanguage *pIMultiLanguage = NULL;
|
74
|
+
#else
|
75
|
+
#define pIMultiLanguage NULL /* dummy */
|
76
|
+
#endif
|
77
|
+
|
78
|
+
struct oleparam {
|
79
|
+
DISPPARAMS dp;
|
80
|
+
OLECHAR** pNamedArgs;
|
81
|
+
};
|
82
|
+
|
83
|
+
static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
|
84
|
+
static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This);
|
85
|
+
static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This);
|
86
|
+
static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo);
|
87
|
+
static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
|
88
|
+
static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId);
|
89
|
+
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);
|
90
|
+
static IDispatch* val2dispatch(VALUE val);
|
91
|
+
static double rbtime2vtdate(VALUE tmobj);
|
92
|
+
static VALUE vtdate2rbtime(double date);
|
93
|
+
static rb_encoding *ole_cp2encoding(UINT cp);
|
94
|
+
static UINT ole_encoding2cp(rb_encoding *enc);
|
95
|
+
NORETURN(static void failed_load_conv51932(void));
|
96
|
+
#ifndef pIMultiLanguage
|
97
|
+
static void load_conv_function51932(void);
|
98
|
+
#endif
|
99
|
+
static UINT ole_init_cp(void);
|
100
|
+
static void ole_freeexceptinfo(EXCEPINFO *pExInfo);
|
101
|
+
static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo);
|
102
|
+
static void ole_free(void *ptr);
|
103
|
+
static size_t ole_size(const void *ptr);
|
104
|
+
static LPWSTR ole_mb2wc(char *pm, int len, UINT cp);
|
105
|
+
static VALUE ole_ary_m_entry(VALUE val, LONG *pid);
|
106
|
+
static VALUE is_all_index_under(LONG *pid, long *pub, long dim);
|
107
|
+
static void * get_ptr_of_variant(VARIANT *pvar);
|
108
|
+
static void ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt);
|
109
|
+
static long dimension(VALUE val);
|
110
|
+
static long ary_len_of_dim(VALUE ary, long dim);
|
111
|
+
static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
|
112
|
+
static VALUE fole_s_allocate(VALUE klass);
|
113
|
+
static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
|
114
|
+
static VALUE ary_new_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim);
|
115
|
+
static void ary_store_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim, VALUE val);
|
116
|
+
static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self);
|
117
|
+
static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid);
|
118
|
+
static VALUE ole_create_dcom(VALUE self, VALUE ole, VALUE host, VALUE others);
|
119
|
+
static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self);
|
120
|
+
static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self);
|
121
|
+
static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self);
|
122
|
+
static ULONG reference_count(struct oledata * pole);
|
123
|
+
static VALUE fole_s_reference_count(VALUE self, VALUE obj);
|
124
|
+
static VALUE fole_s_free(VALUE self, VALUE obj);
|
125
|
+
static HWND ole_show_help(VALUE helpfile, VALUE helpcontext);
|
126
|
+
static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self);
|
127
|
+
static VALUE fole_s_get_code_page(VALUE self);
|
128
|
+
static BOOL CALLBACK installed_code_page_proc(LPTSTR str);
|
129
|
+
static BOOL code_page_installed(UINT cp);
|
130
|
+
static VALUE fole_s_set_code_page(VALUE self, VALUE vcp);
|
131
|
+
static VALUE fole_s_get_locale(VALUE self);
|
132
|
+
static BOOL CALLBACK installed_lcid_proc(LPTSTR str);
|
133
|
+
static BOOL lcid_installed(LCID lcid);
|
134
|
+
static VALUE fole_s_set_locale(VALUE self, VALUE vlcid);
|
135
|
+
static VALUE fole_s_create_guid(VALUE self);
|
136
|
+
static VALUE fole_s_ole_initialize(VALUE self);
|
137
|
+
static VALUE fole_s_ole_uninitialize(VALUE self);
|
138
|
+
static VALUE fole_initialize(int argc, VALUE *argv, VALUE self);
|
139
|
+
static int hash2named_arg(VALUE key, VALUE val, VALUE pop);
|
140
|
+
static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end);
|
141
|
+
static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket);
|
142
|
+
static VALUE fole_invoke(int argc, VALUE *argv, VALUE self);
|
143
|
+
static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind);
|
144
|
+
static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types);
|
145
|
+
static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
|
146
|
+
static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
|
147
|
+
static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self);
|
148
|
+
static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self);
|
149
|
+
static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self);
|
150
|
+
static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value);
|
151
|
+
static VALUE fole_free(VALUE self);
|
152
|
+
static VALUE ole_each_sub(VALUE pEnumV);
|
153
|
+
static VALUE ole_ienum_free(VALUE pEnumV);
|
154
|
+
static VALUE fole_each(VALUE self);
|
155
|
+
static VALUE fole_missing(int argc, VALUE *argv, VALUE self);
|
156
|
+
static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti);
|
157
|
+
static VALUE ole_methods(VALUE self, int mask);
|
158
|
+
static VALUE fole_methods(VALUE self);
|
159
|
+
static VALUE fole_get_methods(VALUE self);
|
160
|
+
static VALUE fole_put_methods(VALUE self);
|
161
|
+
static VALUE fole_func_methods(VALUE self);
|
162
|
+
static VALUE fole_type(VALUE self);
|
163
|
+
static VALUE fole_typelib(VALUE self);
|
164
|
+
static VALUE fole_query_interface(VALUE self, VALUE str_iid);
|
165
|
+
static VALUE fole_respond_to(VALUE self, VALUE method);
|
166
|
+
static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
|
167
|
+
static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
|
168
|
+
static VALUE fole_method_help(VALUE self, VALUE cmdname);
|
169
|
+
static VALUE fole_activex_initialize(VALUE self);
|
170
|
+
|
171
|
+
static void com_hash_free(void *ptr);
|
172
|
+
static void com_hash_mark(void *ptr);
|
173
|
+
static size_t com_hash_size(const void *ptr);
|
174
|
+
static void check_nano_server(void);
|
175
|
+
|
176
|
+
static const rb_data_type_t ole_datatype = {
|
177
|
+
"win32ole",
|
178
|
+
{NULL, ole_free, ole_size,},
|
179
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
180
|
+
};
|
181
|
+
|
182
|
+
static const rb_data_type_t win32ole_hash_datatype = {
|
183
|
+
"win32ole_hash",
|
184
|
+
{com_hash_mark, com_hash_free, com_hash_size,},
|
185
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
186
|
+
};
|
187
|
+
|
188
|
+
static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
|
189
|
+
IMessageFilter __RPC_FAR * This,
|
190
|
+
/* [in] */ REFIID riid,
|
191
|
+
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
|
192
|
+
{
|
193
|
+
if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
|
194
|
+
|| MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0)
|
195
|
+
{
|
196
|
+
*ppvObject = &message_filter;
|
197
|
+
return S_OK;
|
198
|
+
}
|
199
|
+
return E_NOINTERFACE;
|
200
|
+
}
|
201
|
+
|
202
|
+
static ULONG (STDMETHODCALLTYPE mf_AddRef)(
|
203
|
+
IMessageFilter __RPC_FAR * This)
|
204
|
+
{
|
205
|
+
return 1;
|
206
|
+
}
|
207
|
+
|
208
|
+
static ULONG (STDMETHODCALLTYPE mf_Release)(
|
209
|
+
IMessageFilter __RPC_FAR * This)
|
210
|
+
{
|
211
|
+
return 1;
|
212
|
+
}
|
213
|
+
|
214
|
+
static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)(
|
215
|
+
IMessageFilter __RPC_FAR * pThis,
|
216
|
+
DWORD dwCallType, //Type of incoming call
|
217
|
+
HTASK threadIDCaller, //Task handle calling this task
|
218
|
+
DWORD dwTickCount, //Elapsed tick count
|
219
|
+
LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure
|
220
|
+
)
|
221
|
+
{
|
222
|
+
#ifdef DEBUG_MESSAGEFILTER
|
223
|
+
printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount);
|
224
|
+
fflush(stdout);
|
225
|
+
#endif
|
226
|
+
switch (dwCallType)
|
227
|
+
{
|
228
|
+
case CALLTYPE_ASYNC:
|
229
|
+
case CALLTYPE_TOPLEVEL_CALLPENDING:
|
230
|
+
case CALLTYPE_ASYNC_CALLPENDING:
|
231
|
+
if (rb_during_gc()) {
|
232
|
+
return SERVERCALL_RETRYLATER;
|
233
|
+
}
|
234
|
+
break;
|
235
|
+
default:
|
236
|
+
break;
|
237
|
+
}
|
238
|
+
if (previous_filter) {
|
239
|
+
return previous_filter->lpVtbl->HandleInComingCall(previous_filter,
|
240
|
+
dwCallType,
|
241
|
+
threadIDCaller,
|
242
|
+
dwTickCount,
|
243
|
+
lpInterfaceInfo);
|
244
|
+
}
|
245
|
+
return SERVERCALL_ISHANDLED;
|
246
|
+
}
|
247
|
+
|
248
|
+
static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)(
|
249
|
+
IMessageFilter* pThis,
|
250
|
+
HTASK threadIDCallee, //Server task handle
|
251
|
+
DWORD dwTickCount, //Elapsed tick count
|
252
|
+
DWORD dwRejectType //Returned rejection message
|
253
|
+
)
|
254
|
+
{
|
255
|
+
if (previous_filter) {
|
256
|
+
return previous_filter->lpVtbl->RetryRejectedCall(previous_filter,
|
257
|
+
threadIDCallee,
|
258
|
+
dwTickCount,
|
259
|
+
dwRejectType);
|
260
|
+
}
|
261
|
+
return 1000;
|
262
|
+
}
|
263
|
+
|
264
|
+
static DWORD (STDMETHODCALLTYPE mf_MessagePending)(
|
265
|
+
IMessageFilter* pThis,
|
266
|
+
HTASK threadIDCallee, //Called applications task handle
|
267
|
+
DWORD dwTickCount, //Elapsed tick count
|
268
|
+
DWORD dwPendingType //Call type
|
269
|
+
)
|
270
|
+
{
|
271
|
+
if (rb_during_gc()) {
|
272
|
+
return PENDINGMSG_WAITNOPROCESS;
|
273
|
+
}
|
274
|
+
if (previous_filter) {
|
275
|
+
return previous_filter->lpVtbl->MessagePending(previous_filter,
|
276
|
+
threadIDCallee,
|
277
|
+
dwTickCount,
|
278
|
+
dwPendingType);
|
279
|
+
}
|
280
|
+
return PENDINGMSG_WAITNOPROCESS;
|
281
|
+
}
|
282
|
+
|
283
|
+
typedef struct _Win32OLEIDispatch
|
284
|
+
{
|
285
|
+
IDispatch dispatch;
|
286
|
+
ULONG refcount;
|
287
|
+
VALUE obj;
|
288
|
+
} Win32OLEIDispatch;
|
289
|
+
|
290
|
+
static HRESULT ( STDMETHODCALLTYPE QueryInterface )(
|
291
|
+
IDispatch __RPC_FAR * This,
|
292
|
+
/* [in] */ REFIID riid,
|
293
|
+
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
|
294
|
+
{
|
295
|
+
if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
|
296
|
+
|| MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0)
|
297
|
+
{
|
298
|
+
Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
|
299
|
+
p->refcount++;
|
300
|
+
*ppvObject = This;
|
301
|
+
return S_OK;
|
302
|
+
}
|
303
|
+
return E_NOINTERFACE;
|
304
|
+
}
|
305
|
+
|
306
|
+
static ULONG ( STDMETHODCALLTYPE AddRef )(
|
307
|
+
IDispatch __RPC_FAR * This)
|
308
|
+
{
|
309
|
+
Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
|
310
|
+
return ++(p->refcount);
|
311
|
+
}
|
312
|
+
|
313
|
+
static ULONG ( STDMETHODCALLTYPE Release )(
|
314
|
+
IDispatch __RPC_FAR * This)
|
315
|
+
{
|
316
|
+
Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
|
317
|
+
ULONG u = --(p->refcount);
|
318
|
+
if (u == 0) {
|
319
|
+
st_data_t key = p->obj;
|
320
|
+
st_delete(DATA_PTR(com_hash), &key, 0);
|
321
|
+
free(p);
|
322
|
+
}
|
323
|
+
return u;
|
324
|
+
}
|
325
|
+
|
326
|
+
static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(
|
327
|
+
IDispatch __RPC_FAR * This,
|
328
|
+
/* [out] */ UINT __RPC_FAR *pctinfo)
|
329
|
+
{
|
330
|
+
return E_NOTIMPL;
|
331
|
+
}
|
332
|
+
|
333
|
+
static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(
|
334
|
+
IDispatch __RPC_FAR * This,
|
335
|
+
/* [in] */ UINT iTInfo,
|
336
|
+
/* [in] */ LCID lcid,
|
337
|
+
/* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
|
338
|
+
{
|
339
|
+
return E_NOTIMPL;
|
340
|
+
}
|
341
|
+
|
342
|
+
|
343
|
+
static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(
|
344
|
+
IDispatch __RPC_FAR * This,
|
345
|
+
/* [in] */ REFIID riid,
|
346
|
+
/* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
|
347
|
+
/* [in] */ UINT cNames,
|
348
|
+
/* [in] */ LCID lcid,
|
349
|
+
/* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
|
350
|
+
{
|
351
|
+
/*
|
352
|
+
Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
|
353
|
+
*/
|
354
|
+
char* psz = ole_wc2mb(*rgszNames); // support only one method
|
355
|
+
ID nameid = rb_check_id_cstr(psz, (long)strlen(psz), cWIN32OLE_enc);
|
356
|
+
free(psz);
|
357
|
+
if ((ID)(DISPID)nameid != nameid) return E_NOINTERFACE;
|
358
|
+
*rgDispId = (DISPID)nameid;
|
359
|
+
return S_OK;
|
360
|
+
}
|
361
|
+
|
362
|
+
static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )(
|
363
|
+
IDispatch __RPC_FAR * This,
|
364
|
+
/* [in] */ DISPID dispIdMember,
|
365
|
+
/* [in] */ REFIID riid,
|
366
|
+
/* [in] */ LCID lcid,
|
367
|
+
/* [in] */ WORD wFlags,
|
368
|
+
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
|
369
|
+
/* [out] */ VARIANT __RPC_FAR *pVarResult,
|
370
|
+
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
|
371
|
+
/* [out] */ UINT __RPC_FAR *puArgErr)
|
372
|
+
{
|
373
|
+
VALUE v;
|
374
|
+
int i;
|
375
|
+
int args = pDispParams->cArgs;
|
376
|
+
Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
|
377
|
+
VALUE* parg = ALLOCA_N(VALUE, args);
|
378
|
+
ID mid = (ID)dispIdMember;
|
379
|
+
for (i = 0; i < args; i++) {
|
380
|
+
*(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]);
|
381
|
+
}
|
382
|
+
if (dispIdMember == DISPID_VALUE) {
|
383
|
+
if (wFlags == DISPATCH_METHOD) {
|
384
|
+
mid = rb_intern("call");
|
385
|
+
} else if (wFlags & DISPATCH_PROPERTYGET) {
|
386
|
+
mid = rb_intern("value");
|
387
|
+
}
|
388
|
+
}
|
389
|
+
v = rb_funcallv(p->obj, mid, args, parg);
|
390
|
+
ole_val2variant(v, pVarResult);
|
391
|
+
return S_OK;
|
392
|
+
}
|
393
|
+
|
394
|
+
BOOL
|
395
|
+
ole_initialized(void)
|
396
|
+
{
|
397
|
+
return g_ole_initialized;
|
398
|
+
}
|
399
|
+
|
400
|
+
static IDispatch*
|
401
|
+
val2dispatch(VALUE val)
|
402
|
+
{
|
403
|
+
struct st_table *tbl = DATA_PTR(com_hash);
|
404
|
+
Win32OLEIDispatch* pdisp;
|
405
|
+
st_data_t data;
|
406
|
+
if (st_lookup(tbl, val, &data)) {
|
407
|
+
pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG);
|
408
|
+
pdisp->refcount++;
|
409
|
+
}
|
410
|
+
else {
|
411
|
+
pdisp = ALLOC(Win32OLEIDispatch);
|
412
|
+
pdisp->dispatch.lpVtbl = &com_vtbl;
|
413
|
+
pdisp->refcount = 1;
|
414
|
+
pdisp->obj = val;
|
415
|
+
st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG);
|
416
|
+
}
|
417
|
+
return &pdisp->dispatch;
|
418
|
+
}
|
419
|
+
|
420
|
+
static double
|
421
|
+
rbtime2vtdate(VALUE tmobj)
|
422
|
+
{
|
423
|
+
SYSTEMTIME st;
|
424
|
+
double t;
|
425
|
+
double nsec;
|
426
|
+
|
427
|
+
st.wYear = RB_FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0));
|
428
|
+
st.wMonth = RB_FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0));
|
429
|
+
st.wDay = RB_FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0));
|
430
|
+
st.wHour = RB_FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0));
|
431
|
+
st.wMinute = RB_FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0));
|
432
|
+
st.wSecond = RB_FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0));
|
433
|
+
st.wMilliseconds = 0;
|
434
|
+
SystemTimeToVariantTime(&st, &t);
|
435
|
+
|
436
|
+
/*
|
437
|
+
* Unfortunately SystemTimeToVariantTime function always ignores the
|
438
|
+
* wMilliseconds of SYSTEMTIME struct.
|
439
|
+
* So, we need to calculate milliseconds by ourselves.
|
440
|
+
*/
|
441
|
+
nsec = RB_FIX2INT(rb_funcall(tmobj, rb_intern("nsec"), 0));
|
442
|
+
nsec /= 1000000.0;
|
443
|
+
nsec /= (24.0 * 3600.0);
|
444
|
+
nsec /= 1000;
|
445
|
+
return t + nsec;
|
446
|
+
}
|
447
|
+
|
448
|
+
static VALUE
|
449
|
+
vtdate2rbtime(double date)
|
450
|
+
{
|
451
|
+
SYSTEMTIME st;
|
452
|
+
VALUE v;
|
453
|
+
double msec;
|
454
|
+
double sec;
|
455
|
+
VariantTimeToSystemTime(date, &st);
|
456
|
+
v = rb_funcall(rb_cTime, rb_intern("new"), 6,
|
457
|
+
RB_INT2FIX(st.wYear),
|
458
|
+
RB_INT2FIX(st.wMonth),
|
459
|
+
RB_INT2FIX(st.wDay),
|
460
|
+
RB_INT2FIX(st.wHour),
|
461
|
+
RB_INT2FIX(st.wMinute),
|
462
|
+
RB_INT2FIX(st.wSecond));
|
463
|
+
st.wYear = RB_FIX2INT(rb_funcall(v, rb_intern("year"), 0));
|
464
|
+
st.wMonth = RB_FIX2INT(rb_funcall(v, rb_intern("month"), 0));
|
465
|
+
st.wDay = RB_FIX2INT(rb_funcall(v, rb_intern("mday"), 0));
|
466
|
+
st.wHour = RB_FIX2INT(rb_funcall(v, rb_intern("hour"), 0));
|
467
|
+
st.wMinute = RB_FIX2INT(rb_funcall(v, rb_intern("min"), 0));
|
468
|
+
st.wSecond = RB_FIX2INT(rb_funcall(v, rb_intern("sec"), 0));
|
469
|
+
st.wMilliseconds = 0;
|
470
|
+
SystemTimeToVariantTime(&st, &sec);
|
471
|
+
/*
|
472
|
+
* Unfortunately VariantTimeToSystemTime always ignores the
|
473
|
+
* wMilliseconds of SYSTEMTIME struct(The wMilliseconds is 0).
|
474
|
+
* So, we need to calculate milliseconds by ourselves.
|
475
|
+
*/
|
476
|
+
msec = date - sec;
|
477
|
+
msec *= 24 * 60;
|
478
|
+
msec -= floor(msec);
|
479
|
+
msec *= 60;
|
480
|
+
if (msec >= 59) {
|
481
|
+
msec -= 60;
|
482
|
+
}
|
483
|
+
if (msec != 0) {
|
484
|
+
return rb_funcall(v, rb_intern("+"), 1, rb_float_new(msec));
|
485
|
+
}
|
486
|
+
return v;
|
487
|
+
}
|
488
|
+
|
489
|
+
#define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp
|
490
|
+
|
491
|
+
static UINT ole_encoding2cp(rb_encoding *enc)
|
492
|
+
{
|
493
|
+
/*
|
494
|
+
* Is there any better solution to convert
|
495
|
+
* Ruby encoding to Windows codepage???
|
496
|
+
*/
|
497
|
+
ENC_MACHING_CP(enc, "Big5", 950);
|
498
|
+
ENC_MACHING_CP(enc, "CP51932", 51932);
|
499
|
+
ENC_MACHING_CP(enc, "CP850", 850);
|
500
|
+
ENC_MACHING_CP(enc, "CP852", 852);
|
501
|
+
ENC_MACHING_CP(enc, "CP855", 855);
|
502
|
+
ENC_MACHING_CP(enc, "CP949", 949);
|
503
|
+
ENC_MACHING_CP(enc, "EUC-JP", 20932);
|
504
|
+
ENC_MACHING_CP(enc, "EUC-KR", 51949);
|
505
|
+
ENC_MACHING_CP(enc, "EUC-TW", 51950);
|
506
|
+
ENC_MACHING_CP(enc, "GB18030", 54936);
|
507
|
+
ENC_MACHING_CP(enc, "GB2312", 20936);
|
508
|
+
ENC_MACHING_CP(enc, "GBK", 936);
|
509
|
+
ENC_MACHING_CP(enc, "IBM437", 437);
|
510
|
+
ENC_MACHING_CP(enc, "IBM737", 737);
|
511
|
+
ENC_MACHING_CP(enc, "IBM775", 775);
|
512
|
+
ENC_MACHING_CP(enc, "IBM852", 852);
|
513
|
+
ENC_MACHING_CP(enc, "IBM855", 855);
|
514
|
+
ENC_MACHING_CP(enc, "IBM857", 857);
|
515
|
+
ENC_MACHING_CP(enc, "IBM860", 860);
|
516
|
+
ENC_MACHING_CP(enc, "IBM861", 861);
|
517
|
+
ENC_MACHING_CP(enc, "IBM862", 862);
|
518
|
+
ENC_MACHING_CP(enc, "IBM863", 863);
|
519
|
+
ENC_MACHING_CP(enc, "IBM864", 864);
|
520
|
+
ENC_MACHING_CP(enc, "IBM865", 865);
|
521
|
+
ENC_MACHING_CP(enc, "IBM866", 866);
|
522
|
+
ENC_MACHING_CP(enc, "IBM869", 869);
|
523
|
+
ENC_MACHING_CP(enc, "ISO-2022-JP", 50220);
|
524
|
+
ENC_MACHING_CP(enc, "ISO-8859-1", 28591);
|
525
|
+
ENC_MACHING_CP(enc, "ISO-8859-15", 28605);
|
526
|
+
ENC_MACHING_CP(enc, "ISO-8859-2", 28592);
|
527
|
+
ENC_MACHING_CP(enc, "ISO-8859-3", 28593);
|
528
|
+
ENC_MACHING_CP(enc, "ISO-8859-4", 28594);
|
529
|
+
ENC_MACHING_CP(enc, "ISO-8859-5", 28595);
|
530
|
+
ENC_MACHING_CP(enc, "ISO-8859-6", 28596);
|
531
|
+
ENC_MACHING_CP(enc, "ISO-8859-7", 28597);
|
532
|
+
ENC_MACHING_CP(enc, "ISO-8859-8", 28598);
|
533
|
+
ENC_MACHING_CP(enc, "ISO-8859-9", 28599);
|
534
|
+
ENC_MACHING_CP(enc, "KOI8-R", 20866);
|
535
|
+
ENC_MACHING_CP(enc, "KOI8-U", 21866);
|
536
|
+
ENC_MACHING_CP(enc, "Shift_JIS", 932);
|
537
|
+
ENC_MACHING_CP(enc, "UTF-16BE", 1201);
|
538
|
+
ENC_MACHING_CP(enc, "UTF-16LE", 1200);
|
539
|
+
ENC_MACHING_CP(enc, "UTF-7", 65000);
|
540
|
+
ENC_MACHING_CP(enc, "UTF-8", 65001);
|
541
|
+
ENC_MACHING_CP(enc, "Windows-1250", 1250);
|
542
|
+
ENC_MACHING_CP(enc, "Windows-1251", 1251);
|
543
|
+
ENC_MACHING_CP(enc, "Windows-1252", 1252);
|
544
|
+
ENC_MACHING_CP(enc, "Windows-1253", 1253);
|
545
|
+
ENC_MACHING_CP(enc, "Windows-1254", 1254);
|
546
|
+
ENC_MACHING_CP(enc, "Windows-1255", 1255);
|
547
|
+
ENC_MACHING_CP(enc, "Windows-1256", 1256);
|
548
|
+
ENC_MACHING_CP(enc, "Windows-1257", 1257);
|
549
|
+
ENC_MACHING_CP(enc, "Windows-1258", 1258);
|
550
|
+
ENC_MACHING_CP(enc, "Windows-31J", 932);
|
551
|
+
ENC_MACHING_CP(enc, "Windows-874", 874);
|
552
|
+
ENC_MACHING_CP(enc, "eucJP-ms", 20932);
|
553
|
+
return CP_ACP;
|
554
|
+
}
|
555
|
+
|
556
|
+
static void
|
557
|
+
failed_load_conv51932(void)
|
558
|
+
{
|
559
|
+
rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932");
|
560
|
+
}
|
561
|
+
|
562
|
+
#ifndef pIMultiLanguage
|
563
|
+
static void
|
564
|
+
load_conv_function51932(void)
|
565
|
+
{
|
566
|
+
HRESULT hr = E_NOINTERFACE;
|
567
|
+
void *p;
|
568
|
+
if (!pIMultiLanguage) {
|
569
|
+
#if defined(HAVE_TYPE_IMULTILANGUAGE2)
|
570
|
+
hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
|
571
|
+
&IID_IMultiLanguage2, &p);
|
572
|
+
#elif defined(HAVE_TYPE_IMULTILANGUAGE)
|
573
|
+
hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
|
574
|
+
&IID_IMultiLanguage, &p);
|
575
|
+
#endif
|
576
|
+
if (FAILED(hr)) {
|
577
|
+
failed_load_conv51932();
|
578
|
+
}
|
579
|
+
pIMultiLanguage = p;
|
580
|
+
}
|
581
|
+
}
|
582
|
+
#define need_conv_function51932() (load_conv_function51932(), 1)
|
583
|
+
#else
|
584
|
+
#define load_conv_function51932() failed_load_conv51932()
|
585
|
+
#define need_conv_function51932() (failed_load_conv51932(), 0)
|
586
|
+
#endif
|
587
|
+
|
588
|
+
#define conv_51932(cp) ((cp) == 51932 && need_conv_function51932())
|
589
|
+
|
590
|
+
static void
|
591
|
+
set_ole_codepage(UINT cp)
|
592
|
+
{
|
593
|
+
if (code_page_installed(cp)) {
|
594
|
+
cWIN32OLE_cp = cp;
|
595
|
+
} else {
|
596
|
+
switch(cp) {
|
597
|
+
case CP_ACP:
|
598
|
+
case CP_OEMCP:
|
599
|
+
case CP_MACCP:
|
600
|
+
case CP_THREAD_ACP:
|
601
|
+
case CP_SYMBOL:
|
602
|
+
case CP_UTF7:
|
603
|
+
case CP_UTF8:
|
604
|
+
cWIN32OLE_cp = cp;
|
605
|
+
break;
|
606
|
+
case 51932:
|
607
|
+
cWIN32OLE_cp = cp;
|
608
|
+
load_conv_function51932();
|
609
|
+
break;
|
610
|
+
default:
|
611
|
+
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.");
|
612
|
+
break;
|
613
|
+
}
|
614
|
+
}
|
615
|
+
cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
|
616
|
+
}
|
617
|
+
|
618
|
+
|
619
|
+
static UINT
|
620
|
+
ole_init_cp(void)
|
621
|
+
{
|
622
|
+
UINT cp;
|
623
|
+
rb_encoding *encdef;
|
624
|
+
encdef = rb_default_internal_encoding();
|
625
|
+
if (!encdef) {
|
626
|
+
encdef = rb_default_external_encoding();
|
627
|
+
}
|
628
|
+
cp = ole_encoding2cp(encdef);
|
629
|
+
set_ole_codepage(cp);
|
630
|
+
return cp;
|
631
|
+
}
|
632
|
+
|
633
|
+
struct myCPINFOEX {
|
634
|
+
UINT MaxCharSize;
|
635
|
+
BYTE DefaultChar[2];
|
636
|
+
BYTE LeadByte[12];
|
637
|
+
WCHAR UnicodeDefaultChar;
|
638
|
+
UINT CodePage;
|
639
|
+
char CodePageName[MAX_PATH];
|
640
|
+
};
|
641
|
+
|
642
|
+
static rb_encoding *
|
643
|
+
ole_cp2encoding(UINT cp)
|
644
|
+
{
|
645
|
+
static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL;
|
646
|
+
struct myCPINFOEX* buf;
|
647
|
+
VALUE enc_name;
|
648
|
+
char *enc_cstr;
|
649
|
+
int idx;
|
650
|
+
|
651
|
+
if (!code_page_installed(cp)) {
|
652
|
+
switch(cp) {
|
653
|
+
case CP_ACP:
|
654
|
+
cp = GetACP();
|
655
|
+
break;
|
656
|
+
case CP_OEMCP:
|
657
|
+
cp = GetOEMCP();
|
658
|
+
break;
|
659
|
+
case CP_MACCP:
|
660
|
+
case CP_THREAD_ACP:
|
661
|
+
if (!pGetCPInfoEx) {
|
662
|
+
pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
|
663
|
+
GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
|
664
|
+
if (!pGetCPInfoEx) {
|
665
|
+
pGetCPInfoEx = (void*)-1;
|
666
|
+
}
|
667
|
+
}
|
668
|
+
buf = ALLOCA_N(struct myCPINFOEX, 1);
|
669
|
+
ZeroMemory(buf, sizeof(struct myCPINFOEX));
|
670
|
+
if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
|
671
|
+
rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
|
672
|
+
break; /* never reach here */
|
673
|
+
}
|
674
|
+
cp = buf->CodePage;
|
675
|
+
break;
|
676
|
+
case CP_SYMBOL:
|
677
|
+
case CP_UTF7:
|
678
|
+
case CP_UTF8:
|
679
|
+
break;
|
680
|
+
case 51932:
|
681
|
+
load_conv_function51932();
|
682
|
+
break;
|
683
|
+
default:
|
684
|
+
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.");
|
685
|
+
break;
|
686
|
+
}
|
687
|
+
}
|
688
|
+
|
689
|
+
enc_name = rb_sprintf("CP%d", cp);
|
690
|
+
idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name));
|
691
|
+
if (idx < 0)
|
692
|
+
idx = rb_define_dummy_encoding(enc_cstr);
|
693
|
+
return rb_enc_from_index(idx);
|
694
|
+
}
|
695
|
+
|
696
|
+
#ifndef pIMultiLanguage
|
697
|
+
static HRESULT
|
698
|
+
ole_ml_wc2mb_conv0(LPWSTR pw, LPSTR pm, UINT *size)
|
699
|
+
{
|
700
|
+
DWORD dw = 0;
|
701
|
+
return pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
|
702
|
+
&dw, cWIN32OLE_cp, pw, NULL, pm, size);
|
703
|
+
}
|
704
|
+
#define ole_ml_wc2mb_conv(pw, pm, size, onfailure) do { \
|
705
|
+
HRESULT hr = ole_ml_wc2mb_conv0(pw, pm, &size); \
|
706
|
+
if (FAILED(hr)) { \
|
707
|
+
onfailure; \
|
708
|
+
ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); \
|
709
|
+
} \
|
710
|
+
} while (0)
|
711
|
+
#endif
|
712
|
+
|
713
|
+
#define ole_wc2mb_conv(pw, pm, size) WideCharToMultiByte(cWIN32OLE_cp, 0, (pw), -1, (pm), (size), NULL, NULL)
|
714
|
+
|
715
|
+
static char *
|
716
|
+
ole_wc2mb_alloc(LPWSTR pw, char *(alloc)(UINT size, void *arg), void *arg)
|
717
|
+
{
|
718
|
+
LPSTR pm;
|
719
|
+
UINT size = 0;
|
720
|
+
if (conv_51932(cWIN32OLE_cp)) {
|
721
|
+
#ifndef pIMultiLanguage
|
722
|
+
ole_ml_wc2mb_conv(pw, NULL, size, {});
|
723
|
+
pm = alloc(size, arg);
|
724
|
+
if (size) ole_ml_wc2mb_conv(pw, pm, size, xfree(pm));
|
725
|
+
pm[size] = '\0';
|
726
|
+
return pm;
|
727
|
+
#endif
|
728
|
+
}
|
729
|
+
size = ole_wc2mb_conv(pw, NULL, 0);
|
730
|
+
pm = alloc(size, arg);
|
731
|
+
if (size) ole_wc2mb_conv(pw, pm, size);
|
732
|
+
pm[size] = '\0';
|
733
|
+
return pm;
|
734
|
+
}
|
735
|
+
|
736
|
+
static char *
|
737
|
+
ole_alloc_str(UINT size, void *arg)
|
738
|
+
{
|
739
|
+
return ALLOC_N(char, size + 1);
|
740
|
+
}
|
741
|
+
|
742
|
+
char *
|
743
|
+
ole_wc2mb(LPWSTR pw)
|
744
|
+
{
|
745
|
+
return ole_wc2mb_alloc(pw, ole_alloc_str, NULL);
|
746
|
+
}
|
747
|
+
|
748
|
+
static void
|
749
|
+
ole_freeexceptinfo(EXCEPINFO *pExInfo)
|
750
|
+
{
|
751
|
+
SysFreeString(pExInfo->bstrDescription);
|
752
|
+
SysFreeString(pExInfo->bstrSource);
|
753
|
+
SysFreeString(pExInfo->bstrHelpFile);
|
754
|
+
}
|
755
|
+
|
756
|
+
static VALUE
|
757
|
+
ole_excepinfo2msg(EXCEPINFO *pExInfo)
|
758
|
+
{
|
759
|
+
char error_code[40];
|
760
|
+
char *pSource = NULL;
|
761
|
+
char *pDescription = NULL;
|
762
|
+
VALUE error_msg;
|
763
|
+
if(pExInfo->pfnDeferredFillIn != NULL) {
|
764
|
+
(*pExInfo->pfnDeferredFillIn)(pExInfo);
|
765
|
+
}
|
766
|
+
if (pExInfo->bstrSource != NULL) {
|
767
|
+
pSource = ole_wc2mb(pExInfo->bstrSource);
|
768
|
+
}
|
769
|
+
if (pExInfo->bstrDescription != NULL) {
|
770
|
+
pDescription = ole_wc2mb(pExInfo->bstrDescription);
|
771
|
+
}
|
772
|
+
if(pExInfo->wCode == 0) {
|
773
|
+
sprintf(error_code, "\n OLE error code:%lX in ", (unsigned long)pExInfo->scode);
|
774
|
+
}
|
775
|
+
else{
|
776
|
+
sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode);
|
777
|
+
}
|
778
|
+
error_msg = rb_str_new2(error_code);
|
779
|
+
if(pSource != NULL) {
|
780
|
+
rb_str_cat2(error_msg, pSource);
|
781
|
+
}
|
782
|
+
else {
|
783
|
+
rb_str_cat(error_msg, "<Unknown>", 9);
|
784
|
+
}
|
785
|
+
rb_str_cat2(error_msg, "\n ");
|
786
|
+
if(pDescription != NULL) {
|
787
|
+
rb_str_cat2(error_msg, pDescription);
|
788
|
+
}
|
789
|
+
else {
|
790
|
+
rb_str_cat2(error_msg, "<No Description>");
|
791
|
+
}
|
792
|
+
if(pSource) free(pSource);
|
793
|
+
if(pDescription) free(pDescription);
|
794
|
+
ole_freeexceptinfo(pExInfo);
|
795
|
+
return error_msg;
|
796
|
+
}
|
797
|
+
|
798
|
+
void
|
799
|
+
ole_uninitialize(void)
|
800
|
+
{
|
801
|
+
if (!g_ole_initialized) return;
|
802
|
+
OleUninitialize();
|
803
|
+
g_ole_initialized_set(FALSE);
|
804
|
+
}
|
805
|
+
|
806
|
+
static void
|
807
|
+
ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
|
808
|
+
{
|
809
|
+
ole_uninitialize();
|
810
|
+
}
|
811
|
+
|
812
|
+
void
|
813
|
+
ole_initialize(void)
|
814
|
+
{
|
815
|
+
HRESULT hr;
|
816
|
+
|
817
|
+
if(!g_uninitialize_hooked) {
|
818
|
+
rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil);
|
819
|
+
g_uninitialize_hooked = TRUE;
|
820
|
+
}
|
821
|
+
|
822
|
+
if(g_ole_initialized == FALSE) {
|
823
|
+
if(g_running_nano) {
|
824
|
+
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
825
|
+
} else {
|
826
|
+
hr = OleInitialize(NULL);
|
827
|
+
}
|
828
|
+
if(FAILED(hr)) {
|
829
|
+
ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize");
|
830
|
+
}
|
831
|
+
g_ole_initialized_set(TRUE);
|
832
|
+
|
833
|
+
if (g_running_nano == FALSE) {
|
834
|
+
hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter);
|
835
|
+
if(FAILED(hr)) {
|
836
|
+
previous_filter = NULL;
|
837
|
+
ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter");
|
838
|
+
}
|
839
|
+
}
|
840
|
+
}
|
841
|
+
}
|
842
|
+
|
843
|
+
static void
|
844
|
+
ole_free(void *ptr)
|
845
|
+
{
|
846
|
+
struct oledata *pole = ptr;
|
847
|
+
OLE_FREE(pole->pDispatch);
|
848
|
+
free(pole);
|
849
|
+
}
|
850
|
+
|
851
|
+
static size_t ole_size(const void *ptr)
|
852
|
+
{
|
853
|
+
return ptr ? sizeof(struct oledata) : 0;
|
854
|
+
}
|
855
|
+
|
856
|
+
struct oledata *
|
857
|
+
oledata_get_struct(VALUE ole)
|
858
|
+
{
|
859
|
+
struct oledata *pole;
|
860
|
+
TypedData_Get_Struct(ole, struct oledata, &ole_datatype, pole);
|
861
|
+
return pole;
|
862
|
+
}
|
863
|
+
|
864
|
+
LPWSTR
|
865
|
+
ole_vstr2wc(VALUE vstr)
|
866
|
+
{
|
867
|
+
rb_encoding *enc;
|
868
|
+
int cp;
|
869
|
+
LPWSTR pw;
|
870
|
+
st_data_t data;
|
871
|
+
struct st_table *tbl = DATA_PTR(enc2cp_hash);
|
872
|
+
|
873
|
+
/* do not type-conversion here to prevent from other arguments
|
874
|
+
* changing (if exist) */
|
875
|
+
Check_Type(vstr, T_STRING);
|
876
|
+
if (RSTRING_LEN(vstr) == 0) {
|
877
|
+
return NULL;
|
878
|
+
}
|
879
|
+
|
880
|
+
enc = rb_enc_get(vstr);
|
881
|
+
|
882
|
+
if (st_lookup(tbl, (VALUE)enc | FIXNUM_FLAG, &data)) {
|
883
|
+
cp = RB_FIX2INT((VALUE)data);
|
884
|
+
} else {
|
885
|
+
cp = ole_encoding2cp(enc);
|
886
|
+
if (code_page_installed(cp) ||
|
887
|
+
cp == CP_ACP ||
|
888
|
+
cp == CP_OEMCP ||
|
889
|
+
cp == CP_MACCP ||
|
890
|
+
cp == CP_THREAD_ACP ||
|
891
|
+
cp == CP_SYMBOL ||
|
892
|
+
cp == CP_UTF7 ||
|
893
|
+
cp == CP_UTF8 ||
|
894
|
+
cp == 51932) {
|
895
|
+
st_insert(tbl, (VALUE)enc | FIXNUM_FLAG, RB_INT2FIX(cp));
|
896
|
+
} else {
|
897
|
+
rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
|
898
|
+
}
|
899
|
+
}
|
900
|
+
pw = ole_mb2wc(RSTRING_PTR(vstr), RSTRING_LENINT(vstr), cp);
|
901
|
+
RB_GC_GUARD(vstr);
|
902
|
+
return pw;
|
903
|
+
}
|
904
|
+
|
905
|
+
static LPWSTR
|
906
|
+
ole_mb2wc(char *pm, int len, UINT cp)
|
907
|
+
{
|
908
|
+
UINT size = 0;
|
909
|
+
LPWSTR pw;
|
910
|
+
|
911
|
+
if (conv_51932(cp)) {
|
912
|
+
#ifndef pIMultiLanguage
|
913
|
+
DWORD dw = 0;
|
914
|
+
UINT n = len;
|
915
|
+
HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
|
916
|
+
&dw, cp, pm, &n, NULL, &size);
|
917
|
+
if (FAILED(hr)) {
|
918
|
+
ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
|
919
|
+
}
|
920
|
+
pw = SysAllocStringLen(NULL, size);
|
921
|
+
n = len;
|
922
|
+
hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
|
923
|
+
&dw, cp, pm, &n, pw, &size);
|
924
|
+
if (FAILED(hr)) {
|
925
|
+
ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
|
926
|
+
}
|
927
|
+
return pw;
|
928
|
+
#endif
|
929
|
+
}
|
930
|
+
size = MultiByteToWideChar(cp, 0, pm, len, NULL, 0);
|
931
|
+
pw = SysAllocStringLen(NULL, size);
|
932
|
+
pw[size-1] = 0;
|
933
|
+
MultiByteToWideChar(cp, 0, pm, len, pw, size);
|
934
|
+
return pw;
|
935
|
+
}
|
936
|
+
|
937
|
+
static char *
|
938
|
+
ole_alloc_vstr(UINT size, void *arg)
|
939
|
+
{
|
940
|
+
VALUE str = rb_enc_str_new(NULL, size, cWIN32OLE_enc);
|
941
|
+
*(VALUE *)arg = str;
|
942
|
+
return RSTRING_PTR(str);
|
943
|
+
}
|
944
|
+
|
945
|
+
VALUE
|
946
|
+
ole_wc2vstr(LPWSTR pw, BOOL isfree)
|
947
|
+
{
|
948
|
+
VALUE vstr;
|
949
|
+
ole_wc2mb_alloc(pw, ole_alloc_vstr, &vstr);
|
950
|
+
rb_str_set_len(vstr, (long)strlen(RSTRING_PTR(vstr)));
|
951
|
+
if(isfree)
|
952
|
+
SysFreeString(pw);
|
953
|
+
return vstr;
|
954
|
+
}
|
955
|
+
|
956
|
+
static VALUE
|
957
|
+
ole_ary_m_entry(VALUE val, LONG *pid)
|
958
|
+
{
|
959
|
+
VALUE obj = Qnil;
|
960
|
+
int i = 0;
|
961
|
+
obj = val;
|
962
|
+
while(RB_TYPE_P(obj, T_ARRAY)) {
|
963
|
+
obj = rb_ary_entry(obj, pid[i]);
|
964
|
+
i++;
|
965
|
+
}
|
966
|
+
return obj;
|
967
|
+
}
|
968
|
+
|
969
|
+
static VALUE
|
970
|
+
is_all_index_under(LONG *pid, long *pub, long dim)
|
971
|
+
{
|
972
|
+
long i = 0;
|
973
|
+
for (i = 0; i < dim; i++) {
|
974
|
+
if (pid[i] > pub[i]) {
|
975
|
+
return Qfalse;
|
976
|
+
}
|
977
|
+
}
|
978
|
+
return Qtrue;
|
979
|
+
}
|
980
|
+
|
981
|
+
void
|
982
|
+
ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
|
983
|
+
{
|
984
|
+
if (val == Qnil) {
|
985
|
+
if (vt == VT_VARIANT) {
|
986
|
+
ole_val2variant2(val, var);
|
987
|
+
} else {
|
988
|
+
V_VT(var) = (vt & ~VT_BYREF);
|
989
|
+
if (V_VT(var) == VT_DISPATCH) {
|
990
|
+
V_DISPATCH(var) = NULL;
|
991
|
+
} else if (V_VT(var) == VT_UNKNOWN) {
|
992
|
+
V_UNKNOWN(var) = NULL;
|
993
|
+
}
|
994
|
+
}
|
995
|
+
return;
|
996
|
+
}
|
997
|
+
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
998
|
+
switch(vt & ~VT_BYREF) {
|
999
|
+
case VT_I8:
|
1000
|
+
V_VT(var) = VT_I8;
|
1001
|
+
V_I8(var) = NUM2I8 (val);
|
1002
|
+
break;
|
1003
|
+
case VT_UI8:
|
1004
|
+
V_VT(var) = VT_UI8;
|
1005
|
+
V_UI8(var) = NUM2UI8(val);
|
1006
|
+
break;
|
1007
|
+
default:
|
1008
|
+
ole_val2variant2(val, var);
|
1009
|
+
break;
|
1010
|
+
}
|
1011
|
+
#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
|
1012
|
+
ole_val2variant2(val, var);
|
1013
|
+
#endif
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
VOID *
|
1017
|
+
val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
|
1018
|
+
{
|
1019
|
+
VOID *p = NULL;
|
1020
|
+
HRESULT hr = S_OK;
|
1021
|
+
ole_val2variant_ex(val, var, vt);
|
1022
|
+
if ((vt & ~VT_BYREF) == VT_VARIANT) {
|
1023
|
+
p = var;
|
1024
|
+
} else {
|
1025
|
+
if ( (vt & ~VT_BYREF) != V_VT(var)) {
|
1026
|
+
hr = VariantChangeTypeEx(var, var,
|
1027
|
+
cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
|
1028
|
+
if (FAILED(hr)) {
|
1029
|
+
ole_raise(hr, rb_eRuntimeError, "failed to change type");
|
1030
|
+
}
|
1031
|
+
}
|
1032
|
+
p = get_ptr_of_variant(var);
|
1033
|
+
}
|
1034
|
+
if (p == NULL) {
|
1035
|
+
rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
|
1036
|
+
}
|
1037
|
+
return p;
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
static void *
|
1041
|
+
get_ptr_of_variant(VARIANT *pvar)
|
1042
|
+
{
|
1043
|
+
switch(V_VT(pvar)) {
|
1044
|
+
case VT_UI1:
|
1045
|
+
return &V_UI1(pvar);
|
1046
|
+
break;
|
1047
|
+
case VT_I2:
|
1048
|
+
return &V_I2(pvar);
|
1049
|
+
break;
|
1050
|
+
case VT_UI2:
|
1051
|
+
return &V_UI2(pvar);
|
1052
|
+
break;
|
1053
|
+
case VT_I4:
|
1054
|
+
return &V_I4(pvar);
|
1055
|
+
break;
|
1056
|
+
case VT_UI4:
|
1057
|
+
return &V_UI4(pvar);
|
1058
|
+
break;
|
1059
|
+
case VT_R4:
|
1060
|
+
return &V_R4(pvar);
|
1061
|
+
break;
|
1062
|
+
case VT_R8:
|
1063
|
+
return &V_R8(pvar);
|
1064
|
+
break;
|
1065
|
+
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
1066
|
+
case VT_I8:
|
1067
|
+
return &V_I8(pvar);
|
1068
|
+
break;
|
1069
|
+
case VT_UI8:
|
1070
|
+
return &V_UI8(pvar);
|
1071
|
+
break;
|
1072
|
+
#endif
|
1073
|
+
case VT_INT:
|
1074
|
+
return &V_INT(pvar);
|
1075
|
+
break;
|
1076
|
+
case VT_UINT:
|
1077
|
+
return &V_UINT(pvar);
|
1078
|
+
break;
|
1079
|
+
case VT_CY:
|
1080
|
+
return &V_CY(pvar);
|
1081
|
+
break;
|
1082
|
+
case VT_DATE:
|
1083
|
+
return &V_DATE(pvar);
|
1084
|
+
break;
|
1085
|
+
case VT_BSTR:
|
1086
|
+
return V_BSTR(pvar);
|
1087
|
+
break;
|
1088
|
+
case VT_DISPATCH:
|
1089
|
+
return V_DISPATCH(pvar);
|
1090
|
+
break;
|
1091
|
+
case VT_ERROR:
|
1092
|
+
return &V_ERROR(pvar);
|
1093
|
+
break;
|
1094
|
+
case VT_BOOL:
|
1095
|
+
return &V_BOOL(pvar);
|
1096
|
+
break;
|
1097
|
+
case VT_UNKNOWN:
|
1098
|
+
return V_UNKNOWN(pvar);
|
1099
|
+
break;
|
1100
|
+
case VT_ARRAY:
|
1101
|
+
return &V_ARRAY(pvar);
|
1102
|
+
break;
|
1103
|
+
default:
|
1104
|
+
return NULL;
|
1105
|
+
break;
|
1106
|
+
}
|
1107
|
+
}
|
1108
|
+
|
1109
|
+
static void
|
1110
|
+
ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt)
|
1111
|
+
{
|
1112
|
+
VALUE val1;
|
1113
|
+
HRESULT hr = S_OK;
|
1114
|
+
VARIANT var;
|
1115
|
+
VOID *p = NULL;
|
1116
|
+
long i = n;
|
1117
|
+
while(i >= 0) {
|
1118
|
+
val1 = ole_ary_m_entry(val, pid);
|
1119
|
+
VariantInit(&var);
|
1120
|
+
p = val2variant_ptr(val1, &var, vt);
|
1121
|
+
if (is_all_index_under(pid, pub, dim) == Qtrue) {
|
1122
|
+
if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
|
1123
|
+
(V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
|
1124
|
+
rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface");
|
1125
|
+
}
|
1126
|
+
hr = SafeArrayPutElement(psa, pid, p);
|
1127
|
+
}
|
1128
|
+
if (FAILED(hr)) {
|
1129
|
+
ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement");
|
1130
|
+
}
|
1131
|
+
pid[i] += 1;
|
1132
|
+
if (pid[i] > pub[i]) {
|
1133
|
+
pid[i] = 0;
|
1134
|
+
i -= 1;
|
1135
|
+
} else {
|
1136
|
+
i = dim - 1;
|
1137
|
+
}
|
1138
|
+
}
|
1139
|
+
}
|
1140
|
+
|
1141
|
+
static long
|
1142
|
+
dimension(VALUE val) {
|
1143
|
+
long dim = 0;
|
1144
|
+
long dim1 = 0;
|
1145
|
+
long len = 0;
|
1146
|
+
long i = 0;
|
1147
|
+
if (RB_TYPE_P(val, T_ARRAY)) {
|
1148
|
+
len = RARRAY_LEN(val);
|
1149
|
+
for (i = 0; i < len; i++) {
|
1150
|
+
dim1 = dimension(rb_ary_entry(val, i));
|
1151
|
+
if (dim < dim1) {
|
1152
|
+
dim = dim1;
|
1153
|
+
}
|
1154
|
+
}
|
1155
|
+
dim += 1;
|
1156
|
+
}
|
1157
|
+
return dim;
|
1158
|
+
}
|
1159
|
+
|
1160
|
+
static long
|
1161
|
+
ary_len_of_dim(VALUE ary, long dim) {
|
1162
|
+
long ary_len = 0;
|
1163
|
+
long ary_len1 = 0;
|
1164
|
+
long len = 0;
|
1165
|
+
long i = 0;
|
1166
|
+
VALUE val;
|
1167
|
+
if (dim == 0) {
|
1168
|
+
if (RB_TYPE_P(ary, T_ARRAY)) {
|
1169
|
+
ary_len = RARRAY_LEN(ary);
|
1170
|
+
}
|
1171
|
+
} else {
|
1172
|
+
if (RB_TYPE_P(ary, T_ARRAY)) {
|
1173
|
+
len = RARRAY_LEN(ary);
|
1174
|
+
for (i = 0; i < len; i++) {
|
1175
|
+
val = rb_ary_entry(ary, i);
|
1176
|
+
ary_len1 = ary_len_of_dim(val, dim-1);
|
1177
|
+
if (ary_len < ary_len1) {
|
1178
|
+
ary_len = ary_len1;
|
1179
|
+
}
|
1180
|
+
}
|
1181
|
+
}
|
1182
|
+
}
|
1183
|
+
return ary_len;
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
HRESULT
|
1187
|
+
ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
|
1188
|
+
{
|
1189
|
+
long dim = 0;
|
1190
|
+
int i = 0;
|
1191
|
+
HRESULT hr = S_OK;
|
1192
|
+
|
1193
|
+
SAFEARRAYBOUND *psab = NULL;
|
1194
|
+
SAFEARRAY *psa = NULL;
|
1195
|
+
long *pub;
|
1196
|
+
LONG *pid;
|
1197
|
+
|
1198
|
+
Check_Type(val, T_ARRAY);
|
1199
|
+
|
1200
|
+
dim = dimension(val);
|
1201
|
+
|
1202
|
+
psab = ALLOC_N(SAFEARRAYBOUND, dim);
|
1203
|
+
pub = ALLOC_N(long, dim);
|
1204
|
+
pid = ALLOC_N(LONG, dim);
|
1205
|
+
|
1206
|
+
if(!psab || !pub || !pid) {
|
1207
|
+
if(pub) free(pub);
|
1208
|
+
if(psab) free(psab);
|
1209
|
+
if(pid) free(pid);
|
1210
|
+
rb_raise(rb_eRuntimeError, "memory allocation error");
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
for (i = 0; i < dim; i++) {
|
1214
|
+
psab[i].cElements = ary_len_of_dim(val, i);
|
1215
|
+
psab[i].lLbound = 0;
|
1216
|
+
pub[i] = psab[i].cElements - 1;
|
1217
|
+
pid[i] = 0;
|
1218
|
+
}
|
1219
|
+
/* Create and fill VARIANT array */
|
1220
|
+
if ((vt & ~VT_BYREF) == VT_ARRAY) {
|
1221
|
+
vt = (vt | VT_VARIANT);
|
1222
|
+
}
|
1223
|
+
psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
|
1224
|
+
if (psa == NULL)
|
1225
|
+
hr = E_OUTOFMEMORY;
|
1226
|
+
else
|
1227
|
+
hr = SafeArrayLock(psa);
|
1228
|
+
if (SUCCEEDED(hr)) {
|
1229
|
+
ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK));
|
1230
|
+
hr = SafeArrayUnlock(psa);
|
1231
|
+
}
|
1232
|
+
|
1233
|
+
if(pub) free(pub);
|
1234
|
+
if(psab) free(psab);
|
1235
|
+
if(pid) free(pid);
|
1236
|
+
|
1237
|
+
if (SUCCEEDED(hr)) {
|
1238
|
+
V_VT(var) = vt;
|
1239
|
+
V_ARRAY(var) = psa;
|
1240
|
+
}
|
1241
|
+
else {
|
1242
|
+
if (psa != NULL)
|
1243
|
+
SafeArrayDestroy(psa);
|
1244
|
+
}
|
1245
|
+
return hr;
|
1246
|
+
}
|
1247
|
+
|
1248
|
+
void
|
1249
|
+
ole_val2variant(VALUE val, VARIANT *var)
|
1250
|
+
{
|
1251
|
+
struct oledata *pole = NULL;
|
1252
|
+
if(rb_obj_is_kind_of(val, cWIN32OLE)) {
|
1253
|
+
pole = oledata_get_struct(val);
|
1254
|
+
OLE_ADDREF(pole->pDispatch);
|
1255
|
+
V_VT(var) = VT_DISPATCH;
|
1256
|
+
V_DISPATCH(var) = pole->pDispatch;
|
1257
|
+
return;
|
1258
|
+
}
|
1259
|
+
if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) {
|
1260
|
+
ole_variant2variant(val, var);
|
1261
|
+
return;
|
1262
|
+
}
|
1263
|
+
if (rb_obj_is_kind_of(val, cWIN32OLE_RECORD)) {
|
1264
|
+
ole_rec2variant(val, var);
|
1265
|
+
return;
|
1266
|
+
}
|
1267
|
+
if (rb_obj_is_kind_of(val, rb_cTime)) {
|
1268
|
+
V_VT(var) = VT_DATE;
|
1269
|
+
V_DATE(var) = rbtime2vtdate(val);
|
1270
|
+
return;
|
1271
|
+
}
|
1272
|
+
switch (TYPE(val)) {
|
1273
|
+
case T_ARRAY:
|
1274
|
+
ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY);
|
1275
|
+
break;
|
1276
|
+
case T_STRING:
|
1277
|
+
V_VT(var) = VT_BSTR;
|
1278
|
+
V_BSTR(var) = ole_vstr2wc(val);
|
1279
|
+
break;
|
1280
|
+
case T_FIXNUM:
|
1281
|
+
V_VT(var) = VT_I4;
|
1282
|
+
{
|
1283
|
+
long v = RB_NUM2LONG(val);
|
1284
|
+
V_I4(var) = (LONG)v;
|
1285
|
+
#if SIZEOF_LONG > 4
|
1286
|
+
if (V_I4(var) != v) {
|
1287
|
+
V_I8(var) = v;
|
1288
|
+
V_VT(var) = VT_I8;
|
1289
|
+
}
|
1290
|
+
#endif
|
1291
|
+
}
|
1292
|
+
break;
|
1293
|
+
case T_BIGNUM:
|
1294
|
+
V_VT(var) = VT_R8;
|
1295
|
+
V_R8(var) = rb_big2dbl(val);
|
1296
|
+
break;
|
1297
|
+
case T_FLOAT:
|
1298
|
+
V_VT(var) = VT_R8;
|
1299
|
+
V_R8(var) = NUM2DBL(val);
|
1300
|
+
break;
|
1301
|
+
case T_TRUE:
|
1302
|
+
V_VT(var) = VT_BOOL;
|
1303
|
+
V_BOOL(var) = VARIANT_TRUE;
|
1304
|
+
break;
|
1305
|
+
case T_FALSE:
|
1306
|
+
V_VT(var) = VT_BOOL;
|
1307
|
+
V_BOOL(var) = VARIANT_FALSE;
|
1308
|
+
break;
|
1309
|
+
case T_NIL:
|
1310
|
+
if (g_nil_to == VT_ERROR) {
|
1311
|
+
V_VT(var) = VT_ERROR;
|
1312
|
+
V_ERROR(var) = DISP_E_PARAMNOTFOUND;
|
1313
|
+
}else {
|
1314
|
+
V_VT(var) = VT_EMPTY;
|
1315
|
+
}
|
1316
|
+
break;
|
1317
|
+
default:
|
1318
|
+
V_VT(var) = VT_DISPATCH;
|
1319
|
+
V_DISPATCH(var) = val2dispatch(val);
|
1320
|
+
break;
|
1321
|
+
}
|
1322
|
+
}
|
1323
|
+
|
1324
|
+
void
|
1325
|
+
ole_val2variant2(VALUE val, VARIANT *var)
|
1326
|
+
{
|
1327
|
+
g_nil_to = VT_EMPTY;
|
1328
|
+
ole_val2variant(val, var);
|
1329
|
+
g_nil_to = VT_ERROR;
|
1330
|
+
}
|
1331
|
+
|
1332
|
+
VALUE
|
1333
|
+
make_inspect(const char *class_name, VALUE detail)
|
1334
|
+
{
|
1335
|
+
VALUE str;
|
1336
|
+
str = rb_str_new2("#<");
|
1337
|
+
rb_str_cat2(str, class_name);
|
1338
|
+
rb_str_cat2(str, ":");
|
1339
|
+
rb_str_concat(str, detail);
|
1340
|
+
rb_str_cat2(str, ">");
|
1341
|
+
return str;
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
VALUE
|
1345
|
+
default_inspect(VALUE self, const char *class_name)
|
1346
|
+
{
|
1347
|
+
VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
|
1348
|
+
return make_inspect(class_name, detail);
|
1349
|
+
}
|
1350
|
+
|
1351
|
+
static VALUE
|
1352
|
+
ole_set_member(VALUE self, IDispatch *dispatch)
|
1353
|
+
{
|
1354
|
+
struct oledata *pole = NULL;
|
1355
|
+
pole = oledata_get_struct(self);
|
1356
|
+
if (pole->pDispatch) {
|
1357
|
+
OLE_RELEASE(pole->pDispatch);
|
1358
|
+
pole->pDispatch = NULL;
|
1359
|
+
}
|
1360
|
+
pole->pDispatch = dispatch;
|
1361
|
+
return self;
|
1362
|
+
}
|
1363
|
+
|
1364
|
+
|
1365
|
+
static VALUE
|
1366
|
+
fole_s_allocate(VALUE klass)
|
1367
|
+
{
|
1368
|
+
struct oledata *pole;
|
1369
|
+
VALUE obj;
|
1370
|
+
ole_initialize();
|
1371
|
+
obj = TypedData_Make_Struct(klass, struct oledata, &ole_datatype, pole);
|
1372
|
+
pole->pDispatch = NULL;
|
1373
|
+
return obj;
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
static VALUE
|
1377
|
+
create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv)
|
1378
|
+
{
|
1379
|
+
VALUE obj = fole_s_allocate(klass);
|
1380
|
+
ole_set_member(obj, pDispatch);
|
1381
|
+
return obj;
|
1382
|
+
}
|
1383
|
+
|
1384
|
+
static VALUE
|
1385
|
+
ary_new_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim) {
|
1386
|
+
long i;
|
1387
|
+
VALUE obj = Qnil;
|
1388
|
+
VALUE pobj = Qnil;
|
1389
|
+
long *ids = ALLOC_N(long, dim);
|
1390
|
+
if (!ids) {
|
1391
|
+
rb_raise(rb_eRuntimeError, "memory allocation error");
|
1392
|
+
}
|
1393
|
+
for(i = 0; i < dim; i++) {
|
1394
|
+
ids[i] = pid[i] - plb[i];
|
1395
|
+
}
|
1396
|
+
obj = myary;
|
1397
|
+
pobj = myary;
|
1398
|
+
for(i = 0; i < dim-1; i++) {
|
1399
|
+
obj = rb_ary_entry(pobj, ids[i]);
|
1400
|
+
if (obj == Qnil) {
|
1401
|
+
rb_ary_store(pobj, ids[i], rb_ary_new());
|
1402
|
+
}
|
1403
|
+
obj = rb_ary_entry(pobj, ids[i]);
|
1404
|
+
pobj = obj;
|
1405
|
+
}
|
1406
|
+
if (ids) free(ids);
|
1407
|
+
return obj;
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
static void
|
1411
|
+
ary_store_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim, VALUE val) {
|
1412
|
+
long id = pid[dim - 1] - plb[dim - 1];
|
1413
|
+
VALUE obj = ary_new_dim(myary, pid, plb, dim);
|
1414
|
+
rb_ary_store(obj, id, val);
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
VALUE
|
1418
|
+
ole_variant2val(VARIANT *pvar)
|
1419
|
+
{
|
1420
|
+
VALUE obj = Qnil;
|
1421
|
+
VARTYPE vt = V_VT(pvar);
|
1422
|
+
HRESULT hr;
|
1423
|
+
while ( vt == (VT_BYREF | VT_VARIANT) ) {
|
1424
|
+
pvar = V_VARIANTREF(pvar);
|
1425
|
+
vt = V_VT(pvar);
|
1426
|
+
}
|
1427
|
+
|
1428
|
+
if(V_ISARRAY(pvar)) {
|
1429
|
+
VARTYPE vt_base = vt & VT_TYPEMASK;
|
1430
|
+
SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar);
|
1431
|
+
UINT i = 0;
|
1432
|
+
LONG *pid, *plb, *pub;
|
1433
|
+
VARIANT variant;
|
1434
|
+
VALUE val;
|
1435
|
+
UINT dim = 0;
|
1436
|
+
if (!psa) {
|
1437
|
+
return obj;
|
1438
|
+
}
|
1439
|
+
dim = SafeArrayGetDim(psa);
|
1440
|
+
pid = ALLOC_N(LONG, dim);
|
1441
|
+
plb = ALLOC_N(LONG, dim);
|
1442
|
+
pub = ALLOC_N(LONG, dim);
|
1443
|
+
|
1444
|
+
if(!pid || !plb || !pub) {
|
1445
|
+
if(pid) free(pid);
|
1446
|
+
if(plb) free(plb);
|
1447
|
+
if(pub) free(pub);
|
1448
|
+
rb_raise(rb_eRuntimeError, "memory allocation error");
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
for(i = 0; i < dim; ++i) {
|
1452
|
+
SafeArrayGetLBound(psa, i+1, &plb[i]);
|
1453
|
+
SafeArrayGetLBound(psa, i+1, &pid[i]);
|
1454
|
+
SafeArrayGetUBound(psa, i+1, &pub[i]);
|
1455
|
+
}
|
1456
|
+
hr = SafeArrayLock(psa);
|
1457
|
+
if (SUCCEEDED(hr)) {
|
1458
|
+
obj = rb_ary_new();
|
1459
|
+
i = 0;
|
1460
|
+
VariantInit(&variant);
|
1461
|
+
V_VT(&variant) = vt_base | VT_BYREF;
|
1462
|
+
if (vt_base == VT_RECORD) {
|
1463
|
+
hr = SafeArrayGetRecordInfo(psa, &V_RECORDINFO(&variant));
|
1464
|
+
if (SUCCEEDED(hr)) {
|
1465
|
+
V_VT(&variant) = VT_RECORD;
|
1466
|
+
}
|
1467
|
+
}
|
1468
|
+
while (i < dim) {
|
1469
|
+
ary_new_dim(obj, pid, plb, dim);
|
1470
|
+
if (vt_base == VT_RECORD)
|
1471
|
+
hr = SafeArrayPtrOfIndex(psa, pid, &V_RECORD(&variant));
|
1472
|
+
else
|
1473
|
+
hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
|
1474
|
+
if (SUCCEEDED(hr)) {
|
1475
|
+
val = ole_variant2val(&variant);
|
1476
|
+
ary_store_dim(obj, pid, plb, dim, val);
|
1477
|
+
}
|
1478
|
+
for (i = 0; i < dim; ++i) {
|
1479
|
+
if (++pid[i] <= pub[i])
|
1480
|
+
break;
|
1481
|
+
pid[i] = plb[i];
|
1482
|
+
}
|
1483
|
+
}
|
1484
|
+
SafeArrayUnlock(psa);
|
1485
|
+
}
|
1486
|
+
if(pid) free(pid);
|
1487
|
+
if(plb) free(plb);
|
1488
|
+
if(pub) free(pub);
|
1489
|
+
return obj;
|
1490
|
+
}
|
1491
|
+
switch(V_VT(pvar) & ~VT_BYREF){
|
1492
|
+
case VT_EMPTY:
|
1493
|
+
break;
|
1494
|
+
case VT_NULL:
|
1495
|
+
break;
|
1496
|
+
case VT_I1:
|
1497
|
+
if(V_ISBYREF(pvar))
|
1498
|
+
obj = RB_INT2NUM((long)*V_I1REF(pvar));
|
1499
|
+
else
|
1500
|
+
obj = RB_INT2NUM((long)V_I1(pvar));
|
1501
|
+
break;
|
1502
|
+
|
1503
|
+
case VT_UI1:
|
1504
|
+
if(V_ISBYREF(pvar))
|
1505
|
+
obj = RB_INT2NUM((long)*V_UI1REF(pvar));
|
1506
|
+
else
|
1507
|
+
obj = RB_INT2NUM((long)V_UI1(pvar));
|
1508
|
+
break;
|
1509
|
+
|
1510
|
+
case VT_I2:
|
1511
|
+
if(V_ISBYREF(pvar))
|
1512
|
+
obj = RB_INT2NUM((long)*V_I2REF(pvar));
|
1513
|
+
else
|
1514
|
+
obj = RB_INT2NUM((long)V_I2(pvar));
|
1515
|
+
break;
|
1516
|
+
|
1517
|
+
case VT_UI2:
|
1518
|
+
if(V_ISBYREF(pvar))
|
1519
|
+
obj = RB_INT2NUM((long)*V_UI2REF(pvar));
|
1520
|
+
else
|
1521
|
+
obj = RB_INT2NUM((long)V_UI2(pvar));
|
1522
|
+
break;
|
1523
|
+
|
1524
|
+
case VT_I4:
|
1525
|
+
if(V_ISBYREF(pvar))
|
1526
|
+
obj = RB_INT2NUM((long)*V_I4REF(pvar));
|
1527
|
+
else
|
1528
|
+
obj = RB_INT2NUM((long)V_I4(pvar));
|
1529
|
+
break;
|
1530
|
+
|
1531
|
+
case VT_UI4:
|
1532
|
+
if(V_ISBYREF(pvar))
|
1533
|
+
obj = RB_INT2NUM((long)*V_UI4REF(pvar));
|
1534
|
+
else
|
1535
|
+
obj = RB_INT2NUM((long)V_UI4(pvar));
|
1536
|
+
break;
|
1537
|
+
|
1538
|
+
case VT_INT:
|
1539
|
+
if(V_ISBYREF(pvar))
|
1540
|
+
obj = RB_INT2NUM((long)*V_INTREF(pvar));
|
1541
|
+
else
|
1542
|
+
obj = RB_INT2NUM((long)V_INT(pvar));
|
1543
|
+
break;
|
1544
|
+
|
1545
|
+
case VT_UINT:
|
1546
|
+
if(V_ISBYREF(pvar))
|
1547
|
+
obj = RB_INT2NUM((long)*V_UINTREF(pvar));
|
1548
|
+
else
|
1549
|
+
obj = RB_INT2NUM((long)V_UINT(pvar));
|
1550
|
+
break;
|
1551
|
+
|
1552
|
+
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
1553
|
+
case VT_I8:
|
1554
|
+
if(V_ISBYREF(pvar))
|
1555
|
+
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
1556
|
+
#ifdef V_I8REF
|
1557
|
+
obj = I8_2_NUM(*V_I8REF(pvar));
|
1558
|
+
#endif
|
1559
|
+
#else
|
1560
|
+
obj = Qnil;
|
1561
|
+
#endif
|
1562
|
+
else
|
1563
|
+
obj = I8_2_NUM(V_I8(pvar));
|
1564
|
+
break;
|
1565
|
+
case VT_UI8:
|
1566
|
+
if(V_ISBYREF(pvar))
|
1567
|
+
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
1568
|
+
#ifdef V_UI8REF
|
1569
|
+
obj = UI8_2_NUM(*V_UI8REF(pvar));
|
1570
|
+
#endif
|
1571
|
+
#else
|
1572
|
+
obj = Qnil;
|
1573
|
+
#endif
|
1574
|
+
else
|
1575
|
+
obj = UI8_2_NUM(V_UI8(pvar));
|
1576
|
+
break;
|
1577
|
+
#endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
|
1578
|
+
|
1579
|
+
case VT_R4:
|
1580
|
+
if(V_ISBYREF(pvar))
|
1581
|
+
obj = rb_float_new(*V_R4REF(pvar));
|
1582
|
+
else
|
1583
|
+
obj = rb_float_new(V_R4(pvar));
|
1584
|
+
break;
|
1585
|
+
|
1586
|
+
case VT_R8:
|
1587
|
+
if(V_ISBYREF(pvar))
|
1588
|
+
obj = rb_float_new(*V_R8REF(pvar));
|
1589
|
+
else
|
1590
|
+
obj = rb_float_new(V_R8(pvar));
|
1591
|
+
break;
|
1592
|
+
|
1593
|
+
case VT_BSTR:
|
1594
|
+
{
|
1595
|
+
BSTR bstr;
|
1596
|
+
if(V_ISBYREF(pvar))
|
1597
|
+
bstr = *V_BSTRREF(pvar);
|
1598
|
+
else
|
1599
|
+
bstr = V_BSTR(pvar);
|
1600
|
+
obj = (SysStringLen(bstr) == 0)
|
1601
|
+
? rb_str_new2("")
|
1602
|
+
: ole_wc2vstr(bstr, FALSE);
|
1603
|
+
break;
|
1604
|
+
}
|
1605
|
+
|
1606
|
+
case VT_ERROR:
|
1607
|
+
if(V_ISBYREF(pvar))
|
1608
|
+
obj = RB_INT2NUM(*V_ERRORREF(pvar));
|
1609
|
+
else
|
1610
|
+
obj = RB_INT2NUM(V_ERROR(pvar));
|
1611
|
+
break;
|
1612
|
+
|
1613
|
+
case VT_BOOL:
|
1614
|
+
if (V_ISBYREF(pvar))
|
1615
|
+
obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse);
|
1616
|
+
else
|
1617
|
+
obj = (V_BOOL(pvar) ? Qtrue : Qfalse);
|
1618
|
+
break;
|
1619
|
+
|
1620
|
+
case VT_DISPATCH:
|
1621
|
+
{
|
1622
|
+
IDispatch *pDispatch;
|
1623
|
+
|
1624
|
+
if (V_ISBYREF(pvar))
|
1625
|
+
pDispatch = *V_DISPATCHREF(pvar);
|
1626
|
+
else
|
1627
|
+
pDispatch = V_DISPATCH(pvar);
|
1628
|
+
|
1629
|
+
if (pDispatch != NULL ) {
|
1630
|
+
OLE_ADDREF(pDispatch);
|
1631
|
+
obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
|
1632
|
+
}
|
1633
|
+
break;
|
1634
|
+
}
|
1635
|
+
|
1636
|
+
case VT_UNKNOWN:
|
1637
|
+
{
|
1638
|
+
/* get IDispatch interface from IUnknown interface */
|
1639
|
+
IUnknown *punk;
|
1640
|
+
IDispatch *pDispatch;
|
1641
|
+
void *p;
|
1642
|
+
HRESULT hr;
|
1643
|
+
|
1644
|
+
if (V_ISBYREF(pvar))
|
1645
|
+
punk = *V_UNKNOWNREF(pvar);
|
1646
|
+
else
|
1647
|
+
punk = V_UNKNOWN(pvar);
|
1648
|
+
|
1649
|
+
if(punk != NULL) {
|
1650
|
+
hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p);
|
1651
|
+
if(SUCCEEDED(hr)) {
|
1652
|
+
pDispatch = p;
|
1653
|
+
obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
|
1654
|
+
}
|
1655
|
+
}
|
1656
|
+
break;
|
1657
|
+
}
|
1658
|
+
|
1659
|
+
case VT_DATE:
|
1660
|
+
{
|
1661
|
+
DATE date;
|
1662
|
+
if(V_ISBYREF(pvar))
|
1663
|
+
date = *V_DATEREF(pvar);
|
1664
|
+
else
|
1665
|
+
date = V_DATE(pvar);
|
1666
|
+
|
1667
|
+
obj = vtdate2rbtime(date);
|
1668
|
+
break;
|
1669
|
+
}
|
1670
|
+
|
1671
|
+
case VT_RECORD:
|
1672
|
+
{
|
1673
|
+
IRecordInfo *pri = V_RECORDINFO(pvar);
|
1674
|
+
void *prec = V_RECORD(pvar);
|
1675
|
+
obj = create_win32ole_record(pri, prec);
|
1676
|
+
break;
|
1677
|
+
}
|
1678
|
+
|
1679
|
+
case VT_CY:
|
1680
|
+
default:
|
1681
|
+
{
|
1682
|
+
HRESULT hr;
|
1683
|
+
VARIANT variant;
|
1684
|
+
VariantInit(&variant);
|
1685
|
+
hr = VariantChangeTypeEx(&variant, pvar,
|
1686
|
+
cWIN32OLE_lcid, 0, VT_BSTR);
|
1687
|
+
if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) {
|
1688
|
+
obj = ole_wc2vstr(V_BSTR(&variant), FALSE);
|
1689
|
+
}
|
1690
|
+
VariantClear(&variant);
|
1691
|
+
break;
|
1692
|
+
}
|
1693
|
+
}
|
1694
|
+
return obj;
|
1695
|
+
}
|
1696
|
+
|
1697
|
+
LONG
|
1698
|
+
reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
|
1699
|
+
{
|
1700
|
+
return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey);
|
1701
|
+
}
|
1702
|
+
|
1703
|
+
LONG
|
1704
|
+
reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
|
1705
|
+
{
|
1706
|
+
return reg_open_key(hkey, StringValuePtr(key), phkey);
|
1707
|
+
}
|
1708
|
+
|
1709
|
+
VALUE
|
1710
|
+
reg_enum_key(HKEY hkey, DWORD i)
|
1711
|
+
{
|
1712
|
+
char buf[BUFSIZ + 1];
|
1713
|
+
DWORD size_buf = sizeof(buf);
|
1714
|
+
FILETIME ft;
|
1715
|
+
LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf,
|
1716
|
+
NULL, NULL, NULL, &ft);
|
1717
|
+
if(err == ERROR_SUCCESS) {
|
1718
|
+
buf[BUFSIZ] = '\0';
|
1719
|
+
return rb_str_new2(buf);
|
1720
|
+
}
|
1721
|
+
return Qnil;
|
1722
|
+
}
|
1723
|
+
|
1724
|
+
VALUE
|
1725
|
+
reg_get_val(HKEY hkey, const char *subkey)
|
1726
|
+
{
|
1727
|
+
char *pbuf;
|
1728
|
+
DWORD dwtype = 0;
|
1729
|
+
DWORD size = 0;
|
1730
|
+
VALUE val = Qnil;
|
1731
|
+
LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size);
|
1732
|
+
|
1733
|
+
if (err == ERROR_SUCCESS) {
|
1734
|
+
pbuf = ALLOC_N(char, size + 1);
|
1735
|
+
err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, (BYTE *)pbuf, &size);
|
1736
|
+
if (err == ERROR_SUCCESS) {
|
1737
|
+
pbuf[size] = '\0';
|
1738
|
+
if (dwtype == REG_EXPAND_SZ) {
|
1739
|
+
char* pbuf2 = (char *)pbuf;
|
1740
|
+
DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0);
|
1741
|
+
pbuf = ALLOC_N(char, len + 1);
|
1742
|
+
ExpandEnvironmentStrings(pbuf2, pbuf, len + 1);
|
1743
|
+
free(pbuf2);
|
1744
|
+
}
|
1745
|
+
val = rb_str_new2((char *)pbuf);
|
1746
|
+
}
|
1747
|
+
free(pbuf);
|
1748
|
+
}
|
1749
|
+
return val;
|
1750
|
+
}
|
1751
|
+
|
1752
|
+
VALUE
|
1753
|
+
reg_get_val2(HKEY hkey, const char *subkey)
|
1754
|
+
{
|
1755
|
+
HKEY hsubkey;
|
1756
|
+
LONG err;
|
1757
|
+
VALUE val = Qnil;
|
1758
|
+
err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey);
|
1759
|
+
if (err == ERROR_SUCCESS) {
|
1760
|
+
val = reg_get_val(hsubkey, NULL);
|
1761
|
+
RegCloseKey(hsubkey);
|
1762
|
+
}
|
1763
|
+
if (val == Qnil) {
|
1764
|
+
val = reg_get_val(hkey, subkey);
|
1765
|
+
}
|
1766
|
+
return val;
|
1767
|
+
}
|
1768
|
+
|
1769
|
+
static void
|
1770
|
+
ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self)
|
1771
|
+
{
|
1772
|
+
unsigned int count;
|
1773
|
+
unsigned int index;
|
1774
|
+
int iVar;
|
1775
|
+
ITypeInfo *pTypeInfo;
|
1776
|
+
TYPEATTR *pTypeAttr;
|
1777
|
+
VARDESC *pVarDesc;
|
1778
|
+
HRESULT hr;
|
1779
|
+
unsigned int len;
|
1780
|
+
BSTR bstr;
|
1781
|
+
char *pName = NULL;
|
1782
|
+
VALUE val;
|
1783
|
+
VALUE constant;
|
1784
|
+
ID id;
|
1785
|
+
constant = rb_hash_new();
|
1786
|
+
count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
|
1787
|
+
for (index = 0; index < count; index++) {
|
1788
|
+
hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo);
|
1789
|
+
if (FAILED(hr))
|
1790
|
+
continue;
|
1791
|
+
hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
|
1792
|
+
if(FAILED(hr)) {
|
1793
|
+
OLE_RELEASE(pTypeInfo);
|
1794
|
+
continue;
|
1795
|
+
}
|
1796
|
+
for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) {
|
1797
|
+
hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc);
|
1798
|
+
if(FAILED(hr))
|
1799
|
+
continue;
|
1800
|
+
if(pVarDesc->varkind == VAR_CONST &&
|
1801
|
+
!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
|
1802
|
+
VARFLAG_FRESTRICTED |
|
1803
|
+
VARFLAG_FNONBROWSABLE))) {
|
1804
|
+
hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
|
1805
|
+
1, &len);
|
1806
|
+
if(FAILED(hr) || len == 0 || !bstr)
|
1807
|
+
continue;
|
1808
|
+
pName = ole_wc2mb(bstr);
|
1809
|
+
val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
|
1810
|
+
*pName = toupper((int)*pName);
|
1811
|
+
id = rb_intern(pName);
|
1812
|
+
if (rb_is_const_id(id)) {
|
1813
|
+
if(!rb_const_defined_at(klass, id)) {
|
1814
|
+
rb_define_const(klass, pName, val);
|
1815
|
+
}
|
1816
|
+
}
|
1817
|
+
else {
|
1818
|
+
rb_hash_aset(constant, rb_str_new2(pName), val);
|
1819
|
+
}
|
1820
|
+
SysFreeString(bstr);
|
1821
|
+
if(pName) {
|
1822
|
+
free(pName);
|
1823
|
+
pName = NULL;
|
1824
|
+
}
|
1825
|
+
}
|
1826
|
+
pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
|
1827
|
+
}
|
1828
|
+
pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
|
1829
|
+
OLE_RELEASE(pTypeInfo);
|
1830
|
+
}
|
1831
|
+
rb_define_const(klass, "CONSTANTS", constant);
|
1832
|
+
}
|
1833
|
+
|
1834
|
+
static HRESULT
|
1835
|
+
clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid)
|
1836
|
+
{
|
1837
|
+
HKEY hlm;
|
1838
|
+
HKEY hpid;
|
1839
|
+
VALUE subkey;
|
1840
|
+
LONG err;
|
1841
|
+
char clsid[100];
|
1842
|
+
OLECHAR *pbuf;
|
1843
|
+
DWORD len;
|
1844
|
+
DWORD dwtype;
|
1845
|
+
HRESULT hr = S_OK;
|
1846
|
+
err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm);
|
1847
|
+
if (err != ERROR_SUCCESS)
|
1848
|
+
return HRESULT_FROM_WIN32(err);
|
1849
|
+
subkey = rb_str_new2("SOFTWARE\\Classes\\");
|
1850
|
+
rb_str_concat(subkey, com);
|
1851
|
+
rb_str_cat2(subkey, "\\CLSID");
|
1852
|
+
err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid);
|
1853
|
+
if (err != ERROR_SUCCESS)
|
1854
|
+
hr = HRESULT_FROM_WIN32(err);
|
1855
|
+
else {
|
1856
|
+
len = sizeof(clsid);
|
1857
|
+
err = RegQueryValueEx(hpid, "", NULL, &dwtype, (BYTE *)clsid, &len);
|
1858
|
+
if (err == ERROR_SUCCESS && dwtype == REG_SZ) {
|
1859
|
+
pbuf = ole_mb2wc(clsid, -1, cWIN32OLE_cp);
|
1860
|
+
hr = CLSIDFromString(pbuf, pclsid);
|
1861
|
+
SysFreeString(pbuf);
|
1862
|
+
}
|
1863
|
+
else {
|
1864
|
+
hr = HRESULT_FROM_WIN32(err);
|
1865
|
+
}
|
1866
|
+
RegCloseKey(hpid);
|
1867
|
+
}
|
1868
|
+
RegCloseKey(hlm);
|
1869
|
+
return hr;
|
1870
|
+
}
|
1871
|
+
|
1872
|
+
static VALUE
|
1873
|
+
ole_create_dcom(VALUE self, VALUE ole, VALUE host, VALUE others)
|
1874
|
+
{
|
1875
|
+
HRESULT hr;
|
1876
|
+
CLSID clsid;
|
1877
|
+
OLECHAR *pbuf;
|
1878
|
+
|
1879
|
+
COSERVERINFO serverinfo;
|
1880
|
+
MULTI_QI multi_qi;
|
1881
|
+
DWORD clsctx = CLSCTX_REMOTE_SERVER;
|
1882
|
+
|
1883
|
+
if (!gole32)
|
1884
|
+
gole32 = LoadLibrary("OLE32");
|
1885
|
+
if (!gole32)
|
1886
|
+
rb_raise(rb_eRuntimeError, "failed to load OLE32");
|
1887
|
+
if (!gCoCreateInstanceEx)
|
1888
|
+
gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*)
|
1889
|
+
GetProcAddress(gole32, "CoCreateInstanceEx");
|
1890
|
+
if (!gCoCreateInstanceEx)
|
1891
|
+
rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment");
|
1892
|
+
|
1893
|
+
pbuf = ole_vstr2wc(ole);
|
1894
|
+
hr = CLSIDFromProgID(pbuf, &clsid);
|
1895
|
+
if (FAILED(hr))
|
1896
|
+
hr = clsid_from_remote(host, ole, &clsid);
|
1897
|
+
if (FAILED(hr))
|
1898
|
+
hr = CLSIDFromString(pbuf, &clsid);
|
1899
|
+
SysFreeString(pbuf);
|
1900
|
+
if (FAILED(hr))
|
1901
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
1902
|
+
"unknown OLE server: `%s'",
|
1903
|
+
StringValuePtr(ole));
|
1904
|
+
memset(&serverinfo, 0, sizeof(COSERVERINFO));
|
1905
|
+
serverinfo.pwszName = ole_vstr2wc(host);
|
1906
|
+
memset(&multi_qi, 0, sizeof(MULTI_QI));
|
1907
|
+
multi_qi.pIID = &IID_IDispatch;
|
1908
|
+
hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi);
|
1909
|
+
SysFreeString(serverinfo.pwszName);
|
1910
|
+
if (FAILED(hr))
|
1911
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
1912
|
+
"failed to create DCOM server `%s' in `%s'",
|
1913
|
+
StringValuePtr(ole),
|
1914
|
+
StringValuePtr(host));
|
1915
|
+
|
1916
|
+
ole_set_member(self, (IDispatch*)multi_qi.pItf);
|
1917
|
+
return self;
|
1918
|
+
}
|
1919
|
+
|
1920
|
+
static VALUE
|
1921
|
+
ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
|
1922
|
+
{
|
1923
|
+
IBindCtx *pBindCtx;
|
1924
|
+
IMoniker *pMoniker;
|
1925
|
+
IDispatch *pDispatch;
|
1926
|
+
void *p;
|
1927
|
+
HRESULT hr;
|
1928
|
+
OLECHAR *pbuf;
|
1929
|
+
ULONG eaten = 0;
|
1930
|
+
|
1931
|
+
ole_initialize();
|
1932
|
+
|
1933
|
+
hr = CreateBindCtx(0, &pBindCtx);
|
1934
|
+
if(FAILED(hr)) {
|
1935
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
1936
|
+
"failed to create bind context");
|
1937
|
+
}
|
1938
|
+
|
1939
|
+
pbuf = ole_vstr2wc(moniker);
|
1940
|
+
hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker);
|
1941
|
+
SysFreeString(pbuf);
|
1942
|
+
if(FAILED(hr)) {
|
1943
|
+
OLE_RELEASE(pBindCtx);
|
1944
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
1945
|
+
"failed to parse display name of moniker `%s'",
|
1946
|
+
StringValuePtr(moniker));
|
1947
|
+
}
|
1948
|
+
hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL,
|
1949
|
+
&IID_IDispatch, &p);
|
1950
|
+
pDispatch = p;
|
1951
|
+
OLE_RELEASE(pMoniker);
|
1952
|
+
OLE_RELEASE(pBindCtx);
|
1953
|
+
|
1954
|
+
if(FAILED(hr)) {
|
1955
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
1956
|
+
"failed to bind moniker `%s'",
|
1957
|
+
StringValuePtr(moniker));
|
1958
|
+
}
|
1959
|
+
return create_win32ole_object(self, pDispatch, argc, argv);
|
1960
|
+
}
|
1961
|
+
|
1962
|
+
/*
|
1963
|
+
* call-seq:
|
1964
|
+
* WIN32OLE.connect( ole ) --> aWIN32OLE
|
1965
|
+
*
|
1966
|
+
* Returns running OLE Automation object or WIN32OLE object from moniker.
|
1967
|
+
* 1st argument should be OLE program id or class id or moniker.
|
1968
|
+
*
|
1969
|
+
* WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel.
|
1970
|
+
*/
|
1971
|
+
static VALUE
|
1972
|
+
fole_s_connect(int argc, VALUE *argv, VALUE self)
|
1973
|
+
{
|
1974
|
+
VALUE svr_name;
|
1975
|
+
VALUE others;
|
1976
|
+
HRESULT hr;
|
1977
|
+
CLSID clsid;
|
1978
|
+
OLECHAR *pBuf;
|
1979
|
+
IDispatch *pDispatch;
|
1980
|
+
void *p;
|
1981
|
+
IUnknown *pUnknown;
|
1982
|
+
|
1983
|
+
/* initialize to use OLE */
|
1984
|
+
ole_initialize();
|
1985
|
+
|
1986
|
+
rb_scan_args(argc, argv, "1*", &svr_name, &others);
|
1987
|
+
StringValue(svr_name);
|
1988
|
+
|
1989
|
+
/* get CLSID from OLE server name */
|
1990
|
+
pBuf = ole_vstr2wc(svr_name);
|
1991
|
+
hr = CLSIDFromProgID(pBuf, &clsid);
|
1992
|
+
if(FAILED(hr)) {
|
1993
|
+
hr = CLSIDFromString(pBuf, &clsid);
|
1994
|
+
}
|
1995
|
+
SysFreeString(pBuf);
|
1996
|
+
if(FAILED(hr)) {
|
1997
|
+
return ole_bind_obj(svr_name, argc, argv, self);
|
1998
|
+
}
|
1999
|
+
|
2000
|
+
hr = GetActiveObject(&clsid, 0, &pUnknown);
|
2001
|
+
if (FAILED(hr)) {
|
2002
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
2003
|
+
"OLE server `%s' not running", StringValuePtr(svr_name));
|
2004
|
+
}
|
2005
|
+
hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p);
|
2006
|
+
pDispatch = p;
|
2007
|
+
if(FAILED(hr)) {
|
2008
|
+
OLE_RELEASE(pUnknown);
|
2009
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
2010
|
+
"failed to create WIN32OLE server `%s'",
|
2011
|
+
StringValuePtr(svr_name));
|
2012
|
+
}
|
2013
|
+
|
2014
|
+
OLE_RELEASE(pUnknown);
|
2015
|
+
|
2016
|
+
return create_win32ole_object(self, pDispatch, argc, argv);
|
2017
|
+
}
|
2018
|
+
|
2019
|
+
/*
|
2020
|
+
* call-seq:
|
2021
|
+
* WIN32OLE.const_load( ole, mod = WIN32OLE)
|
2022
|
+
*
|
2023
|
+
* Defines the constants of OLE Automation server as mod's constants.
|
2024
|
+
* The first argument is WIN32OLE object or type library name.
|
2025
|
+
* If 2nd argument is omitted, the default is WIN32OLE.
|
2026
|
+
* The first letter of Ruby's constant variable name is upper case,
|
2027
|
+
* so constant variable name of WIN32OLE object is capitalized.
|
2028
|
+
* For example, the 'xlTop' constant of Excel is changed to 'XlTop'
|
2029
|
+
* in WIN32OLE.
|
2030
|
+
* If the first letter of constant variable is not [A-Z], then
|
2031
|
+
* the constant is defined as CONSTANTS hash element.
|
2032
|
+
*
|
2033
|
+
* module EXCEL_CONST
|
2034
|
+
* end
|
2035
|
+
* excel = WIN32OLE.new('Excel.Application')
|
2036
|
+
* WIN32OLE.const_load(excel, EXCEL_CONST)
|
2037
|
+
* puts EXCEL_CONST::XlTop # => -4160
|
2038
|
+
* puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541
|
2039
|
+
*
|
2040
|
+
* WIN32OLE.const_load(excel)
|
2041
|
+
* puts WIN32OLE::XlTop # => -4160
|
2042
|
+
*
|
2043
|
+
* module MSO
|
2044
|
+
* end
|
2045
|
+
* WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO)
|
2046
|
+
* puts MSO::MsoLineSingle # => 1
|
2047
|
+
*/
|
2048
|
+
static VALUE
|
2049
|
+
fole_s_const_load(int argc, VALUE *argv, VALUE self)
|
2050
|
+
{
|
2051
|
+
VALUE ole;
|
2052
|
+
VALUE klass;
|
2053
|
+
struct oledata *pole = NULL;
|
2054
|
+
ITypeInfo *pTypeInfo;
|
2055
|
+
ITypeLib *pTypeLib;
|
2056
|
+
unsigned int index;
|
2057
|
+
HRESULT hr;
|
2058
|
+
OLECHAR *pBuf;
|
2059
|
+
VALUE file;
|
2060
|
+
LCID lcid = cWIN32OLE_lcid;
|
2061
|
+
|
2062
|
+
rb_scan_args(argc, argv, "11", &ole, &klass);
|
2063
|
+
if (!RB_TYPE_P(klass, T_CLASS) &&
|
2064
|
+
!RB_TYPE_P(klass, T_MODULE) &&
|
2065
|
+
!RB_TYPE_P(klass, T_NIL)) {
|
2066
|
+
rb_raise(rb_eTypeError, "2nd parameter must be Class or Module");
|
2067
|
+
}
|
2068
|
+
if (rb_obj_is_kind_of(ole, cWIN32OLE)) {
|
2069
|
+
pole = oledata_get_struct(ole);
|
2070
|
+
hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
|
2071
|
+
0, lcid, &pTypeInfo);
|
2072
|
+
if(FAILED(hr)) {
|
2073
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
|
2074
|
+
}
|
2075
|
+
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
|
2076
|
+
if(FAILED(hr)) {
|
2077
|
+
OLE_RELEASE(pTypeInfo);
|
2078
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetContainingTypeLib");
|
2079
|
+
}
|
2080
|
+
OLE_RELEASE(pTypeInfo);
|
2081
|
+
if(!RB_TYPE_P(klass, T_NIL)) {
|
2082
|
+
ole_const_load(pTypeLib, klass, self);
|
2083
|
+
}
|
2084
|
+
else {
|
2085
|
+
ole_const_load(pTypeLib, cWIN32OLE, self);
|
2086
|
+
}
|
2087
|
+
OLE_RELEASE(pTypeLib);
|
2088
|
+
}
|
2089
|
+
else if(RB_TYPE_P(ole, T_STRING)) {
|
2090
|
+
file = typelib_file(ole);
|
2091
|
+
if (file == Qnil) {
|
2092
|
+
file = ole;
|
2093
|
+
}
|
2094
|
+
pBuf = ole_vstr2wc(file);
|
2095
|
+
hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib);
|
2096
|
+
SysFreeString(pBuf);
|
2097
|
+
if (FAILED(hr))
|
2098
|
+
ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
|
2099
|
+
if(!RB_TYPE_P(klass, T_NIL)) {
|
2100
|
+
ole_const_load(pTypeLib, klass, self);
|
2101
|
+
}
|
2102
|
+
else {
|
2103
|
+
ole_const_load(pTypeLib, cWIN32OLE, self);
|
2104
|
+
}
|
2105
|
+
OLE_RELEASE(pTypeLib);
|
2106
|
+
}
|
2107
|
+
else {
|
2108
|
+
rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance");
|
2109
|
+
}
|
2110
|
+
return Qnil;
|
2111
|
+
}
|
2112
|
+
|
2113
|
+
static ULONG
|
2114
|
+
reference_count(struct oledata * pole)
|
2115
|
+
{
|
2116
|
+
ULONG n = 0;
|
2117
|
+
if(pole->pDispatch) {
|
2118
|
+
OLE_ADDREF(pole->pDispatch);
|
2119
|
+
n = OLE_RELEASE(pole->pDispatch);
|
2120
|
+
}
|
2121
|
+
return n;
|
2122
|
+
}
|
2123
|
+
|
2124
|
+
/*
|
2125
|
+
* call-seq:
|
2126
|
+
* WIN32OLE.ole_reference_count(aWIN32OLE) --> number
|
2127
|
+
*
|
2128
|
+
* Returns reference counter of Dispatch interface of WIN32OLE object.
|
2129
|
+
* You should not use this method because this method
|
2130
|
+
* exists only for debugging WIN32OLE.
|
2131
|
+
*/
|
2132
|
+
static VALUE
|
2133
|
+
fole_s_reference_count(VALUE self, VALUE obj)
|
2134
|
+
{
|
2135
|
+
struct oledata * pole = NULL;
|
2136
|
+
pole = oledata_get_struct(obj);
|
2137
|
+
return RB_INT2NUM(reference_count(pole));
|
2138
|
+
}
|
2139
|
+
|
2140
|
+
/*
|
2141
|
+
* call-seq:
|
2142
|
+
* WIN32OLE.ole_free(aWIN32OLE) --> number
|
2143
|
+
*
|
2144
|
+
* Invokes Release method of Dispatch interface of WIN32OLE object.
|
2145
|
+
* You should not use this method because this method
|
2146
|
+
* exists only for debugging WIN32OLE.
|
2147
|
+
* The return value is reference counter of OLE object.
|
2148
|
+
*/
|
2149
|
+
static VALUE
|
2150
|
+
fole_s_free(VALUE self, VALUE obj)
|
2151
|
+
{
|
2152
|
+
ULONG n = 0;
|
2153
|
+
struct oledata * pole = NULL;
|
2154
|
+
pole = oledata_get_struct(obj);
|
2155
|
+
if(pole->pDispatch) {
|
2156
|
+
if (reference_count(pole) > 0) {
|
2157
|
+
n = OLE_RELEASE(pole->pDispatch);
|
2158
|
+
}
|
2159
|
+
}
|
2160
|
+
return RB_INT2NUM(n);
|
2161
|
+
}
|
2162
|
+
|
2163
|
+
static HWND
|
2164
|
+
ole_show_help(VALUE helpfile, VALUE helpcontext)
|
2165
|
+
{
|
2166
|
+
FNHTMLHELP *pfnHtmlHelp;
|
2167
|
+
HWND hwnd = 0;
|
2168
|
+
|
2169
|
+
if(!ghhctrl)
|
2170
|
+
ghhctrl = LoadLibrary("HHCTRL.OCX");
|
2171
|
+
if (!ghhctrl)
|
2172
|
+
return hwnd;
|
2173
|
+
pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA");
|
2174
|
+
if (!pfnHtmlHelp)
|
2175
|
+
return hwnd;
|
2176
|
+
hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
|
2177
|
+
0x0f, RB_NUM2INT(helpcontext));
|
2178
|
+
if (hwnd == 0)
|
2179
|
+
hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
|
2180
|
+
0, RB_NUM2INT(helpcontext));
|
2181
|
+
return hwnd;
|
2182
|
+
}
|
2183
|
+
|
2184
|
+
/*
|
2185
|
+
* call-seq:
|
2186
|
+
* WIN32OLE.ole_show_help(obj [,helpcontext])
|
2187
|
+
*
|
2188
|
+
* Displays helpfile. The 1st argument specifies WIN32OLE_TYPE
|
2189
|
+
* object or WIN32OLE_METHOD object or helpfile.
|
2190
|
+
*
|
2191
|
+
* excel = WIN32OLE.new('Excel.Application')
|
2192
|
+
* typeobj = excel.ole_type
|
2193
|
+
* WIN32OLE.ole_show_help(typeobj)
|
2194
|
+
*/
|
2195
|
+
static VALUE
|
2196
|
+
fole_s_show_help(int argc, VALUE *argv, VALUE self)
|
2197
|
+
{
|
2198
|
+
VALUE target;
|
2199
|
+
VALUE helpcontext;
|
2200
|
+
VALUE helpfile;
|
2201
|
+
VALUE name;
|
2202
|
+
HWND hwnd;
|
2203
|
+
rb_scan_args(argc, argv, "11", &target, &helpcontext);
|
2204
|
+
if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) ||
|
2205
|
+
rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) {
|
2206
|
+
helpfile = rb_funcall(target, rb_intern("helpfile"), 0);
|
2207
|
+
if(strlen(StringValuePtr(helpfile)) == 0) {
|
2208
|
+
name = rb_ivar_get(target, rb_intern("name"));
|
2209
|
+
rb_raise(rb_eRuntimeError, "no helpfile of `%s'",
|
2210
|
+
StringValuePtr(name));
|
2211
|
+
}
|
2212
|
+
helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0);
|
2213
|
+
} else {
|
2214
|
+
helpfile = target;
|
2215
|
+
}
|
2216
|
+
if (!RB_TYPE_P(helpfile, T_STRING)) {
|
2217
|
+
rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)");
|
2218
|
+
}
|
2219
|
+
hwnd = ole_show_help(helpfile, helpcontext);
|
2220
|
+
if(hwnd == 0) {
|
2221
|
+
rb_raise(rb_eRuntimeError, "failed to open help file `%s'",
|
2222
|
+
StringValuePtr(helpfile));
|
2223
|
+
}
|
2224
|
+
return Qnil;
|
2225
|
+
}
|
2226
|
+
|
2227
|
+
/*
|
2228
|
+
* call-seq:
|
2229
|
+
* WIN32OLE.codepage
|
2230
|
+
*
|
2231
|
+
* Returns current codepage.
|
2232
|
+
* WIN32OLE.codepage # => WIN32OLE::CP_ACP
|
2233
|
+
*/
|
2234
|
+
static VALUE
|
2235
|
+
fole_s_get_code_page(VALUE self)
|
2236
|
+
{
|
2237
|
+
return RB_INT2FIX(cWIN32OLE_cp);
|
2238
|
+
}
|
2239
|
+
|
2240
|
+
static BOOL CALLBACK
|
2241
|
+
installed_code_page_proc(LPTSTR str) {
|
2242
|
+
if (strtoul(str, NULL, 10) == g_cp_to_check) {
|
2243
|
+
g_cp_installed = TRUE;
|
2244
|
+
return FALSE;
|
2245
|
+
}
|
2246
|
+
return TRUE;
|
2247
|
+
}
|
2248
|
+
|
2249
|
+
static BOOL
|
2250
|
+
code_page_installed(UINT cp)
|
2251
|
+
{
|
2252
|
+
g_cp_installed = FALSE;
|
2253
|
+
g_cp_to_check = cp;
|
2254
|
+
EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED);
|
2255
|
+
return g_cp_installed;
|
2256
|
+
}
|
2257
|
+
|
2258
|
+
/*
|
2259
|
+
* call-seq:
|
2260
|
+
* WIN32OLE.codepage = CP
|
2261
|
+
*
|
2262
|
+
* Sets current codepage.
|
2263
|
+
* The WIN32OLE.codepage is initialized according to
|
2264
|
+
* Encoding.default_internal.
|
2265
|
+
* If Encoding.default_internal is nil then WIN32OLE.codepage
|
2266
|
+
* is initialized according to Encoding.default_external.
|
2267
|
+
*
|
2268
|
+
* WIN32OLE.codepage = WIN32OLE::CP_UTF8
|
2269
|
+
* WIN32OLE.codepage = 65001
|
2270
|
+
*/
|
2271
|
+
static VALUE
|
2272
|
+
fole_s_set_code_page(VALUE self, VALUE vcp)
|
2273
|
+
{
|
2274
|
+
UINT cp = RB_FIX2INT(vcp);
|
2275
|
+
set_ole_codepage(cp);
|
2276
|
+
/*
|
2277
|
+
* Should this method return old codepage?
|
2278
|
+
*/
|
2279
|
+
return Qnil;
|
2280
|
+
}
|
2281
|
+
|
2282
|
+
/*
|
2283
|
+
* call-seq:
|
2284
|
+
* WIN32OLE.locale -> locale id.
|
2285
|
+
*
|
2286
|
+
* Returns current locale id (lcid). The default locale is
|
2287
|
+
* WIN32OLE::LOCALE_SYSTEM_DEFAULT.
|
2288
|
+
*
|
2289
|
+
* lcid = WIN32OLE.locale
|
2290
|
+
*/
|
2291
|
+
static VALUE
|
2292
|
+
fole_s_get_locale(VALUE self)
|
2293
|
+
{
|
2294
|
+
return RB_INT2FIX(cWIN32OLE_lcid);
|
2295
|
+
}
|
2296
|
+
|
2297
|
+
static BOOL
|
2298
|
+
CALLBACK installed_lcid_proc(LPTSTR str)
|
2299
|
+
{
|
2300
|
+
if (strcmp(str, g_lcid_to_check) == 0) {
|
2301
|
+
g_lcid_installed = TRUE;
|
2302
|
+
return FALSE;
|
2303
|
+
}
|
2304
|
+
return TRUE;
|
2305
|
+
}
|
2306
|
+
|
2307
|
+
static BOOL
|
2308
|
+
lcid_installed(LCID lcid)
|
2309
|
+
{
|
2310
|
+
g_lcid_installed = FALSE;
|
2311
|
+
snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", (unsigned long)lcid);
|
2312
|
+
EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED);
|
2313
|
+
return g_lcid_installed;
|
2314
|
+
}
|
2315
|
+
|
2316
|
+
/*
|
2317
|
+
* call-seq:
|
2318
|
+
* WIN32OLE.locale = lcid
|
2319
|
+
*
|
2320
|
+
* Sets current locale id (lcid).
|
2321
|
+
*
|
2322
|
+
* WIN32OLE.locale = 1033 # set locale English(U.S)
|
2323
|
+
* obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
|
2324
|
+
*
|
2325
|
+
*/
|
2326
|
+
static VALUE
|
2327
|
+
fole_s_set_locale(VALUE self, VALUE vlcid)
|
2328
|
+
{
|
2329
|
+
LCID lcid = RB_FIX2INT(vlcid);
|
2330
|
+
if (lcid_installed(lcid)) {
|
2331
|
+
cWIN32OLE_lcid = lcid;
|
2332
|
+
} else {
|
2333
|
+
switch (lcid) {
|
2334
|
+
case LOCALE_SYSTEM_DEFAULT:
|
2335
|
+
case LOCALE_USER_DEFAULT:
|
2336
|
+
cWIN32OLE_lcid = lcid;
|
2337
|
+
break;
|
2338
|
+
default:
|
2339
|
+
rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid);
|
2340
|
+
}
|
2341
|
+
}
|
2342
|
+
return Qnil;
|
2343
|
+
}
|
2344
|
+
|
2345
|
+
/*
|
2346
|
+
* call-seq:
|
2347
|
+
* WIN32OLE.create_guid
|
2348
|
+
*
|
2349
|
+
* Creates GUID.
|
2350
|
+
* WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
|
2351
|
+
*/
|
2352
|
+
static VALUE
|
2353
|
+
fole_s_create_guid(VALUE self)
|
2354
|
+
{
|
2355
|
+
GUID guid;
|
2356
|
+
HRESULT hr;
|
2357
|
+
OLECHAR bstr[80];
|
2358
|
+
int len = 0;
|
2359
|
+
hr = CoCreateGuid(&guid);
|
2360
|
+
if (FAILED(hr)) {
|
2361
|
+
ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID");
|
2362
|
+
}
|
2363
|
+
len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
|
2364
|
+
if (len == 0) {
|
2365
|
+
rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)");
|
2366
|
+
}
|
2367
|
+
return ole_wc2vstr(bstr, FALSE);
|
2368
|
+
}
|
2369
|
+
|
2370
|
+
/*
|
2371
|
+
* WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize
|
2372
|
+
* are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634).
|
2373
|
+
* You must not use these method.
|
2374
|
+
*/
|
2375
|
+
|
2376
|
+
/* :nodoc: */
|
2377
|
+
static VALUE
|
2378
|
+
fole_s_ole_initialize(VALUE self)
|
2379
|
+
{
|
2380
|
+
ole_initialize();
|
2381
|
+
return Qnil;
|
2382
|
+
}
|
2383
|
+
|
2384
|
+
/* :nodoc: */
|
2385
|
+
static VALUE
|
2386
|
+
fole_s_ole_uninitialize(VALUE self)
|
2387
|
+
{
|
2388
|
+
ole_uninitialize();
|
2389
|
+
return Qnil;
|
2390
|
+
}
|
2391
|
+
|
2392
|
+
/*
|
2393
|
+
* Document-class: WIN32OLE
|
2394
|
+
*
|
2395
|
+
* <code>WIN32OLE</code> objects represent OLE Automation object in Ruby.
|
2396
|
+
*
|
2397
|
+
* By using WIN32OLE, you can access OLE server like VBScript.
|
2398
|
+
*
|
2399
|
+
* Here is sample script.
|
2400
|
+
*
|
2401
|
+
* require 'win32ole'
|
2402
|
+
*
|
2403
|
+
* excel = WIN32OLE.new('Excel.Application')
|
2404
|
+
* excel.visible = true
|
2405
|
+
* workbook = excel.Workbooks.Add();
|
2406
|
+
* worksheet = workbook.Worksheets(1);
|
2407
|
+
* worksheet.Range("A1:D1").value = ["North","South","East","West"];
|
2408
|
+
* worksheet.Range("A2:B2").value = [5.2, 10];
|
2409
|
+
* worksheet.Range("C2").value = 8;
|
2410
|
+
* worksheet.Range("D2").value = 20;
|
2411
|
+
*
|
2412
|
+
* range = worksheet.Range("A1:D2");
|
2413
|
+
* range.select
|
2414
|
+
* chart = workbook.Charts.Add;
|
2415
|
+
*
|
2416
|
+
* workbook.saved = true;
|
2417
|
+
*
|
2418
|
+
* excel.ActiveWorkbook.Close(0);
|
2419
|
+
* excel.Quit();
|
2420
|
+
*
|
2421
|
+
* Unfortunately, Win32OLE doesn't support the argument passed by
|
2422
|
+
* reference directly.
|
2423
|
+
* Instead, Win32OLE provides WIN32OLE::ARGV or WIN32OLE_VARIANT object.
|
2424
|
+
* If you want to get the result value of argument passed by reference,
|
2425
|
+
* you can use WIN32OLE::ARGV or WIN32OLE_VARIANT.
|
2426
|
+
*
|
2427
|
+
* oleobj.method(arg1, arg2, refargv3)
|
2428
|
+
* puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
|
2429
|
+
*
|
2430
|
+
* or
|
2431
|
+
*
|
2432
|
+
* refargv3 = WIN32OLE_VARIANT.new(XXX,
|
2433
|
+
* WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX)
|
2434
|
+
* oleobj.method(arg1, arg2, refargv3)
|
2435
|
+
* p refargv3.value # the value of refargv3 after called oleobj.method.
|
2436
|
+
*
|
2437
|
+
*/
|
2438
|
+
|
2439
|
+
/*
|
2440
|
+
* call-seq:
|
2441
|
+
* WIN32OLE.new(server, [host]) -> WIN32OLE object
|
2442
|
+
* WIN32OLE.new(server, license: 'key') -> WIN32OLE object
|
2443
|
+
*
|
2444
|
+
* Returns a new WIN32OLE object(OLE Automation object).
|
2445
|
+
* The first argument server specifies OLE Automation server.
|
2446
|
+
* The first argument should be CLSID or PROGID.
|
2447
|
+
* If second argument host specified, then returns OLE Automation
|
2448
|
+
* object on host.
|
2449
|
+
* If :license keyword argument is provided,
|
2450
|
+
* IClassFactory2::CreateInstanceLic is used to create instance of
|
2451
|
+
* licensed server.
|
2452
|
+
*
|
2453
|
+
* WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object.
|
2454
|
+
* WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
|
2455
|
+
*/
|
2456
|
+
static VALUE
|
2457
|
+
fole_initialize(int argc, VALUE *argv, VALUE self)
|
2458
|
+
{
|
2459
|
+
VALUE svr_name;
|
2460
|
+
VALUE host;
|
2461
|
+
VALUE others;
|
2462
|
+
VALUE opts;
|
2463
|
+
HRESULT hr;
|
2464
|
+
CLSID clsid;
|
2465
|
+
OLECHAR *pBuf;
|
2466
|
+
OLECHAR *key_buf;
|
2467
|
+
IDispatch *pDispatch;
|
2468
|
+
IClassFactory2 * pIClassFactory2;
|
2469
|
+
void *p;
|
2470
|
+
static ID keyword_ids[1];
|
2471
|
+
VALUE kwargs[1];
|
2472
|
+
|
2473
|
+
rb_call_super(0, 0);
|
2474
|
+
rb_scan_args(argc, argv, "11*:", &svr_name, &host, &others, &opts);
|
2475
|
+
|
2476
|
+
StringValue(svr_name);
|
2477
|
+
if (!NIL_P(host)) {
|
2478
|
+
StringValue(host);
|
2479
|
+
return ole_create_dcom(self, svr_name, host, others);
|
2480
|
+
}
|
2481
|
+
|
2482
|
+
/* get CLSID from OLE server name */
|
2483
|
+
pBuf = ole_vstr2wc(svr_name);
|
2484
|
+
hr = CLSIDFromProgID(pBuf, &clsid);
|
2485
|
+
if(FAILED(hr)) {
|
2486
|
+
hr = CLSIDFromString(pBuf, &clsid);
|
2487
|
+
}
|
2488
|
+
SysFreeString(pBuf);
|
2489
|
+
if(FAILED(hr)) {
|
2490
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
2491
|
+
"unknown OLE server: `%s'",
|
2492
|
+
StringValuePtr(svr_name));
|
2493
|
+
}
|
2494
|
+
|
2495
|
+
if (!keyword_ids[0]) {
|
2496
|
+
keyword_ids[0] = rb_intern_const("license");
|
2497
|
+
}
|
2498
|
+
rb_get_kwargs(opts, keyword_ids, 0, 1, kwargs);
|
2499
|
+
|
2500
|
+
if (kwargs[0] == Qundef) {
|
2501
|
+
/* get IDispatch interface */
|
2502
|
+
hr = CoCreateInstance(
|
2503
|
+
&clsid,
|
2504
|
+
NULL,
|
2505
|
+
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
|
2506
|
+
&IID_IDispatch,
|
2507
|
+
&p
|
2508
|
+
);
|
2509
|
+
} else {
|
2510
|
+
hr = CoGetClassObject(
|
2511
|
+
&clsid,
|
2512
|
+
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
|
2513
|
+
NULL,
|
2514
|
+
&IID_IClassFactory2,
|
2515
|
+
(LPVOID)&pIClassFactory2
|
2516
|
+
);
|
2517
|
+
if (hr == S_OK) {
|
2518
|
+
key_buf = ole_vstr2wc(kwargs[0]);
|
2519
|
+
hr = pIClassFactory2->lpVtbl->CreateInstanceLic(pIClassFactory2, NULL, NULL, &IID_IDispatch, key_buf, &p);
|
2520
|
+
SysFreeString(key_buf);
|
2521
|
+
OLE_RELEASE(pIClassFactory2);
|
2522
|
+
}
|
2523
|
+
}
|
2524
|
+
pDispatch = p;
|
2525
|
+
if(FAILED(hr)) {
|
2526
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
2527
|
+
"failed to create WIN32OLE object from `%s'",
|
2528
|
+
StringValuePtr(svr_name));
|
2529
|
+
}
|
2530
|
+
|
2531
|
+
ole_set_member(self, pDispatch);
|
2532
|
+
return self;
|
2533
|
+
}
|
2534
|
+
|
2535
|
+
static int
|
2536
|
+
hash2named_arg(VALUE key, VALUE val, VALUE pop)
|
2537
|
+
{
|
2538
|
+
struct oleparam* pOp = (struct oleparam *)pop;
|
2539
|
+
unsigned int index, i;
|
2540
|
+
index = pOp->dp.cNamedArgs;
|
2541
|
+
/*---------------------------------------------
|
2542
|
+
the data-type of key must be String or Symbol
|
2543
|
+
-----------------------------------------------*/
|
2544
|
+
if(!RB_TYPE_P(key, T_STRING) && !RB_TYPE_P(key, T_SYMBOL)) {
|
2545
|
+
/* clear name of dispatch parameters */
|
2546
|
+
for(i = 1; i < index + 1; i++) {
|
2547
|
+
SysFreeString(pOp->pNamedArgs[i]);
|
2548
|
+
}
|
2549
|
+
/* clear dispatch parameters */
|
2550
|
+
for(i = 0; i < index; i++ ) {
|
2551
|
+
VariantClear(&(pOp->dp.rgvarg[i]));
|
2552
|
+
}
|
2553
|
+
/* raise an exception */
|
2554
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
|
2555
|
+
}
|
2556
|
+
if (RB_TYPE_P(key, T_SYMBOL)) {
|
2557
|
+
key = rb_sym2str(key);
|
2558
|
+
}
|
2559
|
+
|
2560
|
+
/* pNamedArgs[0] is <method name>, so "index + 1" */
|
2561
|
+
pOp->pNamedArgs[index + 1] = ole_vstr2wc(key);
|
2562
|
+
|
2563
|
+
VariantInit(&(pOp->dp.rgvarg[index]));
|
2564
|
+
ole_val2variant(val, &(pOp->dp.rgvarg[index]));
|
2565
|
+
|
2566
|
+
pOp->dp.cNamedArgs += 1;
|
2567
|
+
return ST_CONTINUE;
|
2568
|
+
}
|
2569
|
+
|
2570
|
+
static VALUE
|
2571
|
+
set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
|
2572
|
+
{
|
2573
|
+
VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV"));
|
2574
|
+
|
2575
|
+
Check_Type(argv, T_ARRAY);
|
2576
|
+
rb_ary_clear(argv);
|
2577
|
+
while (end-- > beg) {
|
2578
|
+
rb_ary_push(argv, ole_variant2val(&realargs[end]));
|
2579
|
+
if (V_VT(&realargs[end]) != VT_RECORD) {
|
2580
|
+
VariantClear(&realargs[end]);
|
2581
|
+
}
|
2582
|
+
}
|
2583
|
+
return argv;
|
2584
|
+
}
|
2585
|
+
|
2586
|
+
static VALUE
|
2587
|
+
ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
|
2588
|
+
{
|
2589
|
+
LCID lcid = cWIN32OLE_lcid;
|
2590
|
+
struct oledata *pole = NULL;
|
2591
|
+
HRESULT hr;
|
2592
|
+
VALUE cmd;
|
2593
|
+
VALUE paramS;
|
2594
|
+
VALUE param;
|
2595
|
+
VALUE obj;
|
2596
|
+
VALUE v;
|
2597
|
+
|
2598
|
+
BSTR wcmdname;
|
2599
|
+
|
2600
|
+
DISPID DispID;
|
2601
|
+
DISPID* pDispID;
|
2602
|
+
EXCEPINFO excepinfo;
|
2603
|
+
VARIANT result;
|
2604
|
+
VARIANTARG* realargs = NULL;
|
2605
|
+
unsigned int argErr = 0;
|
2606
|
+
unsigned int i;
|
2607
|
+
unsigned int cNamedArgs;
|
2608
|
+
int n;
|
2609
|
+
struct oleparam op;
|
2610
|
+
memset(&excepinfo, 0, sizeof(EXCEPINFO));
|
2611
|
+
|
2612
|
+
VariantInit(&result);
|
2613
|
+
|
2614
|
+
op.dp.rgvarg = NULL;
|
2615
|
+
op.dp.rgdispidNamedArgs = NULL;
|
2616
|
+
op.dp.cNamedArgs = 0;
|
2617
|
+
op.dp.cArgs = 0;
|
2618
|
+
|
2619
|
+
rb_scan_args(argc, argv, "1*", &cmd, ¶mS);
|
2620
|
+
if(!RB_TYPE_P(cmd, T_STRING) && !RB_TYPE_P(cmd, T_SYMBOL) && !is_bracket) {
|
2621
|
+
rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
|
2622
|
+
}
|
2623
|
+
if (RB_TYPE_P(cmd, T_SYMBOL)) {
|
2624
|
+
cmd = rb_sym2str(cmd);
|
2625
|
+
}
|
2626
|
+
pole = oledata_get_struct(self);
|
2627
|
+
if(!pole->pDispatch) {
|
2628
|
+
rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
|
2629
|
+
}
|
2630
|
+
if (is_bracket) {
|
2631
|
+
DispID = DISPID_VALUE;
|
2632
|
+
argc += 1;
|
2633
|
+
rb_ary_unshift(paramS, cmd);
|
2634
|
+
} else {
|
2635
|
+
wcmdname = ole_vstr2wc(cmd);
|
2636
|
+
hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
|
2637
|
+
&wcmdname, 1, lcid, &DispID);
|
2638
|
+
SysFreeString(wcmdname);
|
2639
|
+
if(FAILED(hr)) {
|
2640
|
+
return rb_eNoMethodError;
|
2641
|
+
}
|
2642
|
+
}
|
2643
|
+
|
2644
|
+
/* pick up last argument of method */
|
2645
|
+
param = rb_ary_entry(paramS, argc-2);
|
2646
|
+
|
2647
|
+
op.dp.cNamedArgs = 0;
|
2648
|
+
|
2649
|
+
/* if last arg is hash object */
|
2650
|
+
if(RB_TYPE_P(param, T_HASH)) {
|
2651
|
+
/*------------------------------------------
|
2652
|
+
hash object ==> named dispatch parameters
|
2653
|
+
--------------------------------------------*/
|
2654
|
+
cNamedArgs = rb_long2int(RHASH_SIZE(param));
|
2655
|
+
op.dp.cArgs = cNamedArgs + argc - 2;
|
2656
|
+
op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
|
2657
|
+
op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
|
2658
|
+
|
2659
|
+
rb_hash_foreach(param, hash2named_arg, (VALUE)&op);
|
2660
|
+
|
2661
|
+
pDispID = ALLOCA_N(DISPID, cNamedArgs + 1);
|
2662
|
+
op.pNamedArgs[0] = ole_vstr2wc(cmd);
|
2663
|
+
hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch,
|
2664
|
+
&IID_NULL,
|
2665
|
+
op.pNamedArgs,
|
2666
|
+
op.dp.cNamedArgs + 1,
|
2667
|
+
lcid, pDispID);
|
2668
|
+
for(i = 0; i < op.dp.cNamedArgs + 1; i++) {
|
2669
|
+
SysFreeString(op.pNamedArgs[i]);
|
2670
|
+
op.pNamedArgs[i] = NULL;
|
2671
|
+
}
|
2672
|
+
if(FAILED(hr)) {
|
2673
|
+
/* clear dispatch parameters */
|
2674
|
+
for(i = 0; i < op.dp.cArgs; i++ ) {
|
2675
|
+
VariantClear(&op.dp.rgvarg[i]);
|
2676
|
+
}
|
2677
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
2678
|
+
"failed to get named argument info: `%s'",
|
2679
|
+
StringValuePtr(cmd));
|
2680
|
+
}
|
2681
|
+
op.dp.rgdispidNamedArgs = &(pDispID[1]);
|
2682
|
+
}
|
2683
|
+
else {
|
2684
|
+
cNamedArgs = 0;
|
2685
|
+
op.dp.cArgs = argc - 1;
|
2686
|
+
op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
|
2687
|
+
if (op.dp.cArgs > 0) {
|
2688
|
+
op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
|
2689
|
+
}
|
2690
|
+
}
|
2691
|
+
/*--------------------------------------
|
2692
|
+
non hash args ==> dispatch parameters
|
2693
|
+
----------------------------------------*/
|
2694
|
+
if(op.dp.cArgs > cNamedArgs) {
|
2695
|
+
realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1);
|
2696
|
+
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
|
2697
|
+
n = op.dp.cArgs - i + cNamedArgs - 1;
|
2698
|
+
VariantInit(&realargs[n]);
|
2699
|
+
VariantInit(&op.dp.rgvarg[n]);
|
2700
|
+
param = rb_ary_entry(paramS, i-cNamedArgs);
|
2701
|
+
if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
|
2702
|
+
ole_variant2variant(param, &op.dp.rgvarg[n]);
|
2703
|
+
} else if (rb_obj_is_kind_of(param, cWIN32OLE_RECORD)) {
|
2704
|
+
ole_val2variant(param, &realargs[n]);
|
2705
|
+
op.dp.rgvarg[n] = realargs[n];
|
2706
|
+
V_VT(&op.dp.rgvarg[n]) = VT_RECORD | VT_BYREF;
|
2707
|
+
} else {
|
2708
|
+
ole_val2variant(param, &realargs[n]);
|
2709
|
+
V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF;
|
2710
|
+
V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n];
|
2711
|
+
}
|
2712
|
+
}
|
2713
|
+
}
|
2714
|
+
/* apparent you need to call propput, you need this */
|
2715
|
+
if (wFlags & DISPATCH_PROPERTYPUT) {
|
2716
|
+
if (op.dp.cArgs == 0)
|
2717
|
+
ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error");
|
2718
|
+
|
2719
|
+
op.dp.cNamedArgs = 1;
|
2720
|
+
op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
|
2721
|
+
op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
|
2722
|
+
}
|
2723
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
|
2724
|
+
&IID_NULL, lcid, wFlags, &op.dp,
|
2725
|
+
&result, &excepinfo, &argErr);
|
2726
|
+
|
2727
|
+
if (FAILED(hr)) {
|
2728
|
+
/* retry to call args by value */
|
2729
|
+
if(op.dp.cArgs >= cNamedArgs) {
|
2730
|
+
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
|
2731
|
+
n = op.dp.cArgs - i + cNamedArgs - 1;
|
2732
|
+
param = rb_ary_entry(paramS, i-cNamedArgs);
|
2733
|
+
ole_val2variant(param, &op.dp.rgvarg[n]);
|
2734
|
+
}
|
2735
|
+
if (hr == DISP_E_EXCEPTION) {
|
2736
|
+
ole_freeexceptinfo(&excepinfo);
|
2737
|
+
}
|
2738
|
+
memset(&excepinfo, 0, sizeof(EXCEPINFO));
|
2739
|
+
VariantInit(&result);
|
2740
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
|
2741
|
+
&IID_NULL, lcid, wFlags,
|
2742
|
+
&op.dp, &result,
|
2743
|
+
&excepinfo, &argErr);
|
2744
|
+
|
2745
|
+
/* mega kludge. if a method in WORD is called and we ask
|
2746
|
+
* for a result when one is not returned then
|
2747
|
+
* hResult == DISP_E_EXCEPTION. this only happens on
|
2748
|
+
* functions whose DISPID > 0x8000 */
|
2749
|
+
if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) {
|
2750
|
+
if (hr == DISP_E_EXCEPTION) {
|
2751
|
+
ole_freeexceptinfo(&excepinfo);
|
2752
|
+
}
|
2753
|
+
memset(&excepinfo, 0, sizeof(EXCEPINFO));
|
2754
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
|
2755
|
+
&IID_NULL, lcid, wFlags,
|
2756
|
+
&op.dp, NULL,
|
2757
|
+
&excepinfo, &argErr);
|
2758
|
+
|
2759
|
+
}
|
2760
|
+
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
|
2761
|
+
n = op.dp.cArgs - i + cNamedArgs - 1;
|
2762
|
+
if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
|
2763
|
+
VariantClear(&op.dp.rgvarg[n]);
|
2764
|
+
}
|
2765
|
+
}
|
2766
|
+
}
|
2767
|
+
|
2768
|
+
if (FAILED(hr)) {
|
2769
|
+
/* retry after converting nil to VT_EMPTY */
|
2770
|
+
if (op.dp.cArgs > cNamedArgs) {
|
2771
|
+
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
|
2772
|
+
n = op.dp.cArgs - i + cNamedArgs - 1;
|
2773
|
+
param = rb_ary_entry(paramS, i-cNamedArgs);
|
2774
|
+
ole_val2variant2(param, &op.dp.rgvarg[n]);
|
2775
|
+
}
|
2776
|
+
if (hr == DISP_E_EXCEPTION) {
|
2777
|
+
ole_freeexceptinfo(&excepinfo);
|
2778
|
+
}
|
2779
|
+
memset(&excepinfo, 0, sizeof(EXCEPINFO));
|
2780
|
+
VariantInit(&result);
|
2781
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
|
2782
|
+
&IID_NULL, lcid, wFlags,
|
2783
|
+
&op.dp, &result,
|
2784
|
+
&excepinfo, &argErr);
|
2785
|
+
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
|
2786
|
+
n = op.dp.cArgs - i + cNamedArgs - 1;
|
2787
|
+
if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
|
2788
|
+
VariantClear(&op.dp.rgvarg[n]);
|
2789
|
+
}
|
2790
|
+
}
|
2791
|
+
}
|
2792
|
+
}
|
2793
|
+
|
2794
|
+
}
|
2795
|
+
/* clear dispatch parameter */
|
2796
|
+
if(op.dp.cArgs > cNamedArgs) {
|
2797
|
+
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
|
2798
|
+
n = op.dp.cArgs - i + cNamedArgs - 1;
|
2799
|
+
param = rb_ary_entry(paramS, i-cNamedArgs);
|
2800
|
+
if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
|
2801
|
+
ole_val2variant(param, &realargs[n]);
|
2802
|
+
} else if ( rb_obj_is_kind_of(param, cWIN32OLE_RECORD) &&
|
2803
|
+
V_VT(&realargs[n]) == VT_RECORD ) {
|
2804
|
+
olerecord_set_ivar(param, V_RECORDINFO(&realargs[n]), V_RECORD(&realargs[n]));
|
2805
|
+
}
|
2806
|
+
}
|
2807
|
+
set_argv(realargs, cNamedArgs, op.dp.cArgs);
|
2808
|
+
}
|
2809
|
+
else {
|
2810
|
+
for(i = 0; i < op.dp.cArgs; i++) {
|
2811
|
+
VariantClear(&op.dp.rgvarg[i]);
|
2812
|
+
}
|
2813
|
+
}
|
2814
|
+
|
2815
|
+
if (FAILED(hr)) {
|
2816
|
+
v = ole_excepinfo2msg(&excepinfo);
|
2817
|
+
ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s",
|
2818
|
+
StringValuePtr(cmd),
|
2819
|
+
StringValuePtr(v));
|
2820
|
+
}
|
2821
|
+
obj = ole_variant2val(&result);
|
2822
|
+
VariantClear(&result);
|
2823
|
+
return obj;
|
2824
|
+
}
|
2825
|
+
|
2826
|
+
/*
|
2827
|
+
* call-seq:
|
2828
|
+
* WIN32OLE#invoke(method, [arg1,...]) => return value of method.
|
2829
|
+
*
|
2830
|
+
* Runs OLE method.
|
2831
|
+
* The first argument specifies the method name of OLE Automation object.
|
2832
|
+
* The others specify argument of the <i>method</i>.
|
2833
|
+
* If you can not execute <i>method</i> directly, then use this method instead.
|
2834
|
+
*
|
2835
|
+
* excel = WIN32OLE.new('Excel.Application')
|
2836
|
+
* excel.invoke('Quit') # => same as excel.Quit
|
2837
|
+
*
|
2838
|
+
*/
|
2839
|
+
static VALUE
|
2840
|
+
fole_invoke(int argc, VALUE *argv, VALUE self)
|
2841
|
+
{
|
2842
|
+
VALUE v = ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
|
2843
|
+
if (v == rb_eNoMethodError) {
|
2844
|
+
return rb_call_super(argc, argv);
|
2845
|
+
}
|
2846
|
+
return v;
|
2847
|
+
}
|
2848
|
+
|
2849
|
+
static VALUE
|
2850
|
+
ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
|
2851
|
+
{
|
2852
|
+
HRESULT hr;
|
2853
|
+
struct oledata *pole = NULL;
|
2854
|
+
unsigned int argErr = 0;
|
2855
|
+
EXCEPINFO excepinfo;
|
2856
|
+
VARIANT result;
|
2857
|
+
DISPPARAMS dispParams;
|
2858
|
+
VARIANTARG* realargs = NULL;
|
2859
|
+
int i, j; VALUE obj = Qnil;
|
2860
|
+
VALUE tp, param;
|
2861
|
+
VALUE v;
|
2862
|
+
VARTYPE vt;
|
2863
|
+
|
2864
|
+
Check_Type(args, T_ARRAY);
|
2865
|
+
Check_Type(types, T_ARRAY);
|
2866
|
+
|
2867
|
+
memset(&excepinfo, 0, sizeof(EXCEPINFO));
|
2868
|
+
memset(&dispParams, 0, sizeof(DISPPARAMS));
|
2869
|
+
VariantInit(&result);
|
2870
|
+
pole = oledata_get_struct(self);
|
2871
|
+
|
2872
|
+
dispParams.cArgs = RARRAY_LEN(args);
|
2873
|
+
dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs);
|
2874
|
+
realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs);
|
2875
|
+
for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--)
|
2876
|
+
{
|
2877
|
+
VariantInit(&realargs[i]);
|
2878
|
+
VariantInit(&dispParams.rgvarg[i]);
|
2879
|
+
tp = rb_ary_entry(types, j);
|
2880
|
+
vt = (VARTYPE)RB_FIX2INT(tp);
|
2881
|
+
V_VT(&dispParams.rgvarg[i]) = vt;
|
2882
|
+
param = rb_ary_entry(args, j);
|
2883
|
+
if (param == Qnil)
|
2884
|
+
{
|
2885
|
+
|
2886
|
+
V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR;
|
2887
|
+
V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND;
|
2888
|
+
}
|
2889
|
+
else
|
2890
|
+
{
|
2891
|
+
if (vt & VT_ARRAY)
|
2892
|
+
{
|
2893
|
+
int ent;
|
2894
|
+
LPBYTE pb;
|
2895
|
+
short* ps;
|
2896
|
+
LPLONG pl;
|
2897
|
+
VARIANT* pv;
|
2898
|
+
CY *py;
|
2899
|
+
VARTYPE v;
|
2900
|
+
SAFEARRAYBOUND rgsabound[1];
|
2901
|
+
Check_Type(param, T_ARRAY);
|
2902
|
+
rgsabound[0].lLbound = 0;
|
2903
|
+
rgsabound[0].cElements = RARRAY_LEN(param);
|
2904
|
+
v = vt & ~(VT_ARRAY | VT_BYREF);
|
2905
|
+
V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound);
|
2906
|
+
V_VT(&realargs[i]) = VT_ARRAY | v;
|
2907
|
+
SafeArrayLock(V_ARRAY(&realargs[i]));
|
2908
|
+
pb = V_ARRAY(&realargs[i])->pvData;
|
2909
|
+
ps = V_ARRAY(&realargs[i])->pvData;
|
2910
|
+
pl = V_ARRAY(&realargs[i])->pvData;
|
2911
|
+
py = V_ARRAY(&realargs[i])->pvData;
|
2912
|
+
pv = V_ARRAY(&realargs[i])->pvData;
|
2913
|
+
for (ent = 0; ent < (int)rgsabound[0].cElements; ent++)
|
2914
|
+
{
|
2915
|
+
VARIANT velem;
|
2916
|
+
VALUE elem = rb_ary_entry(param, ent);
|
2917
|
+
ole_val2variant(elem, &velem);
|
2918
|
+
if (v != VT_VARIANT)
|
2919
|
+
{
|
2920
|
+
VariantChangeTypeEx(&velem, &velem,
|
2921
|
+
cWIN32OLE_lcid, 0, v);
|
2922
|
+
}
|
2923
|
+
switch (v)
|
2924
|
+
{
|
2925
|
+
/* 128 bits */
|
2926
|
+
case VT_VARIANT:
|
2927
|
+
*pv++ = velem;
|
2928
|
+
break;
|
2929
|
+
/* 64 bits */
|
2930
|
+
case VT_R8:
|
2931
|
+
case VT_CY:
|
2932
|
+
case VT_DATE:
|
2933
|
+
*py++ = V_CY(&velem);
|
2934
|
+
break;
|
2935
|
+
/* 16 bits */
|
2936
|
+
case VT_BOOL:
|
2937
|
+
case VT_I2:
|
2938
|
+
case VT_UI2:
|
2939
|
+
*ps++ = V_I2(&velem);
|
2940
|
+
break;
|
2941
|
+
/* 8 bites */
|
2942
|
+
case VT_UI1:
|
2943
|
+
case VT_I1:
|
2944
|
+
*pb++ = V_UI1(&velem);
|
2945
|
+
break;
|
2946
|
+
/* 32 bits */
|
2947
|
+
default:
|
2948
|
+
*pl++ = V_I4(&velem);
|
2949
|
+
break;
|
2950
|
+
}
|
2951
|
+
}
|
2952
|
+
SafeArrayUnlock(V_ARRAY(&realargs[i]));
|
2953
|
+
}
|
2954
|
+
else
|
2955
|
+
{
|
2956
|
+
ole_val2variant(param, &realargs[i]);
|
2957
|
+
if ((vt & (~VT_BYREF)) != VT_VARIANT)
|
2958
|
+
{
|
2959
|
+
hr = VariantChangeTypeEx(&realargs[i], &realargs[i],
|
2960
|
+
cWIN32OLE_lcid, 0,
|
2961
|
+
(VARTYPE)(vt & (~VT_BYREF)));
|
2962
|
+
if (hr != S_OK)
|
2963
|
+
{
|
2964
|
+
rb_raise(rb_eTypeError, "not valid value");
|
2965
|
+
}
|
2966
|
+
}
|
2967
|
+
}
|
2968
|
+
if ((vt & VT_BYREF) || vt == VT_VARIANT)
|
2969
|
+
{
|
2970
|
+
if (vt == VT_VARIANT)
|
2971
|
+
V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF;
|
2972
|
+
switch (vt & (~VT_BYREF))
|
2973
|
+
{
|
2974
|
+
/* 128 bits */
|
2975
|
+
case VT_VARIANT:
|
2976
|
+
V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i];
|
2977
|
+
break;
|
2978
|
+
/* 64 bits */
|
2979
|
+
case VT_R8:
|
2980
|
+
case VT_CY:
|
2981
|
+
case VT_DATE:
|
2982
|
+
V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]);
|
2983
|
+
break;
|
2984
|
+
/* 16 bits */
|
2985
|
+
case VT_BOOL:
|
2986
|
+
case VT_I2:
|
2987
|
+
case VT_UI2:
|
2988
|
+
V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]);
|
2989
|
+
break;
|
2990
|
+
/* 8 bites */
|
2991
|
+
case VT_UI1:
|
2992
|
+
case VT_I1:
|
2993
|
+
V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]);
|
2994
|
+
break;
|
2995
|
+
/* 32 bits */
|
2996
|
+
default:
|
2997
|
+
V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]);
|
2998
|
+
break;
|
2999
|
+
}
|
3000
|
+
}
|
3001
|
+
else
|
3002
|
+
{
|
3003
|
+
/* copy 64 bits of data */
|
3004
|
+
V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]);
|
3005
|
+
}
|
3006
|
+
}
|
3007
|
+
}
|
3008
|
+
|
3009
|
+
if (dispkind & DISPATCH_PROPERTYPUT) {
|
3010
|
+
dispParams.cNamedArgs = 1;
|
3011
|
+
dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
|
3012
|
+
dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
|
3013
|
+
}
|
3014
|
+
|
3015
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, RB_NUM2INT(dispid),
|
3016
|
+
&IID_NULL, cWIN32OLE_lcid,
|
3017
|
+
dispkind,
|
3018
|
+
&dispParams, &result,
|
3019
|
+
&excepinfo, &argErr);
|
3020
|
+
|
3021
|
+
if (FAILED(hr)) {
|
3022
|
+
v = ole_excepinfo2msg(&excepinfo);
|
3023
|
+
ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s",
|
3024
|
+
RB_NUM2INT(dispid),
|
3025
|
+
StringValuePtr(v));
|
3026
|
+
}
|
3027
|
+
|
3028
|
+
/* clear dispatch parameter */
|
3029
|
+
if(dispParams.cArgs > 0) {
|
3030
|
+
set_argv(realargs, 0, dispParams.cArgs);
|
3031
|
+
}
|
3032
|
+
|
3033
|
+
obj = ole_variant2val(&result);
|
3034
|
+
VariantClear(&result);
|
3035
|
+
return obj;
|
3036
|
+
}
|
3037
|
+
|
3038
|
+
/*
|
3039
|
+
* call-seq:
|
3040
|
+
* WIN32OLE#_invoke(dispid, args, types)
|
3041
|
+
*
|
3042
|
+
* Runs the early binding method.
|
3043
|
+
* The 1st argument specifies dispatch ID,
|
3044
|
+
* the 2nd argument specifies the array of arguments,
|
3045
|
+
* the 3rd argument specifies the array of the type of arguments.
|
3046
|
+
*
|
3047
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3048
|
+
* excel._invoke(302, [], []) # same effect as excel.Quit
|
3049
|
+
*/
|
3050
|
+
static VALUE
|
3051
|
+
fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
|
3052
|
+
{
|
3053
|
+
return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD);
|
3054
|
+
}
|
3055
|
+
|
3056
|
+
/*
|
3057
|
+
* call-seq:
|
3058
|
+
* WIN32OLE#_getproperty(dispid, args, types)
|
3059
|
+
*
|
3060
|
+
* Runs the early binding method to get property.
|
3061
|
+
* The 1st argument specifies dispatch ID,
|
3062
|
+
* the 2nd argument specifies the array of arguments,
|
3063
|
+
* the 3rd argument specifies the array of the type of arguments.
|
3064
|
+
*
|
3065
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3066
|
+
* puts excel._getproperty(558, [], []) # same effect as puts excel.visible
|
3067
|
+
*/
|
3068
|
+
static VALUE
|
3069
|
+
fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
|
3070
|
+
{
|
3071
|
+
return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET);
|
3072
|
+
}
|
3073
|
+
|
3074
|
+
/*
|
3075
|
+
* call-seq:
|
3076
|
+
* WIN32OLE#_setproperty(dispid, args, types)
|
3077
|
+
*
|
3078
|
+
* Runs the early binding method to set property.
|
3079
|
+
* The 1st argument specifies dispatch ID,
|
3080
|
+
* the 2nd argument specifies the array of arguments,
|
3081
|
+
* the 3rd argument specifies the array of the type of arguments.
|
3082
|
+
*
|
3083
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3084
|
+
* excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true
|
3085
|
+
*/
|
3086
|
+
static VALUE
|
3087
|
+
fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
|
3088
|
+
{
|
3089
|
+
return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT);
|
3090
|
+
}
|
3091
|
+
|
3092
|
+
/*
|
3093
|
+
* call-seq:
|
3094
|
+
* WIN32OLE[a1, a2, ...]=val
|
3095
|
+
*
|
3096
|
+
* Sets the value to WIN32OLE object specified by a1, a2, ...
|
3097
|
+
*
|
3098
|
+
* dict = WIN32OLE.new('Scripting.Dictionary')
|
3099
|
+
* dict.add('ruby', 'RUBY')
|
3100
|
+
* dict['ruby'] = 'Ruby'
|
3101
|
+
* puts dict['ruby'] # => 'Ruby'
|
3102
|
+
*
|
3103
|
+
* Remark: You can not use this method to set the property value.
|
3104
|
+
*
|
3105
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3106
|
+
* # excel['Visible'] = true # This is error !!!
|
3107
|
+
* excel.Visible = true # You should to use this style to set the property.
|
3108
|
+
*
|
3109
|
+
*/
|
3110
|
+
static VALUE
|
3111
|
+
fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
|
3112
|
+
{
|
3113
|
+
VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE);
|
3114
|
+
if (v == rb_eNoMethodError) {
|
3115
|
+
return rb_call_super(argc, argv);
|
3116
|
+
}
|
3117
|
+
return v;
|
3118
|
+
}
|
3119
|
+
|
3120
|
+
/*
|
3121
|
+
* call-seq:
|
3122
|
+
* WIN32OLE.setproperty('property', [arg1, arg2,...] val)
|
3123
|
+
*
|
3124
|
+
* Sets property of OLE object.
|
3125
|
+
* When you want to set property with argument, you can use this method.
|
3126
|
+
*
|
3127
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3128
|
+
* excel.Visible = true
|
3129
|
+
* book = excel.workbooks.add
|
3130
|
+
* sheet = book.worksheets(1)
|
3131
|
+
* sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10.
|
3132
|
+
*/
|
3133
|
+
static VALUE
|
3134
|
+
fole_setproperty(int argc, VALUE *argv, VALUE self)
|
3135
|
+
{
|
3136
|
+
VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE);
|
3137
|
+
if (v == rb_eNoMethodError) {
|
3138
|
+
return rb_call_super(argc, argv);
|
3139
|
+
}
|
3140
|
+
return v;
|
3141
|
+
}
|
3142
|
+
|
3143
|
+
/*
|
3144
|
+
* call-seq:
|
3145
|
+
* WIN32OLE[a1,a2,...]
|
3146
|
+
*
|
3147
|
+
* Returns the value of Collection specified by a1, a2,....
|
3148
|
+
*
|
3149
|
+
* dict = WIN32OLE.new('Scripting.Dictionary')
|
3150
|
+
* dict.add('ruby', 'Ruby')
|
3151
|
+
* puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')')
|
3152
|
+
*
|
3153
|
+
* Remark: You can not use this method to get the property.
|
3154
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3155
|
+
* # puts excel['Visible'] This is error !!!
|
3156
|
+
* puts excel.Visible # You should to use this style to get the property.
|
3157
|
+
*
|
3158
|
+
*/
|
3159
|
+
static VALUE
|
3160
|
+
fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self)
|
3161
|
+
{
|
3162
|
+
VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE);
|
3163
|
+
if (v == rb_eNoMethodError) {
|
3164
|
+
return rb_call_super(argc, argv);
|
3165
|
+
}
|
3166
|
+
return v;
|
3167
|
+
}
|
3168
|
+
|
3169
|
+
static VALUE
|
3170
|
+
ole_propertyput(VALUE self, VALUE property, VALUE value)
|
3171
|
+
{
|
3172
|
+
struct oledata *pole = NULL;
|
3173
|
+
unsigned argErr;
|
3174
|
+
unsigned int index;
|
3175
|
+
HRESULT hr;
|
3176
|
+
EXCEPINFO excepinfo;
|
3177
|
+
DISPID dispID = DISPID_VALUE;
|
3178
|
+
DISPID dispIDParam = DISPID_PROPERTYPUT;
|
3179
|
+
USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF;
|
3180
|
+
DISPPARAMS dispParams;
|
3181
|
+
VARIANTARG propertyValue[2];
|
3182
|
+
OLECHAR* pBuf[1];
|
3183
|
+
VALUE v;
|
3184
|
+
LCID lcid = cWIN32OLE_lcid;
|
3185
|
+
dispParams.rgdispidNamedArgs = &dispIDParam;
|
3186
|
+
dispParams.rgvarg = propertyValue;
|
3187
|
+
dispParams.cNamedArgs = 1;
|
3188
|
+
dispParams.cArgs = 1;
|
3189
|
+
|
3190
|
+
VariantInit(&propertyValue[0]);
|
3191
|
+
VariantInit(&propertyValue[1]);
|
3192
|
+
memset(&excepinfo, 0, sizeof(excepinfo));
|
3193
|
+
|
3194
|
+
pole = oledata_get_struct(self);
|
3195
|
+
|
3196
|
+
/* get ID from property name */
|
3197
|
+
pBuf[0] = ole_vstr2wc(property);
|
3198
|
+
hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL,
|
3199
|
+
pBuf, 1, lcid, &dispID);
|
3200
|
+
SysFreeString(pBuf[0]);
|
3201
|
+
pBuf[0] = NULL;
|
3202
|
+
|
3203
|
+
if(FAILED(hr)) {
|
3204
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
3205
|
+
"unknown property or method: `%s'",
|
3206
|
+
StringValuePtr(property));
|
3207
|
+
}
|
3208
|
+
/* set property value */
|
3209
|
+
ole_val2variant(value, &propertyValue[0]);
|
3210
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL,
|
3211
|
+
lcid, wFlags, &dispParams,
|
3212
|
+
NULL, &excepinfo, &argErr);
|
3213
|
+
|
3214
|
+
for(index = 0; index < dispParams.cArgs; ++index) {
|
3215
|
+
VariantClear(&propertyValue[index]);
|
3216
|
+
}
|
3217
|
+
if (FAILED(hr)) {
|
3218
|
+
v = ole_excepinfo2msg(&excepinfo);
|
3219
|
+
ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s",
|
3220
|
+
StringValuePtr(property),
|
3221
|
+
StringValuePtr(v));
|
3222
|
+
}
|
3223
|
+
return Qnil;
|
3224
|
+
}
|
3225
|
+
|
3226
|
+
/*
|
3227
|
+
* call-seq:
|
3228
|
+
* WIN32OLE#ole_free
|
3229
|
+
*
|
3230
|
+
* invokes Release method of Dispatch interface of WIN32OLE object.
|
3231
|
+
* Usually, you do not need to call this method because Release method
|
3232
|
+
* called automatically when WIN32OLE object garbaged.
|
3233
|
+
*
|
3234
|
+
*/
|
3235
|
+
static VALUE
|
3236
|
+
fole_free(VALUE self)
|
3237
|
+
{
|
3238
|
+
struct oledata *pole = NULL;
|
3239
|
+
pole = oledata_get_struct(self);
|
3240
|
+
OLE_FREE(pole->pDispatch);
|
3241
|
+
pole->pDispatch = NULL;
|
3242
|
+
return Qnil;
|
3243
|
+
}
|
3244
|
+
|
3245
|
+
static VALUE
|
3246
|
+
ole_each_sub(VALUE pEnumV)
|
3247
|
+
{
|
3248
|
+
VARIANT variant;
|
3249
|
+
VALUE obj = Qnil;
|
3250
|
+
IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
|
3251
|
+
VariantInit(&variant);
|
3252
|
+
while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) {
|
3253
|
+
obj = ole_variant2val(&variant);
|
3254
|
+
VariantClear(&variant);
|
3255
|
+
VariantInit(&variant);
|
3256
|
+
rb_yield(obj);
|
3257
|
+
}
|
3258
|
+
return Qnil;
|
3259
|
+
}
|
3260
|
+
|
3261
|
+
static VALUE
|
3262
|
+
ole_ienum_free(VALUE pEnumV)
|
3263
|
+
{
|
3264
|
+
IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
|
3265
|
+
OLE_RELEASE(pEnum);
|
3266
|
+
return Qnil;
|
3267
|
+
}
|
3268
|
+
|
3269
|
+
/*
|
3270
|
+
* call-seq:
|
3271
|
+
* WIN32OLE#each {|i|...}
|
3272
|
+
*
|
3273
|
+
* Iterates over each item of OLE collection which has IEnumVARIANT interface.
|
3274
|
+
*
|
3275
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3276
|
+
* book = excel.workbooks.add
|
3277
|
+
* sheets = book.worksheets(1)
|
3278
|
+
* cells = sheets.cells("A1:A5")
|
3279
|
+
* cells.each do |cell|
|
3280
|
+
* cell.value = 10
|
3281
|
+
* end
|
3282
|
+
*/
|
3283
|
+
static VALUE
|
3284
|
+
fole_each(VALUE self)
|
3285
|
+
{
|
3286
|
+
LCID lcid = cWIN32OLE_lcid;
|
3287
|
+
|
3288
|
+
struct oledata *pole = NULL;
|
3289
|
+
|
3290
|
+
unsigned int argErr;
|
3291
|
+
EXCEPINFO excepinfo;
|
3292
|
+
DISPPARAMS dispParams;
|
3293
|
+
VARIANT result;
|
3294
|
+
HRESULT hr;
|
3295
|
+
IEnumVARIANT *pEnum = NULL;
|
3296
|
+
void *p;
|
3297
|
+
|
3298
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
3299
|
+
|
3300
|
+
VariantInit(&result);
|
3301
|
+
dispParams.rgvarg = NULL;
|
3302
|
+
dispParams.rgdispidNamedArgs = NULL;
|
3303
|
+
dispParams.cNamedArgs = 0;
|
3304
|
+
dispParams.cArgs = 0;
|
3305
|
+
memset(&excepinfo, 0, sizeof(excepinfo));
|
3306
|
+
|
3307
|
+
pole = oledata_get_struct(self);
|
3308
|
+
hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM,
|
3309
|
+
&IID_NULL, lcid,
|
3310
|
+
DISPATCH_METHOD | DISPATCH_PROPERTYGET,
|
3311
|
+
&dispParams, &result,
|
3312
|
+
&excepinfo, &argErr);
|
3313
|
+
|
3314
|
+
if (FAILED(hr)) {
|
3315
|
+
VariantClear(&result);
|
3316
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get IEnum Interface");
|
3317
|
+
}
|
3318
|
+
|
3319
|
+
if (V_VT(&result) == VT_UNKNOWN) {
|
3320
|
+
hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result),
|
3321
|
+
&IID_IEnumVARIANT,
|
3322
|
+
&p);
|
3323
|
+
pEnum = p;
|
3324
|
+
} else if (V_VT(&result) == VT_DISPATCH) {
|
3325
|
+
hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result),
|
3326
|
+
&IID_IEnumVARIANT,
|
3327
|
+
&p);
|
3328
|
+
pEnum = p;
|
3329
|
+
}
|
3330
|
+
if (FAILED(hr) || !pEnum) {
|
3331
|
+
VariantClear(&result);
|
3332
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get IEnum Interface");
|
3333
|
+
}
|
3334
|
+
|
3335
|
+
VariantClear(&result);
|
3336
|
+
rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
|
3337
|
+
return Qnil;
|
3338
|
+
}
|
3339
|
+
|
3340
|
+
/*
|
3341
|
+
* call-seq:
|
3342
|
+
* WIN32OLE#method_missing(id [,arg1, arg2, ...])
|
3343
|
+
*
|
3344
|
+
* Calls WIN32OLE#invoke method.
|
3345
|
+
*/
|
3346
|
+
static VALUE
|
3347
|
+
fole_missing(int argc, VALUE *argv, VALUE self)
|
3348
|
+
{
|
3349
|
+
VALUE mid, org_mid, sym, v;
|
3350
|
+
const char* mname;
|
3351
|
+
long n;
|
3352
|
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
3353
|
+
mid = org_mid = argv[0];
|
3354
|
+
sym = rb_check_symbol(&mid);
|
3355
|
+
if (!NIL_P(sym)) mid = rb_sym2str(sym);
|
3356
|
+
mname = StringValueCStr(mid);
|
3357
|
+
if(!mname) {
|
3358
|
+
rb_raise(rb_eRuntimeError, "fail: unknown method or property");
|
3359
|
+
}
|
3360
|
+
n = RSTRING_LEN(mid);
|
3361
|
+
if(mname[n-1] == '=') {
|
3362
|
+
rb_check_arity(argc, 2, 2);
|
3363
|
+
argv[0] = rb_enc_associate(rb_str_subseq(mid, 0, n-1), cWIN32OLE_enc);
|
3364
|
+
|
3365
|
+
return ole_propertyput(self, argv[0], argv[1]);
|
3366
|
+
}
|
3367
|
+
else {
|
3368
|
+
argv[0] = rb_enc_associate(rb_str_dup(mid), cWIN32OLE_enc);
|
3369
|
+
v = ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
|
3370
|
+
if (v == rb_eNoMethodError) {
|
3371
|
+
argv[0] = org_mid;
|
3372
|
+
return rb_call_super(argc, argv);
|
3373
|
+
}
|
3374
|
+
return v;
|
3375
|
+
}
|
3376
|
+
}
|
3377
|
+
|
3378
|
+
static HRESULT
|
3379
|
+
typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti)
|
3380
|
+
{
|
3381
|
+
ITypeInfo *pTypeInfo;
|
3382
|
+
ITypeLib *pTypeLib;
|
3383
|
+
BSTR bstr;
|
3384
|
+
VALUE type;
|
3385
|
+
UINT i;
|
3386
|
+
UINT count;
|
3387
|
+
LCID lcid = cWIN32OLE_lcid;
|
3388
|
+
HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
|
3389
|
+
0, lcid, &pTypeInfo);
|
3390
|
+
if(FAILED(hr)) {
|
3391
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
|
3392
|
+
}
|
3393
|
+
hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo,
|
3394
|
+
-1,
|
3395
|
+
&bstr,
|
3396
|
+
NULL, NULL, NULL);
|
3397
|
+
type = WC2VSTR(bstr);
|
3398
|
+
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
|
3399
|
+
OLE_RELEASE(pTypeInfo);
|
3400
|
+
if (FAILED(hr)) {
|
3401
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetContainingTypeLib");
|
3402
|
+
}
|
3403
|
+
count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
|
3404
|
+
for (i = 0; i < count; i++) {
|
3405
|
+
hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
|
3406
|
+
&bstr, NULL, NULL, NULL);
|
3407
|
+
if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) {
|
3408
|
+
hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
|
3409
|
+
if (SUCCEEDED(hr)) {
|
3410
|
+
*ppti = pTypeInfo;
|
3411
|
+
break;
|
3412
|
+
}
|
3413
|
+
}
|
3414
|
+
}
|
3415
|
+
OLE_RELEASE(pTypeLib);
|
3416
|
+
return hr;
|
3417
|
+
}
|
3418
|
+
|
3419
|
+
static VALUE
|
3420
|
+
ole_methods(VALUE self, int mask)
|
3421
|
+
{
|
3422
|
+
ITypeInfo *pTypeInfo;
|
3423
|
+
HRESULT hr;
|
3424
|
+
VALUE methods;
|
3425
|
+
struct oledata *pole = NULL;
|
3426
|
+
|
3427
|
+
pole = oledata_get_struct(self);
|
3428
|
+
methods = rb_ary_new();
|
3429
|
+
|
3430
|
+
hr = typeinfo_from_ole(pole, &pTypeInfo);
|
3431
|
+
if(FAILED(hr))
|
3432
|
+
return methods;
|
3433
|
+
rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask));
|
3434
|
+
OLE_RELEASE(pTypeInfo);
|
3435
|
+
return methods;
|
3436
|
+
}
|
3437
|
+
|
3438
|
+
/*
|
3439
|
+
* call-seq:
|
3440
|
+
* WIN32OLE#ole_methods
|
3441
|
+
*
|
3442
|
+
* Returns the array of WIN32OLE_METHOD object.
|
3443
|
+
* The element is OLE method of WIN32OLE object.
|
3444
|
+
*
|
3445
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3446
|
+
* methods = excel.ole_methods
|
3447
|
+
*
|
3448
|
+
*/
|
3449
|
+
static VALUE
|
3450
|
+
fole_methods(VALUE self)
|
3451
|
+
{
|
3452
|
+
return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
|
3453
|
+
}
|
3454
|
+
|
3455
|
+
/*
|
3456
|
+
* call-seq:
|
3457
|
+
* WIN32OLE#ole_get_methods
|
3458
|
+
*
|
3459
|
+
* Returns the array of WIN32OLE_METHOD object .
|
3460
|
+
* The element of the array is property (gettable) of WIN32OLE object.
|
3461
|
+
*
|
3462
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3463
|
+
* properties = excel.ole_get_methods
|
3464
|
+
*/
|
3465
|
+
static VALUE
|
3466
|
+
fole_get_methods(VALUE self)
|
3467
|
+
{
|
3468
|
+
return ole_methods( self, INVOKE_PROPERTYGET);
|
3469
|
+
}
|
3470
|
+
|
3471
|
+
/*
|
3472
|
+
* call-seq:
|
3473
|
+
* WIN32OLE#ole_put_methods
|
3474
|
+
*
|
3475
|
+
* Returns the array of WIN32OLE_METHOD object .
|
3476
|
+
* The element of the array is property (settable) of WIN32OLE object.
|
3477
|
+
*
|
3478
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3479
|
+
* properties = excel.ole_put_methods
|
3480
|
+
*/
|
3481
|
+
static VALUE
|
3482
|
+
fole_put_methods(VALUE self)
|
3483
|
+
{
|
3484
|
+
return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF);
|
3485
|
+
}
|
3486
|
+
|
3487
|
+
/*
|
3488
|
+
* call-seq:
|
3489
|
+
* WIN32OLE#ole_func_methods
|
3490
|
+
*
|
3491
|
+
* Returns the array of WIN32OLE_METHOD object .
|
3492
|
+
* The element of the array is property (settable) of WIN32OLE object.
|
3493
|
+
*
|
3494
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3495
|
+
* properties = excel.ole_func_methods
|
3496
|
+
*
|
3497
|
+
*/
|
3498
|
+
static VALUE
|
3499
|
+
fole_func_methods(VALUE self)
|
3500
|
+
{
|
3501
|
+
return ole_methods( self, INVOKE_FUNC);
|
3502
|
+
}
|
3503
|
+
|
3504
|
+
/*
|
3505
|
+
* call-seq:
|
3506
|
+
* WIN32OLE#ole_type
|
3507
|
+
*
|
3508
|
+
* Returns WIN32OLE_TYPE object.
|
3509
|
+
*
|
3510
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3511
|
+
* tobj = excel.ole_type
|
3512
|
+
*/
|
3513
|
+
static VALUE
|
3514
|
+
fole_type(VALUE self)
|
3515
|
+
{
|
3516
|
+
ITypeInfo *pTypeInfo;
|
3517
|
+
HRESULT hr;
|
3518
|
+
struct oledata *pole = NULL;
|
3519
|
+
LCID lcid = cWIN32OLE_lcid;
|
3520
|
+
VALUE type = Qnil;
|
3521
|
+
|
3522
|
+
pole = oledata_get_struct(self);
|
3523
|
+
|
3524
|
+
hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo );
|
3525
|
+
if(FAILED(hr)) {
|
3526
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
|
3527
|
+
}
|
3528
|
+
type = ole_type_from_itypeinfo(pTypeInfo);
|
3529
|
+
OLE_RELEASE(pTypeInfo);
|
3530
|
+
if (type == Qnil) {
|
3531
|
+
rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo");
|
3532
|
+
}
|
3533
|
+
return type;
|
3534
|
+
}
|
3535
|
+
|
3536
|
+
/*
|
3537
|
+
* call-seq:
|
3538
|
+
* WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object
|
3539
|
+
*
|
3540
|
+
* Returns the WIN32OLE_TYPELIB object. The object represents the
|
3541
|
+
* type library which contains the WIN32OLE object.
|
3542
|
+
*
|
3543
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3544
|
+
* tlib = excel.ole_typelib
|
3545
|
+
* puts tlib.name # -> 'Microsoft Excel 9.0 Object Library'
|
3546
|
+
*/
|
3547
|
+
static VALUE
|
3548
|
+
fole_typelib(VALUE self)
|
3549
|
+
{
|
3550
|
+
struct oledata *pole = NULL;
|
3551
|
+
HRESULT hr;
|
3552
|
+
ITypeInfo *pTypeInfo;
|
3553
|
+
LCID lcid = cWIN32OLE_lcid;
|
3554
|
+
VALUE vtlib = Qnil;
|
3555
|
+
|
3556
|
+
pole = oledata_get_struct(self);
|
3557
|
+
hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
|
3558
|
+
0, lcid, &pTypeInfo);
|
3559
|
+
if(FAILED(hr)) {
|
3560
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
|
3561
|
+
}
|
3562
|
+
vtlib = ole_typelib_from_itypeinfo(pTypeInfo);
|
3563
|
+
OLE_RELEASE(pTypeInfo);
|
3564
|
+
if (vtlib == Qnil) {
|
3565
|
+
rb_raise(rb_eRuntimeError, "failed to get type library info.");
|
3566
|
+
}
|
3567
|
+
return vtlib;
|
3568
|
+
}
|
3569
|
+
|
3570
|
+
/*
|
3571
|
+
* call-seq:
|
3572
|
+
* WIN32OLE#ole_query_interface(iid) -> WIN32OLE object
|
3573
|
+
*
|
3574
|
+
* Returns WIN32OLE object for a specific dispatch or dual
|
3575
|
+
* interface specified by iid.
|
3576
|
+
*
|
3577
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
3578
|
+
* ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp
|
3579
|
+
*/
|
3580
|
+
static VALUE
|
3581
|
+
fole_query_interface(VALUE self, VALUE str_iid)
|
3582
|
+
{
|
3583
|
+
HRESULT hr;
|
3584
|
+
OLECHAR *pBuf;
|
3585
|
+
IID iid;
|
3586
|
+
struct oledata *pole = NULL;
|
3587
|
+
IDispatch *pDispatch;
|
3588
|
+
void *p;
|
3589
|
+
|
3590
|
+
pBuf = ole_vstr2wc(str_iid);
|
3591
|
+
hr = CLSIDFromString(pBuf, &iid);
|
3592
|
+
SysFreeString(pBuf);
|
3593
|
+
if(FAILED(hr)) {
|
3594
|
+
ole_raise(hr, eWIN32OLERuntimeError,
|
3595
|
+
"invalid iid: `%s'",
|
3596
|
+
StringValuePtr(str_iid));
|
3597
|
+
}
|
3598
|
+
|
3599
|
+
pole = oledata_get_struct(self);
|
3600
|
+
if(!pole->pDispatch) {
|
3601
|
+
rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
|
3602
|
+
}
|
3603
|
+
|
3604
|
+
hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid,
|
3605
|
+
&p);
|
3606
|
+
if(FAILED(hr)) {
|
3607
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError,
|
3608
|
+
"failed to get interface `%s'",
|
3609
|
+
StringValuePtr(str_iid));
|
3610
|
+
}
|
3611
|
+
|
3612
|
+
pDispatch = p;
|
3613
|
+
return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
|
3614
|
+
}
|
3615
|
+
|
3616
|
+
/*
|
3617
|
+
* call-seq:
|
3618
|
+
* WIN32OLE#ole_respond_to?(method) -> true or false
|
3619
|
+
*
|
3620
|
+
* Returns true when OLE object has OLE method, otherwise returns false.
|
3621
|
+
*
|
3622
|
+
* ie = WIN32OLE.new('InternetExplorer.Application')
|
3623
|
+
* ie.ole_respond_to?("gohome") => true
|
3624
|
+
*/
|
3625
|
+
static VALUE
|
3626
|
+
fole_respond_to(VALUE self, VALUE method)
|
3627
|
+
{
|
3628
|
+
struct oledata *pole = NULL;
|
3629
|
+
BSTR wcmdname;
|
3630
|
+
DISPID DispID;
|
3631
|
+
HRESULT hr;
|
3632
|
+
if(!RB_TYPE_P(method, T_STRING) && !RB_TYPE_P(method, T_SYMBOL)) {
|
3633
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
|
3634
|
+
}
|
3635
|
+
if (RB_TYPE_P(method, T_SYMBOL)) {
|
3636
|
+
method = rb_sym2str(method);
|
3637
|
+
}
|
3638
|
+
pole = oledata_get_struct(self);
|
3639
|
+
wcmdname = ole_vstr2wc(method);
|
3640
|
+
hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
|
3641
|
+
&wcmdname, 1, cWIN32OLE_lcid, &DispID);
|
3642
|
+
SysFreeString(wcmdname);
|
3643
|
+
return SUCCEEDED(hr) ? Qtrue : Qfalse;
|
3644
|
+
}
|
3645
|
+
|
3646
|
+
HRESULT
|
3647
|
+
ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
|
3648
|
+
{
|
3649
|
+
HRESULT hr;
|
3650
|
+
ITypeLib *pTypeLib;
|
3651
|
+
UINT i;
|
3652
|
+
|
3653
|
+
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
|
3654
|
+
if (FAILED(hr)) {
|
3655
|
+
return hr;
|
3656
|
+
}
|
3657
|
+
|
3658
|
+
hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
|
3659
|
+
name, helpstr,
|
3660
|
+
helpcontext, helpfile);
|
3661
|
+
if (FAILED(hr)) {
|
3662
|
+
OLE_RELEASE(pTypeLib);
|
3663
|
+
return hr;
|
3664
|
+
}
|
3665
|
+
OLE_RELEASE(pTypeLib);
|
3666
|
+
return hr;
|
3667
|
+
}
|
3668
|
+
|
3669
|
+
static VALUE
|
3670
|
+
ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
|
3671
|
+
{
|
3672
|
+
HRESULT hr;
|
3673
|
+
BSTR bstr;
|
3674
|
+
ITypeInfo *pRefTypeInfo;
|
3675
|
+
VALUE type = Qnil;
|
3676
|
+
|
3677
|
+
hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
|
3678
|
+
V_UNION1(pTypeDesc, hreftype),
|
3679
|
+
&pRefTypeInfo);
|
3680
|
+
if(FAILED(hr))
|
3681
|
+
return Qnil;
|
3682
|
+
hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL);
|
3683
|
+
if(FAILED(hr)) {
|
3684
|
+
OLE_RELEASE(pRefTypeInfo);
|
3685
|
+
return Qnil;
|
3686
|
+
}
|
3687
|
+
OLE_RELEASE(pRefTypeInfo);
|
3688
|
+
type = WC2VSTR(bstr);
|
3689
|
+
if(typedetails != Qnil)
|
3690
|
+
rb_ary_push(typedetails, type);
|
3691
|
+
return type;
|
3692
|
+
}
|
3693
|
+
|
3694
|
+
static VALUE
|
3695
|
+
ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
|
3696
|
+
{
|
3697
|
+
TYPEDESC *p = pTypeDesc;
|
3698
|
+
VALUE type = rb_str_new2("");
|
3699
|
+
|
3700
|
+
if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) {
|
3701
|
+
p = V_UNION1(p, lptdesc);
|
3702
|
+
type = ole_typedesc2val(pTypeInfo, p, typedetails);
|
3703
|
+
}
|
3704
|
+
return type;
|
3705
|
+
}
|
3706
|
+
|
3707
|
+
VALUE
|
3708
|
+
ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
|
3709
|
+
{
|
3710
|
+
VALUE str;
|
3711
|
+
VALUE typestr = Qnil;
|
3712
|
+
switch(pTypeDesc->vt) {
|
3713
|
+
case VT_I2:
|
3714
|
+
typestr = rb_str_new2("I2");
|
3715
|
+
break;
|
3716
|
+
case VT_I4:
|
3717
|
+
typestr = rb_str_new2("I4");
|
3718
|
+
break;
|
3719
|
+
case VT_R4:
|
3720
|
+
typestr = rb_str_new2("R4");
|
3721
|
+
break;
|
3722
|
+
case VT_R8:
|
3723
|
+
typestr = rb_str_new2("R8");
|
3724
|
+
break;
|
3725
|
+
case VT_CY:
|
3726
|
+
typestr = rb_str_new2("CY");
|
3727
|
+
break;
|
3728
|
+
case VT_DATE:
|
3729
|
+
typestr = rb_str_new2("DATE");
|
3730
|
+
break;
|
3731
|
+
case VT_BSTR:
|
3732
|
+
typestr = rb_str_new2("BSTR");
|
3733
|
+
break;
|
3734
|
+
case VT_BOOL:
|
3735
|
+
typestr = rb_str_new2("BOOL");
|
3736
|
+
break;
|
3737
|
+
case VT_VARIANT:
|
3738
|
+
typestr = rb_str_new2("VARIANT");
|
3739
|
+
break;
|
3740
|
+
case VT_DECIMAL:
|
3741
|
+
typestr = rb_str_new2("DECIMAL");
|
3742
|
+
break;
|
3743
|
+
case VT_I1:
|
3744
|
+
typestr = rb_str_new2("I1");
|
3745
|
+
break;
|
3746
|
+
case VT_UI1:
|
3747
|
+
typestr = rb_str_new2("UI1");
|
3748
|
+
break;
|
3749
|
+
case VT_UI2:
|
3750
|
+
typestr = rb_str_new2("UI2");
|
3751
|
+
break;
|
3752
|
+
case VT_UI4:
|
3753
|
+
typestr = rb_str_new2("UI4");
|
3754
|
+
break;
|
3755
|
+
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
3756
|
+
case VT_I8:
|
3757
|
+
typestr = rb_str_new2("I8");
|
3758
|
+
break;
|
3759
|
+
case VT_UI8:
|
3760
|
+
typestr = rb_str_new2("UI8");
|
3761
|
+
break;
|
3762
|
+
#endif
|
3763
|
+
case VT_INT:
|
3764
|
+
typestr = rb_str_new2("INT");
|
3765
|
+
break;
|
3766
|
+
case VT_UINT:
|
3767
|
+
typestr = rb_str_new2("UINT");
|
3768
|
+
break;
|
3769
|
+
case VT_VOID:
|
3770
|
+
typestr = rb_str_new2("VOID");
|
3771
|
+
break;
|
3772
|
+
case VT_HRESULT:
|
3773
|
+
typestr = rb_str_new2("HRESULT");
|
3774
|
+
break;
|
3775
|
+
case VT_PTR:
|
3776
|
+
typestr = rb_str_new2("PTR");
|
3777
|
+
if(typedetails != Qnil)
|
3778
|
+
rb_ary_push(typedetails, typestr);
|
3779
|
+
return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
|
3780
|
+
case VT_SAFEARRAY:
|
3781
|
+
typestr = rb_str_new2("SAFEARRAY");
|
3782
|
+
if(typedetails != Qnil)
|
3783
|
+
rb_ary_push(typedetails, typestr);
|
3784
|
+
return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
|
3785
|
+
case VT_CARRAY:
|
3786
|
+
typestr = rb_str_new2("CARRAY");
|
3787
|
+
break;
|
3788
|
+
case VT_USERDEFINED:
|
3789
|
+
typestr = rb_str_new2("USERDEFINED");
|
3790
|
+
if (typedetails != Qnil)
|
3791
|
+
rb_ary_push(typedetails, typestr);
|
3792
|
+
str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails);
|
3793
|
+
if (str != Qnil) {
|
3794
|
+
return str;
|
3795
|
+
}
|
3796
|
+
return typestr;
|
3797
|
+
case VT_UNKNOWN:
|
3798
|
+
typestr = rb_str_new2("UNKNOWN");
|
3799
|
+
break;
|
3800
|
+
case VT_DISPATCH:
|
3801
|
+
typestr = rb_str_new2("DISPATCH");
|
3802
|
+
break;
|
3803
|
+
case VT_ERROR:
|
3804
|
+
typestr = rb_str_new2("ERROR");
|
3805
|
+
break;
|
3806
|
+
case VT_LPWSTR:
|
3807
|
+
typestr = rb_str_new2("LPWSTR");
|
3808
|
+
break;
|
3809
|
+
case VT_LPSTR:
|
3810
|
+
typestr = rb_str_new2("LPSTR");
|
3811
|
+
break;
|
3812
|
+
case VT_RECORD:
|
3813
|
+
typestr = rb_str_new2("RECORD");
|
3814
|
+
break;
|
3815
|
+
default:
|
3816
|
+
typestr = rb_str_new2("Unknown Type ");
|
3817
|
+
rb_str_concat(typestr, rb_fix2str(RB_INT2FIX(pTypeDesc->vt), 10));
|
3818
|
+
break;
|
3819
|
+
}
|
3820
|
+
if (typedetails != Qnil)
|
3821
|
+
rb_ary_push(typedetails, typestr);
|
3822
|
+
return typestr;
|
3823
|
+
}
|
3824
|
+
|
3825
|
+
/*
|
3826
|
+
* call-seq:
|
3827
|
+
* WIN32OLE#ole_method_help(method)
|
3828
|
+
*
|
3829
|
+
* Returns WIN32OLE_METHOD object corresponding with method
|
3830
|
+
* specified by 1st argument.
|
3831
|
+
*
|
3832
|
+
* excel = WIN32OLE.new('Excel.Application')
|
3833
|
+
* method = excel.ole_method_help('Quit')
|
3834
|
+
*
|
3835
|
+
*/
|
3836
|
+
static VALUE
|
3837
|
+
fole_method_help(VALUE self, VALUE cmdname)
|
3838
|
+
{
|
3839
|
+
ITypeInfo *pTypeInfo;
|
3840
|
+
HRESULT hr;
|
3841
|
+
struct oledata *pole = NULL;
|
3842
|
+
VALUE obj;
|
3843
|
+
|
3844
|
+
SafeStringValue(cmdname);
|
3845
|
+
pole = oledata_get_struct(self);
|
3846
|
+
hr = typeinfo_from_ole(pole, &pTypeInfo);
|
3847
|
+
if(FAILED(hr))
|
3848
|
+
ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get ITypeInfo");
|
3849
|
+
|
3850
|
+
obj = create_win32ole_method(pTypeInfo, cmdname);
|
3851
|
+
|
3852
|
+
OLE_RELEASE(pTypeInfo);
|
3853
|
+
if (obj == Qnil)
|
3854
|
+
rb_raise(eWIN32OLERuntimeError, "not found %s",
|
3855
|
+
StringValuePtr(cmdname));
|
3856
|
+
return obj;
|
3857
|
+
}
|
3858
|
+
|
3859
|
+
/*
|
3860
|
+
* call-seq:
|
3861
|
+
* WIN32OLE#ole_activex_initialize() -> Qnil
|
3862
|
+
*
|
3863
|
+
* Initialize WIN32OLE object(ActiveX Control) by calling
|
3864
|
+
* IPersistMemory::InitNew.
|
3865
|
+
*
|
3866
|
+
* Before calling OLE method, some kind of the ActiveX controls
|
3867
|
+
* created with MFC should be initialized by calling
|
3868
|
+
* IPersistXXX::InitNew.
|
3869
|
+
*
|
3870
|
+
* If and only if you received the exception "HRESULT error code:
|
3871
|
+
* 0x8000ffff catastrophic failure", try this method before
|
3872
|
+
* invoking any ole_method.
|
3873
|
+
*
|
3874
|
+
* obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control")
|
3875
|
+
* obj.ole_activex_initialize
|
3876
|
+
* obj.method(...)
|
3877
|
+
*
|
3878
|
+
*/
|
3879
|
+
static VALUE
|
3880
|
+
fole_activex_initialize(VALUE self)
|
3881
|
+
{
|
3882
|
+
struct oledata *pole = NULL;
|
3883
|
+
IPersistMemory *pPersistMemory;
|
3884
|
+
void *p;
|
3885
|
+
|
3886
|
+
HRESULT hr = S_OK;
|
3887
|
+
|
3888
|
+
pole = oledata_get_struct(self);
|
3889
|
+
|
3890
|
+
hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p);
|
3891
|
+
pPersistMemory = p;
|
3892
|
+
if (SUCCEEDED(hr)) {
|
3893
|
+
hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory);
|
3894
|
+
OLE_RELEASE(pPersistMemory);
|
3895
|
+
if (SUCCEEDED(hr)) {
|
3896
|
+
return Qnil;
|
3897
|
+
}
|
3898
|
+
}
|
3899
|
+
|
3900
|
+
if (FAILED(hr)) {
|
3901
|
+
ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control");
|
3902
|
+
}
|
3903
|
+
|
3904
|
+
return Qnil;
|
3905
|
+
}
|
3906
|
+
|
3907
|
+
HRESULT
|
3908
|
+
typelib_from_val(VALUE obj, ITypeLib **pTypeLib)
|
3909
|
+
{
|
3910
|
+
LCID lcid = cWIN32OLE_lcid;
|
3911
|
+
HRESULT hr;
|
3912
|
+
struct oledata *pole = NULL;
|
3913
|
+
unsigned int index;
|
3914
|
+
ITypeInfo *pTypeInfo;
|
3915
|
+
pole = oledata_get_struct(obj);
|
3916
|
+
hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
|
3917
|
+
0, lcid, &pTypeInfo);
|
3918
|
+
if (FAILED(hr)) {
|
3919
|
+
return hr;
|
3920
|
+
}
|
3921
|
+
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, pTypeLib, &index);
|
3922
|
+
OLE_RELEASE(pTypeInfo);
|
3923
|
+
return hr;
|
3924
|
+
}
|
3925
|
+
|
3926
|
+
static void
|
3927
|
+
com_hash_free(void *ptr)
|
3928
|
+
{
|
3929
|
+
st_table *tbl = ptr;
|
3930
|
+
st_free_table(tbl);
|
3931
|
+
}
|
3932
|
+
|
3933
|
+
static void
|
3934
|
+
com_hash_mark(void *ptr)
|
3935
|
+
{
|
3936
|
+
st_table *tbl = ptr;
|
3937
|
+
rb_mark_hash(tbl);
|
3938
|
+
}
|
3939
|
+
|
3940
|
+
static size_t
|
3941
|
+
com_hash_size(const void *ptr)
|
3942
|
+
{
|
3943
|
+
const st_table *tbl = ptr;
|
3944
|
+
return st_memsize(tbl);
|
3945
|
+
}
|
3946
|
+
|
3947
|
+
static void
|
3948
|
+
check_nano_server(void)
|
3949
|
+
{
|
3950
|
+
HKEY hsubkey;
|
3951
|
+
LONG err;
|
3952
|
+
const char * subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Server\\ServerLevels";
|
3953
|
+
const char * regval = "NanoServer";
|
3954
|
+
|
3955
|
+
err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &hsubkey);
|
3956
|
+
if (err == ERROR_SUCCESS) {
|
3957
|
+
err = RegQueryValueEx(hsubkey, regval, NULL, NULL, NULL, NULL);
|
3958
|
+
if (err == ERROR_SUCCESS) {
|
3959
|
+
g_running_nano = TRUE;
|
3960
|
+
}
|
3961
|
+
RegCloseKey(hsubkey);
|
3962
|
+
}
|
3963
|
+
}
|
3964
|
+
|
3965
|
+
|
3966
|
+
void
|
3967
|
+
Init_win32ole(void)
|
3968
|
+
{
|
3969
|
+
cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT;
|
3970
|
+
g_ole_initialized_init();
|
3971
|
+
check_nano_server();
|
3972
|
+
|
3973
|
+
com_vtbl.QueryInterface = QueryInterface;
|
3974
|
+
com_vtbl.AddRef = AddRef;
|
3975
|
+
com_vtbl.Release = Release;
|
3976
|
+
com_vtbl.GetTypeInfoCount = GetTypeInfoCount;
|
3977
|
+
com_vtbl.GetTypeInfo = GetTypeInfo;
|
3978
|
+
com_vtbl.GetIDsOfNames = GetIDsOfNames;
|
3979
|
+
com_vtbl.Invoke = Invoke;
|
3980
|
+
|
3981
|
+
message_filter.QueryInterface = mf_QueryInterface;
|
3982
|
+
message_filter.AddRef = mf_AddRef;
|
3983
|
+
message_filter.Release = mf_Release;
|
3984
|
+
message_filter.HandleInComingCall = mf_HandleInComingCall;
|
3985
|
+
message_filter.RetryRejectedCall = mf_RetryRejectedCall;
|
3986
|
+
message_filter.MessagePending = mf_MessagePending;
|
3987
|
+
|
3988
|
+
enc2cp_hash = TypedData_Wrap_Struct(0, &win32ole_hash_datatype, 0);
|
3989
|
+
RTYPEDDATA_DATA(enc2cp_hash) = st_init_numtable();
|
3990
|
+
rb_gc_register_mark_object(enc2cp_hash);
|
3991
|
+
|
3992
|
+
com_hash = TypedData_Wrap_Struct(0, &win32ole_hash_datatype, 0);
|
3993
|
+
RTYPEDDATA_DATA(com_hash) = st_init_numtable();
|
3994
|
+
rb_gc_register_mark_object(com_hash);
|
3995
|
+
|
3996
|
+
cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
|
3997
|
+
|
3998
|
+
rb_define_alloc_func(cWIN32OLE, fole_s_allocate);
|
3999
|
+
|
4000
|
+
rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1);
|
4001
|
+
|
4002
|
+
rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1);
|
4003
|
+
rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1);
|
4004
|
+
|
4005
|
+
rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1);
|
4006
|
+
rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1);
|
4007
|
+
rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1);
|
4008
|
+
rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0);
|
4009
|
+
rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1);
|
4010
|
+
rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0);
|
4011
|
+
rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1);
|
4012
|
+
rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0);
|
4013
|
+
rb_define_singleton_method(cWIN32OLE, "ole_initialize", fole_s_ole_initialize, 0);
|
4014
|
+
rb_define_singleton_method(cWIN32OLE, "ole_uninitialize", fole_s_ole_uninitialize, 0);
|
4015
|
+
|
4016
|
+
rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1);
|
4017
|
+
rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1);
|
4018
|
+
rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3);
|
4019
|
+
rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3);
|
4020
|
+
rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3);
|
4021
|
+
|
4022
|
+
/* support propput method that takes an argument */
|
4023
|
+
rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1);
|
4024
|
+
|
4025
|
+
rb_define_method(cWIN32OLE, "ole_free", fole_free, 0);
|
4026
|
+
|
4027
|
+
rb_define_method(cWIN32OLE, "each", fole_each, 0);
|
4028
|
+
rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1);
|
4029
|
+
|
4030
|
+
/* support setproperty method much like Perl ;-) */
|
4031
|
+
rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1);
|
4032
|
+
|
4033
|
+
rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0);
|
4034
|
+
rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0);
|
4035
|
+
rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0);
|
4036
|
+
rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0);
|
4037
|
+
|
4038
|
+
rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1);
|
4039
|
+
rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method");
|
4040
|
+
rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0);
|
4041
|
+
rb_define_method(cWIN32OLE, "ole_type", fole_type, 0);
|
4042
|
+
rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type");
|
4043
|
+
rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0);
|
4044
|
+
rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1);
|
4045
|
+
rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1);
|
4046
|
+
|
4047
|
+
/* Constants definition */
|
4048
|
+
|
4049
|
+
/*
|
4050
|
+
* Version string of WIN32OLE.
|
4051
|
+
*/
|
4052
|
+
rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION));
|
4053
|
+
|
4054
|
+
/*
|
4055
|
+
* After invoking OLE methods with reference arguments, you can access
|
4056
|
+
* the value of arguments by using ARGV.
|
4057
|
+
*
|
4058
|
+
* If the method of OLE(COM) server written by C#.NET is following:
|
4059
|
+
*
|
4060
|
+
* void calcsum(int a, int b, out int c) {
|
4061
|
+
* c = a + b;
|
4062
|
+
* }
|
4063
|
+
*
|
4064
|
+
* then, the Ruby OLE(COM) client script to retrieve the value of
|
4065
|
+
* argument c after invoking calcsum method is following:
|
4066
|
+
*
|
4067
|
+
* a = 10
|
4068
|
+
* b = 20
|
4069
|
+
* c = 0
|
4070
|
+
* comserver.calcsum(a, b, c)
|
4071
|
+
* p c # => 0
|
4072
|
+
* p WIN32OLE::ARGV # => [10, 20, 30]
|
4073
|
+
*
|
4074
|
+
* You can use WIN32OLE_VARIANT object to retrieve the value of reference
|
4075
|
+
* arguments instead of referring WIN32OLE::ARGV.
|
4076
|
+
*
|
4077
|
+
*/
|
4078
|
+
rb_define_const(cWIN32OLE, "ARGV", rb_ary_new());
|
4079
|
+
|
4080
|
+
/*
|
4081
|
+
* 0: ANSI code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
|
4082
|
+
*/
|
4083
|
+
rb_define_const(cWIN32OLE, "CP_ACP", RB_INT2FIX(CP_ACP));
|
4084
|
+
|
4085
|
+
/*
|
4086
|
+
* 1: OEM code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
|
4087
|
+
*/
|
4088
|
+
rb_define_const(cWIN32OLE, "CP_OEMCP", RB_INT2FIX(CP_OEMCP));
|
4089
|
+
|
4090
|
+
/*
|
4091
|
+
* 2
|
4092
|
+
*/
|
4093
|
+
rb_define_const(cWIN32OLE, "CP_MACCP", RB_INT2FIX(CP_MACCP));
|
4094
|
+
|
4095
|
+
/*
|
4096
|
+
* 3: current thread ANSI code page. See WIN32OLE.codepage and
|
4097
|
+
* WIN32OLE.codepage=.
|
4098
|
+
*/
|
4099
|
+
rb_define_const(cWIN32OLE, "CP_THREAD_ACP", RB_INT2FIX(CP_THREAD_ACP));
|
4100
|
+
|
4101
|
+
/*
|
4102
|
+
* 42: symbol code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
|
4103
|
+
*/
|
4104
|
+
rb_define_const(cWIN32OLE, "CP_SYMBOL", RB_INT2FIX(CP_SYMBOL));
|
4105
|
+
|
4106
|
+
/*
|
4107
|
+
* 65000: UTF-7 code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
|
4108
|
+
*/
|
4109
|
+
rb_define_const(cWIN32OLE, "CP_UTF7", RB_INT2FIX(CP_UTF7));
|
4110
|
+
|
4111
|
+
/*
|
4112
|
+
* 65001: UTF-8 code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
|
4113
|
+
*/
|
4114
|
+
rb_define_const(cWIN32OLE, "CP_UTF8", RB_INT2FIX(CP_UTF8));
|
4115
|
+
|
4116
|
+
/*
|
4117
|
+
* 0x0800: default locale for the operating system. See WIN32OLE.locale
|
4118
|
+
* and WIN32OLE.locale=.
|
4119
|
+
*/
|
4120
|
+
rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", RB_INT2FIX(LOCALE_SYSTEM_DEFAULT));
|
4121
|
+
|
4122
|
+
/*
|
4123
|
+
* 0x0400: default locale for the user or process. See WIN32OLE.locale
|
4124
|
+
* and WIN32OLE.locale=.
|
4125
|
+
*/
|
4126
|
+
rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", RB_INT2FIX(LOCALE_USER_DEFAULT));
|
4127
|
+
|
4128
|
+
Init_win32ole_variant_m();
|
4129
|
+
Init_win32ole_typelib();
|
4130
|
+
Init_win32ole_type();
|
4131
|
+
Init_win32ole_variable();
|
4132
|
+
Init_win32ole_method();
|
4133
|
+
Init_win32ole_param();
|
4134
|
+
Init_win32ole_event();
|
4135
|
+
Init_win32ole_variant();
|
4136
|
+
Init_win32ole_record();
|
4137
|
+
Init_win32ole_error();
|
4138
|
+
|
4139
|
+
ole_init_cp();
|
4140
|
+
}
|