Ruby: ext/win32ole/win32ole.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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