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