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