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