win32ole 1.8.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|