Ruby  2.0.0p451(2014-02-24revision45167)
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 "ruby/ruby.h"
19 #include "ruby/st.h"
20 #include "ruby/encoding.h"
21 
22 #define GNUC_OLDER_3_4_4 \
23  ((__GNUC__ < 3) || \
24  ((__GNUC__ <= 3) && (__GNUC_MINOR__ < 4)) || \
25  ((__GNUC__ <= 3) && (__GNUC_MINOR__ <= 4) && (__GNUC_PATCHLEVEL__ <= 4)))
26 
27 #if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
28 #ifndef NONAMELESSUNION
29 #define NONAMELESSUNION 1
30 #endif
31 #endif
32 
33 #include <ctype.h>
34 
35 #include <windows.h>
36 #include <ocidl.h>
37 #include <olectl.h>
38 #include <ole2.h>
39 #if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE)
40 #include <mlang.h>
41 #endif
42 #include <stdlib.h>
43 #include <math.h>
44 #ifdef HAVE_STDARG_PROTOTYPES
45 #include <stdarg.h>
46 #define va_init_list(a,b) va_start(a,b)
47 #else
48 #include <varargs.h>
49 #define va_init_list(a,b) va_start(a)
50 #endif
51 #include <objidl.h>
52 
53 #define DOUT fprintf(stderr,"[%d]\n",__LINE__)
54 #define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x)
55 #define DOUTMSG(x) fprintf(stderr, "[%d]:" #x "\n",__LINE__)
56 #define DOUTI(x) fprintf(stderr, "[%ld]:" #x "=%d\n",__LINE__,x)
57 #define DOUTD(x) fprintf(stderr, "[%d]:" #x "=%f\n",__LINE__,x)
58 
59 #if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
60 #define V_UNION1(X, Y) ((X)->u.Y)
61 #else
62 #define V_UNION1(X, Y) ((X)->Y)
63 #endif
64 
65 #if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
66 #undef V_UNION
67 #define V_UNION(X,Y) ((X)->n1.n2.n3.Y)
68 
69 #undef V_VT
70 #define V_VT(X) ((X)->n1.n2.vt)
71 
72 #undef V_BOOL
73 #define V_BOOL(X) V_UNION(X,boolVal)
74 #endif
75 
76 #ifndef V_I1REF
77 #define V_I1REF(X) V_UNION(X, pcVal)
78 #endif
79 
80 #ifndef V_UI2REF
81 #define V_UI2REF(X) V_UNION(X, puiVal)
82 #endif
83 
84 #ifndef V_INT
85 #define V_INT(X) V_UNION(X, intVal)
86 #endif
87 
88 #ifndef V_INTREF
89 #define V_INTREF(X) V_UNION(X, pintVal)
90 #endif
91 
92 #ifndef V_UINT
93 #define V_UINT(X) V_UNION(X, uintVal)
94 #endif
95 
96 #ifndef V_UINTREF
97 #define V_UINTREF(X) V_UNION(X, puintVal)
98 #endif
99 
100 /*
101  * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a
102  * in Cygwin(mingw32).
103  */
104 #if defined(__CYGWIN__) || defined(__MINGW32__)
105 #undef IID_IMultiLanguage2
106 const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}};
107 #endif
108 
109 #define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
110 
111 #define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
112 
113 #define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y)))
114 #define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y)))
115 
116 #define OLE_FREE(x) {\
117  if(g_ole_initialized == TRUE) {\
118  if(x) {\
119  OLE_RELEASE(x);\
120  (x) = 0;\
121  }\
122  }\
123 }
124 
125 #define OLEData_Get_Struct(obj, pole) {\
126  Data_Get_Struct(obj, struct oledata, pole);\
127  if(!pole->pDispatch) {\
128  rb_raise(rb_eRuntimeError, "failed to get Dispatch Interface");\
129  }\
130 }
131 
132 #ifdef HAVE_LONG_LONG
133 #define I8_2_NUM LL2NUM
134 #define UI8_2_NUM ULL2NUM
135 #define NUM2I8 NUM2LL
136 #define NUM2UI8 NUM2ULL
137 #else
138 #define I8_2_NUM INT2NUM
139 #define UI8_2_NUM UINT2NUM
140 #define NUM2I8 NUM2INT
141 #define NUM2UI8 NUM2UINT
142 #endif
143 
144 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
145 
146 #define WIN32OLE_VERSION "1.5.4"
147 
148 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
149  (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
150 
151 typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile,
152  UINT uCommand, DWORD dwData);
153 typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD);
154 typedef struct {
157 
159 
161  STDMETHOD(QueryInterface)(
162  PEVENTSINK,
163  REFIID,
164  LPVOID *);
165  STDMETHOD_(ULONG, AddRef)(PEVENTSINK);
166  STDMETHOD_(ULONG, Release)(PEVENTSINK);
167 
168  STDMETHOD(GetTypeInfoCount)(
169  PEVENTSINK,
170  UINT *);
171  STDMETHOD(GetTypeInfo)(
172  PEVENTSINK,
173  UINT,
174  LCID,
175  ITypeInfo **);
176  STDMETHOD(GetIDsOfNames)(
177  PEVENTSINK,
178  REFIID,
179  OLECHAR **,
180  UINT,
181  LCID,
182  DISPID *);
183  STDMETHOD(Invoke)(
184  PEVENTSINK,
185  DISPID,
186  REFIID,
187  LCID,
188  WORD,
189  DISPPARAMS *,
190  VARIANT *,
191  EXCEPINFO *,
192  UINT *);
193 };
194 
195 typedef struct tagIEVENTSINKOBJ {
198  IID m_iid;
200  ITypeInfo *pTypeInfo;
202 
214 
216 static ID id_events;
217 #if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__) || defined(__MINGW32__))
218 static RB_THREAD_SPECIFIC BOOL g_ole_initialized;
219 # define g_ole_initialized_init() ((void)0)
220 # define g_ole_initialized_set(val) (g_ole_initialized = (val))
221 #else
222 static volatile DWORD g_ole_initialized_key = TLS_OUT_OF_INDEXES;
223 # define g_ole_initialized (BOOL)TlsGetValue(g_ole_initialized_key)
224 # define g_ole_initialized_init() (g_ole_initialized_key = TlsAlloc())
225 # define g_ole_initialized_set(val) TlsSetValue(g_ole_initialized_key, (void*)(val))
226 #endif
228 static BOOL g_cp_installed = FALSE;
229 static BOOL g_lcid_installed = FALSE;
230 static HINSTANCE ghhctrl = NULL;
231 static HINSTANCE gole32 = NULL;
232 static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL;
234 static IDispatchVtbl com_vtbl;
235 static UINT cWIN32OLE_cp = CP_ACP;
236 static LCID cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT;
238 static UINT g_cp_to_check = CP_ACP;
239 static char g_lcid_to_check[8 + 1];
240 static VARTYPE g_nil_to = VT_ERROR;
242 static IMessageFilterVtbl message_filter;
243 static IMessageFilter imessage_filter = { &message_filter };
244 static IMessageFilter* previous_filter;
245 
246 #if defined(HAVE_TYPE_IMULTILANGUAGE2)
247 static IMultiLanguage2 *pIMultiLanguage = NULL;
248 #elif defined(HAVE_TYPE_IMULTILANGUAGE)
249 static IMultiLanguage *pIMultiLanguage = NULL;
250 #else
251 #define pIMultiLanguage NULL /* dummy */
252 #endif
253 
254 struct oledata {
255  IDispatch *pDispatch;
256 };
257 
259  ITypeLib *pTypeLib;
260 };
261 
262 struct oletypedata {
263  ITypeInfo *pTypeInfo;
264 };
265 
267  ITypeInfo *pOwnerTypeInfo;
268  ITypeInfo *pTypeInfo;
269  UINT index;
270 };
271 
273  ITypeInfo *pTypeInfo;
274  UINT index;
275 };
276 
277 struct oleparamdata {
278  ITypeInfo *pTypeInfo;
280  UINT index;
281 };
282 
283 struct oleeventdata {
285  IConnectionPoint *pConnectionPoint;
286  long event_id;
287 };
288 
289 struct oleparam {
290  DISPPARAMS dp;
291  OLECHAR** pNamedArgs;
292 };
293 
295  VARIANT realvar;
296  VARIANT var;
297 };
298 
299 
300 static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
301 static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This);
302 static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This);
303 static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo);
304 static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
305 static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId);
306 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);
307 static IDispatch* val2dispatch(VALUE val);
308 static double rbtime2vtdate(VALUE tmobj);
309 static VALUE vtdate2rbtime(double date);
310 static rb_encoding *ole_cp2encoding(UINT cp);
311 static UINT ole_encoding2cp(rb_encoding *enc);
312 NORETURN(static void failed_load_conv51932(void));
313 #ifndef pIMultiLanguage
314 static void load_conv_function51932(void);
315 #endif
316 static UINT ole_init_cp(void);
317 static char *ole_wc2mb(LPWSTR pw);
318 static VALUE ole_hresult2msg(HRESULT hr);
319 static void ole_freeexceptinfo(EXCEPINFO *pExInfo);
320 static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo);
321 static void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...);
322 static void ole_initialize(void);
323 static void ole_msg_loop(void);
324 static void ole_free(struct oledata *pole);
325 static void oletypelib_free(struct oletypelibdata *poletypelib);
326 static void oletype_free(struct oletypedata *poletype);
327 static void olemethod_free(struct olemethoddata *polemethod);
328 static void olevariable_free(struct olevariabledata *polevar);
329 static void oleparam_free(struct oleparamdata *pole);
330 static LPWSTR ole_vstr2wc(VALUE vstr);
331 static LPWSTR ole_mb2wc(char *pm, int len);
332 static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree);
333 static VALUE ole_ary_m_entry(VALUE val, long *pid);
334 static void * get_ptr_of_variant(VARIANT *pvar);
335 static VALUE is_all_index_under(long *pid, long *pub, long dim);
336 static void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt);
337 static long dimension(VALUE val);
338 static long ary_len_of_dim(VALUE ary, long dim);
339 static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
340 static void ole_val2variant(VALUE val, VARIANT *var);
341 static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
342 static void ole_val2ptr_variant(VALUE val, VARIANT *var);
343 static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
344 static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
345 static void ole_val2variant2(VALUE val, VARIANT *var);
346 static VALUE make_inspect(const char *class_name, VALUE detail);
347 static VALUE default_inspect(VALUE self, const char *class_name);
348 static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
349 static VALUE fole_s_allocate(VALUE klass);
350 static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
351 static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim);
352 static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val);
353 static VALUE ole_variant2val(VARIANT *pvar);
354 static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey);
355 static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey);
356 static VALUE reg_enum_key(HKEY hkey, DWORD i);
357 static VALUE reg_get_val(HKEY hkey, const char *subkey);
358 static VALUE reg_get_typelib_file_path(HKEY hkey);
361 static VALUE typelib_file(VALUE ole);
362 static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self);
363 static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid);
364 static VALUE ole_create_dcom(int argc, VALUE *argv, VALUE self);
365 static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self);
366 static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self);
367 static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self);
368 static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes);
369 static ULONG reference_count(struct oledata * pole);
370 static VALUE fole_s_reference_count(VALUE self, VALUE obj);
371 static VALUE fole_s_free(VALUE self, VALUE obj);
372 static HWND ole_show_help(VALUE helpfile, VALUE helpcontext);
373 static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self);
374 static VALUE fole_s_get_code_page(VALUE self);
375 static BOOL CALLBACK installed_code_page_proc(LPTSTR str);
376 static BOOL code_page_installed(UINT cp);
377 static VALUE fole_s_set_code_page(VALUE self, VALUE vcp);
378 static VALUE fole_s_get_locale(VALUE self);
379 static BOOL CALLBACK installed_lcid_proc(LPTSTR str);
380 static BOOL lcid_installed(LCID lcid);
381 static VALUE fole_s_set_locale(VALUE self, VALUE vlcid);
382 static VALUE fole_s_create_guid(VALUE self);
383 static VALUE fole_s_ole_initialize(VALUE self);
384 static VALUE fole_s_ole_uninitialize(VALUE self);
385 static VALUE fole_initialize(int argc, VALUE *argv, VALUE self);
386 static VALUE hash2named_arg(VALUE pair, struct oleparam* pOp);
387 static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end);
388 static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket);
389 static VALUE fole_invoke(int argc, VALUE *argv, VALUE self);
390 static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind);
391 static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types);
392 static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
393 static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
395 static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self);
397 static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value);
398 static VALUE fole_free(VALUE self);
399 static VALUE ole_each_sub(VALUE pEnumV);
400 static VALUE ole_ienum_free(VALUE pEnumV);
401 static VALUE fole_each(VALUE self);
402 static VALUE fole_missing(int argc, VALUE *argv, VALUE self);
403 static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name);
404 static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
405 static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask);
406 static VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask);
407 static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti);
408 static VALUE ole_methods(VALUE self, int mask);
409 static VALUE fole_methods(VALUE self);
410 static VALUE fole_get_methods(VALUE self);
411 static VALUE fole_put_methods(VALUE self);
412 static VALUE fole_func_methods(VALUE self);
413 static VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo);
414 static VALUE fole_type(VALUE self);
415 static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo);
416 static VALUE fole_typelib(VALUE self);
417 static VALUE fole_query_interface(VALUE self, VALUE str_iid);
418 static VALUE fole_respond_to(VALUE self, VALUE method);
419 static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
420 static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
421 static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
422 static VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
423 static VALUE fole_method_help(VALUE self, VALUE cmdname);
424 static VALUE fole_activex_initialize(VALUE self);
425 static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib);
426 static VALUE foletype_s_typelibs(VALUE self);
427 static VALUE foletype_s_progids(VALUE self);
428 static VALUE foletype_s_allocate(VALUE klass);
429 static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
430 static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass);
431 static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib);
432 static ITypeLib * oletypelib_get_typelib(VALUE self);
433 static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr);
434 static VALUE foletypelib_s_typelibs(VALUE self);
437 static VALUE oletypelib_search_registry(VALUE self, VALUE typelib);
438 static VALUE foletypelib_s_allocate(VALUE klass);
440 static VALUE foletypelib_guid(VALUE self);
441 static VALUE foletypelib_name(VALUE self);
442 static VALUE foletypelib_version(VALUE self);
445 static VALUE oletypelib_path(VALUE guid, VALUE version);
446 static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib);
447 static VALUE foletypelib_path(VALUE self);
448 static VALUE foletypelib_visible(VALUE self);
450 static VALUE foletypelib_ole_types(VALUE self);
451 static VALUE foletypelib_inspect(VALUE self);
452 static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass);
453 static VALUE foletype_name(VALUE self);
454 static VALUE ole_ole_type(ITypeInfo *pTypeInfo);
455 static VALUE foletype_ole_type(VALUE self);
456 static VALUE ole_type_guid(ITypeInfo *pTypeInfo);
457 static VALUE foletype_guid(VALUE self);
458 static VALUE ole_type_progid(ITypeInfo *pTypeInfo);
459 static VALUE foletype_progid(VALUE self);
460 static VALUE ole_type_visible(ITypeInfo *pTypeInfo);
461 static VALUE foletype_visible(VALUE self);
462 static VALUE ole_type_major_version(ITypeInfo *pTypeInfo);
463 static VALUE foletype_major_version(VALUE self);
464 static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo);
465 static VALUE foletype_minor_version(VALUE self);
466 static VALUE ole_type_typekind(ITypeInfo *pTypeInfo);
467 static VALUE foletype_typekind(VALUE self);
468 static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo);
469 static VALUE foletype_helpstring(VALUE self);
470 static VALUE ole_type_src_type(ITypeInfo *pTypeInfo);
471 static VALUE foletype_src_type(VALUE self);
472 static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo);
473 static VALUE foletype_helpfile(VALUE self);
474 static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo);
475 static VALUE foletype_helpcontext(VALUE self);
476 static VALUE foletype_ole_typelib(VALUE self);
477 static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags);
478 static VALUE foletype_impl_ole_types(VALUE self);
482 static VALUE foletype_inspect(VALUE self);
483 static VALUE ole_variables(ITypeInfo *pTypeInfo);
484 static VALUE foletype_variables(VALUE self);
485 static VALUE foletype_methods(VALUE self);
486 static VALUE folevariable_name(VALUE self);
487 static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index);
488 static VALUE folevariable_ole_type(VALUE self);
489 static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index);
491 static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index);
492 static VALUE folevariable_value(VALUE self);
493 static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index);
494 static VALUE folevariable_visible(VALUE self);
495 static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index);
497 static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index);
498 static VALUE folevariable_varkind(VALUE self);
499 static VALUE folevariable_inspect(VALUE self);
500 static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name);
501 static VALUE folemethod_s_allocate(VALUE klass);
502 static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method);
503 static VALUE folemethod_name(VALUE self);
504 static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index);
505 static VALUE folemethod_return_type(VALUE self);
506 static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index);
507 static VALUE folemethod_return_vtype(VALUE self);
508 static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index);
510 static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index);
511 static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index);
512 static VALUE folemethod_invkind(VALUE self);
513 static VALUE folemethod_invoke_kind(VALUE self);
514 static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index);
515 static VALUE folemethod_visible(VALUE self);
516 static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name);
517 static VALUE folemethod_event(VALUE self);
519 static VALUE ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
520 static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index);
521 static VALUE folemethod_helpstring(VALUE self);
522 static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index);
523 static VALUE folemethod_helpfile(VALUE self);
524 static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index);
525 static VALUE folemethod_helpcontext(VALUE self);
526 static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index);
527 static VALUE folemethod_dispid(VALUE self);
528 static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index);
529 static VALUE folemethod_offset_vtbl(VALUE self);
530 static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index);
531 static VALUE folemethod_size_params(VALUE self);
532 static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index);
534 static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index);
535 static VALUE folemethod_params(VALUE self);
536 static VALUE folemethod_inspect(VALUE self);
537 static VALUE foleparam_s_allocate(VALUE klass);
538 static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index);
539 static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n);
540 static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n);
541 static VALUE foleparam_name(VALUE self);
542 static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
543 static VALUE foleparam_ole_type(VALUE self);
544 static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
546 static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask);
547 static VALUE foleparam_input(VALUE self);
548 static VALUE foleparam_output(VALUE self);
549 static VALUE foleparam_optional(VALUE self);
550 static VALUE foleparam_retval(VALUE self);
551 static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
552 static VALUE foleparam_default(VALUE self);
553 static VALUE foleparam_inspect(VALUE self);
554 static long ole_search_event_at(VALUE ary, VALUE ev);
555 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
556 static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
557 static void ole_delete_event(VALUE ary, VALUE ev);
558 static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
559 static VALUE hash2result(VALUE hash);
560 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
561 static VALUE exec_callback(VALUE arg);
563 static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
564 static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
565 static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
566 static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
567 static void ole_event_free(struct oleeventdata *poleev);
568 static VALUE fev_s_allocate(VALUE klass);
569 static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
570 static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
571 static VALUE fev_s_msg_loop(VALUE klass);
572 static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
573 static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
574 static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
575 static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
576 static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
577 static VALUE fev_unadvise(VALUE self);
578 static VALUE fev_set_handler(VALUE self, VALUE val);
579 static VALUE fev_get_handler(VALUE self);
580 static VALUE evs_push(VALUE ev);
581 static VALUE evs_delete(long i);
582 static VALUE evs_entry(long i);
583 static VALUE evs_length(void);
584 static void olevariant_free(struct olevariantdata *pvar);
585 static VALUE folevariant_s_allocate(VALUE klass);
586 static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
588 static long *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
589 static void unlock_safe_array(SAFEARRAY *psa);
590 static SAFEARRAY *get_locked_safe_array(VALUE val);
591 static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
592 static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
593 static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
594 static VALUE folevariant_value(VALUE self);
595 static VALUE folevariant_vartype(VALUE self);
597 static void init_enc2cp(void);
598 static void free_enc2cp(void);
599 
600 static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
601  IMessageFilter __RPC_FAR * This,
602  /* [in] */ REFIID riid,
603  /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
604 {
605  if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
606  || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0)
607  {
609  return S_OK;
610  }
611  return E_NOINTERFACE;
612 }
613 
614 static ULONG (STDMETHODCALLTYPE mf_AddRef)(
615  IMessageFilter __RPC_FAR * This)
616 {
617  return 1;
618 }
619 
620 static ULONG (STDMETHODCALLTYPE mf_Release)(
621  IMessageFilter __RPC_FAR * This)
622 {
623  return 1;
624 }
625 
626 static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)(
627  IMessageFilter __RPC_FAR * pThis,
628  DWORD dwCallType, //Type of incoming call
629  HTASK threadIDCaller, //Task handle calling this task
630  DWORD dwTickCount, //Elapsed tick count
631  LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure
632  )
633 {
634 #ifdef DEBUG_MESSAGEFILTER
635  printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount);
636  fflush(stdout);
637 #endif
638  switch (dwCallType)
639  {
640  case CALLTYPE_ASYNC:
641  case CALLTYPE_TOPLEVEL_CALLPENDING:
642  case CALLTYPE_ASYNC_CALLPENDING:
643  if (rb_during_gc()) {
644  return SERVERCALL_RETRYLATER;
645  }
646  break;
647  default:
648  break;
649  }
650  if (previous_filter) {
651  return previous_filter->lpVtbl->HandleInComingCall(previous_filter,
652  dwCallType,
653  threadIDCaller,
654  dwTickCount,
656  }
657  return SERVERCALL_ISHANDLED;
658 }
659 
660 static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)(
661  IMessageFilter* pThis,
662  HTASK threadIDCallee, //Server task handle
663  DWORD dwTickCount, //Elapsed tick count
664  DWORD dwRejectType //Returned rejection message
665  )
666 {
667  if (previous_filter) {
668  return previous_filter->lpVtbl->RetryRejectedCall(previous_filter,
669  threadIDCallee,
670  dwTickCount,
671  dwRejectType);
672  }
673  return 1000;
674 }
675 
676 static DWORD (STDMETHODCALLTYPE mf_MessagePending)(
677  IMessageFilter* pThis,
678  HTASK threadIDCallee, //Called applications task handle
679  DWORD dwTickCount, //Elapsed tick count
680  DWORD dwPendingType //Call type
681  )
682 {
683  if (rb_during_gc()) {
684  return PENDINGMSG_WAITNOPROCESS;
685  }
686  if (previous_filter) {
687  return previous_filter->lpVtbl->MessagePending(previous_filter,
688  threadIDCallee,
689  dwTickCount,
690  dwPendingType);
691  }
692  return PENDINGMSG_WAITNOPROCESS;
693 }
694 
695 typedef struct _Win32OLEIDispatch
696 {
697  IDispatch dispatch;
701 
702 static HRESULT ( STDMETHODCALLTYPE QueryInterface )(
703  IDispatch __RPC_FAR * This,
704  /* [in] */ REFIID riid,
705  /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
706 {
707  if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
708  || MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0)
709  {
711  p->refcount++;
712  *ppvObject = This;
713  return S_OK;
714  }
715  return E_NOINTERFACE;
716 }
717 
718 static ULONG ( STDMETHODCALLTYPE AddRef )(
719  IDispatch __RPC_FAR * This)
720 {
722  return ++(p->refcount);
723 }
724 
725 static ULONG ( STDMETHODCALLTYPE Release )(
726  IDispatch __RPC_FAR * This)
727 {
729  ULONG u = --(p->refcount);
730  if (u == 0) {
731  st_data_t key = p->obj;
732  st_delete(DATA_PTR(com_hash), &key, 0);
733  free(p);
734  }
735  return u;
736 }
737 
738 static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(
739  IDispatch __RPC_FAR * This,
740  /* [out] */ UINT __RPC_FAR *pctinfo)
741 {
742  return E_NOTIMPL;
743 }
744 
745 static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(
746  IDispatch __RPC_FAR * This,
747  /* [in] */ UINT iTInfo,
748  /* [in] */ LCID lcid,
749  /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
750 {
751  return E_NOTIMPL;
752 }
753 
754 
755 static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(
756  IDispatch __RPC_FAR * This,
757  /* [in] */ REFIID riid,
758  /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
759  /* [in] */ UINT cNames,
760  /* [in] */ LCID lcid,
761  /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
762 {
763  /*
764  Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
765  */
766  char* psz = ole_wc2mb(*rgszNames); // support only one method
767  *rgDispId = rb_intern(psz);
768  free(psz);
769  return S_OK;
770 }
771 
772 static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )(
773  IDispatch __RPC_FAR * This,
774  /* [in] */ DISPID dispIdMember,
775  /* [in] */ REFIID riid,
776  /* [in] */ LCID lcid,
777  /* [in] */ WORD wFlags,
778  /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
779  /* [out] */ VARIANT __RPC_FAR *pVarResult,
780  /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
781  /* [out] */ UINT __RPC_FAR *puArgErr)
782 {
783  VALUE v;
784  int i;
785  int args = pDispParams->cArgs;
788  for (i = 0; i < args; i++) {
789  *(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]);
790  }
791  if (dispIdMember == DISPID_VALUE) {
792  if (wFlags == DISPATCH_METHOD) {
793  dispIdMember = rb_intern("call");
794  } else if (wFlags & DISPATCH_PROPERTYGET) {
795  dispIdMember = rb_intern("value");
796  }
797  }
798  v = rb_funcall2(p->obj, dispIdMember, args, parg);
799  ole_val2variant(v, pVarResult);
800  return S_OK;
801 }
802 
803 static IDispatch*
805 {
806  struct st_table *tbl = DATA_PTR(com_hash);
807  Win32OLEIDispatch* pdisp;
808  st_data_t data;
809 
810  if (st_lookup(tbl, val, &data)) {
811  pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG);
812  pdisp->refcount++;
813  }
814  else {
815  pdisp = ALLOC(Win32OLEIDispatch);
816  pdisp->dispatch.lpVtbl = &com_vtbl;
817  pdisp->refcount = 1;
818  pdisp->obj = val;
819  st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG);
820  }
821  return &pdisp->dispatch;
822 }
823 
824 static double
826 {
827  SYSTEMTIME st;
828  double t = 0;
829  memset(&st, 0, sizeof(SYSTEMTIME));
830  st.wYear = FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0));
831  st.wMonth = FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0));
832  st.wDay = FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0));
833  st.wHour = FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0));
834  st.wMinute = FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0));
835  st.wSecond = FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0));
836  st.wMilliseconds = FIX2INT(rb_funcall(tmobj, rb_intern("nsec"), 0)) / 1000000;
837  SystemTimeToVariantTime(&st, &t);
838  return t;
839 }
840 
841 static VALUE
842 vtdate2rbtime(double date)
843 {
844  SYSTEMTIME st;
845  VALUE v;
846  VariantTimeToSystemTime(date, &st);
847 
848  v = rb_funcall(rb_cTime, rb_intern("new"), 6,
849  INT2FIX(st.wYear),
850  INT2FIX(st.wMonth),
851  INT2FIX(st.wDay),
852  INT2FIX(st.wHour),
853  INT2FIX(st.wMinute),
854  INT2FIX(st.wSecond));
855  if (st.wMilliseconds > 0) {
856  return rb_funcall(v, rb_intern("+"), 1, rb_float_new((double)(st.wMilliseconds / 1000.0)));
857  }
858  return v;
859 }
860 
861 #define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp
862 
863 static UINT ole_encoding2cp(rb_encoding *enc)
864 {
865  /*
866  * Is there any better solution to convert
867  * Ruby encoding to Windows codepage???
868  */
869  ENC_MACHING_CP(enc, "Big5", 950);
870  ENC_MACHING_CP(enc, "CP51932", 51932);
871  ENC_MACHING_CP(enc, "CP850", 850);
872  ENC_MACHING_CP(enc, "CP852", 852);
873  ENC_MACHING_CP(enc, "CP855", 855);
874  ENC_MACHING_CP(enc, "CP949", 949);
875  ENC_MACHING_CP(enc, "EUC-JP", 20932);
876  ENC_MACHING_CP(enc, "EUC-KR", 51949);
877  ENC_MACHING_CP(enc, "EUC-TW", 51950);
878  ENC_MACHING_CP(enc, "GB18030", 54936);
879  ENC_MACHING_CP(enc, "GB2312", 20936);
880  ENC_MACHING_CP(enc, "GBK", 936);
881  ENC_MACHING_CP(enc, "IBM437", 437);
882  ENC_MACHING_CP(enc, "IBM737", 737);
883  ENC_MACHING_CP(enc, "IBM775", 775);
884  ENC_MACHING_CP(enc, "IBM852", 852);
885  ENC_MACHING_CP(enc, "IBM855", 855);
886  ENC_MACHING_CP(enc, "IBM857", 857);
887  ENC_MACHING_CP(enc, "IBM860", 860);
888  ENC_MACHING_CP(enc, "IBM861", 861);
889  ENC_MACHING_CP(enc, "IBM862", 862);
890  ENC_MACHING_CP(enc, "IBM863", 863);
891  ENC_MACHING_CP(enc, "IBM864", 864);
892  ENC_MACHING_CP(enc, "IBM865", 865);
893  ENC_MACHING_CP(enc, "IBM866", 866);
894  ENC_MACHING_CP(enc, "IBM869", 869);
895  ENC_MACHING_CP(enc, "ISO-2022-JP", 50220);
896  ENC_MACHING_CP(enc, "ISO-8859-1", 28591);
897  ENC_MACHING_CP(enc, "ISO-8859-15", 28605);
898  ENC_MACHING_CP(enc, "ISO-8859-2", 28592);
899  ENC_MACHING_CP(enc, "ISO-8859-3", 28593);
900  ENC_MACHING_CP(enc, "ISO-8859-4", 28594);
901  ENC_MACHING_CP(enc, "ISO-8859-5", 28595);
902  ENC_MACHING_CP(enc, "ISO-8859-6", 28596);
903  ENC_MACHING_CP(enc, "ISO-8859-7", 28597);
904  ENC_MACHING_CP(enc, "ISO-8859-8", 28598);
905  ENC_MACHING_CP(enc, "ISO-8859-9", 28599);
906  ENC_MACHING_CP(enc, "KOI8-R", 20866);
907  ENC_MACHING_CP(enc, "KOI8-U", 21866);
908  ENC_MACHING_CP(enc, "Shift_JIS", 932);
909  ENC_MACHING_CP(enc, "UTF-16BE", 1201);
910  ENC_MACHING_CP(enc, "UTF-16LE", 1200);
911  ENC_MACHING_CP(enc, "UTF-7", 65000);
912  ENC_MACHING_CP(enc, "UTF-8", 65001);
913  ENC_MACHING_CP(enc, "Windows-1250", 1250);
914  ENC_MACHING_CP(enc, "Windows-1251", 1251);
915  ENC_MACHING_CP(enc, "Windows-1252", 1252);
916  ENC_MACHING_CP(enc, "Windows-1253", 1253);
917  ENC_MACHING_CP(enc, "Windows-1254", 1254);
918  ENC_MACHING_CP(enc, "Windows-1255", 1255);
919  ENC_MACHING_CP(enc, "Windows-1256", 1256);
920  ENC_MACHING_CP(enc, "Windows-1257", 1257);
921  ENC_MACHING_CP(enc, "Windows-1258", 1258);
922  ENC_MACHING_CP(enc, "Windows-31J", 932);
923  ENC_MACHING_CP(enc, "Windows-874", 874);
924  ENC_MACHING_CP(enc, "eucJP-ms", 20932);
925  return CP_ACP;
926 }
927 
928 static void
930 {
931  rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932");
932 }
933 
934 #ifndef pIMultiLanguage
935 static void
937 {
938  HRESULT hr = E_NOINTERFACE;
939  void *p;
940  if (!pIMultiLanguage) {
941 #if defined(HAVE_TYPE_IMULTILANGUAGE2)
942  hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
943  &IID_IMultiLanguage2, &p);
944 #elif defined(HAVE_TYPE_IMULTILANGUAGE)
945  hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
946  &IID_IMultiLanguage, &p);
947 #endif
948  if (FAILED(hr)) {
950  }
951  pIMultiLanguage = p;
952  }
953 }
954 #else
955 #define load_conv_function51932() failed_load_conv51932()
956 #endif
957 
958 #define conv_51932(cp) ((cp) == 51932 && (load_conv_function51932(), 1))
959 
960 static void
962 {
963  if (code_page_installed(cp)) {
964  cWIN32OLE_cp = cp;
965  } else {
966  switch(cp) {
967  case CP_ACP:
968  case CP_OEMCP:
969  case CP_MACCP:
970  case CP_THREAD_ACP:
971  case CP_SYMBOL:
972  case CP_UTF7:
973  case CP_UTF8:
974  cWIN32OLE_cp = cp;
975  break;
976  case 51932:
977  cWIN32OLE_cp = cp;
979  break;
980  default:
981  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.");
982  break;
983  }
984  }
985  cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
986 }
987 
988 
989 static UINT
991 {
992  UINT cp;
993  rb_encoding *encdef;
994  encdef = rb_default_internal_encoding();
995  if (!encdef) {
996  encdef = rb_default_external_encoding();
997  }
998  cp = ole_encoding2cp(encdef);
999  set_ole_codepage(cp);
1000  return cp;
1001 }
1002 
1003 struct myCPINFOEX {
1005  BYTE DefaultChar[2];
1006  BYTE LeadByte[12];
1008  UINT CodePage;
1009  char CodePageName[MAX_PATH];
1010 };
1011 
1012 static rb_encoding *
1014 {
1015  static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL;
1016  struct myCPINFOEX* buf;
1017  VALUE enc_name;
1018  char *enc_cstr;
1019  int idx;
1020 
1021  if (!code_page_installed(cp)) {
1022  switch(cp) {
1023  case CP_ACP:
1024  cp = GetACP();
1025  break;
1026  case CP_OEMCP:
1027  cp = GetOEMCP();
1028  break;
1029  case CP_MACCP:
1030  case CP_THREAD_ACP:
1031  if (!pGetCPInfoEx) {
1032  pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
1033  GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
1034  if (!pGetCPInfoEx) {
1035  pGetCPInfoEx = (void*)-1;
1036  }
1037  }
1038  buf = ALLOCA_N(struct myCPINFOEX, 1);
1039  ZeroMemory(buf, sizeof(struct myCPINFOEX));
1040  if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
1041  rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
1042  break; /* never reach here */
1043  }
1044  cp = buf->CodePage;
1045  break;
1046  case CP_SYMBOL:
1047  case CP_UTF7:
1048  case CP_UTF8:
1049  break;
1050  case 51932:
1052  break;
1053  default:
1054  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.");
1055  break;
1056  }
1057  }
1058 
1059  enc_name = rb_sprintf("CP%d", cp);
1060  idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name));
1061  if (idx < 0)
1062  idx = rb_define_dummy_encoding(enc_cstr);
1063  return rb_enc_from_index(idx);
1064 }
1065 
1066 static char *
1067 ole_wc2mb(LPWSTR pw)
1068 {
1069  LPSTR pm;
1070  UINT size = 0;
1071  if (conv_51932(cWIN32OLE_cp)) {
1072 #ifndef pIMultiLanguage
1073  DWORD dw = 0;
1074  HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
1075  &dw, cWIN32OLE_cp, pw, NULL, NULL, &size);
1076  if (FAILED(hr)) {
1077  ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
1078  }
1079  pm = ALLOC_N(char, size + 1);
1080  hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
1081  &dw, cWIN32OLE_cp, pw, NULL, pm, &size);
1082  if (FAILED(hr)) {
1083  ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
1084  }
1085  pm[size] = '\0';
1086 #endif
1087  return pm;
1088  }
1089  size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL);
1090  if (size) {
1091  pm = ALLOC_N(char, size + 1);
1092  WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, pm, size, NULL, NULL);
1093  pm[size] = '\0';
1094  }
1095  else {
1096  pm = ALLOC_N(char, 1);
1097  *pm = '\0';
1098  }
1099  return pm;
1100 }
1101 
1102 static VALUE
1104 {
1105  VALUE msg = Qnil;
1106  char *p_msg = NULL;
1107  char *term = NULL;
1108  DWORD dwCount;
1109 
1110  char strhr[100];
1111  sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr);
1112  msg = rb_str_new2(strhr);
1113  dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1114  FORMAT_MESSAGE_FROM_SYSTEM |
1115  FORMAT_MESSAGE_IGNORE_INSERTS,
1116  NULL, hr,
1117  MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
1118  (LPTSTR)&p_msg, 0, NULL);
1119  if (dwCount == 0) {
1120  dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1121  FORMAT_MESSAGE_FROM_SYSTEM |
1122  FORMAT_MESSAGE_IGNORE_INSERTS,
1123  NULL, hr, cWIN32OLE_lcid,
1124  (LPTSTR)&p_msg, 0, NULL);
1125  }
1126  if (dwCount > 0) {
1127  term = p_msg + strlen(p_msg);
1128  while (p_msg < term) {
1129  term--;
1130  if (*term == '\r' || *term == '\n')
1131  *term = '\0';
1132  else break;
1133  }
1134  if (p_msg[0] != '\0') {
1135  rb_str_cat2(msg, p_msg);
1136  }
1137  }
1138  LocalFree(p_msg);
1139  return msg;
1140 }
1141 
1142 static void
1143 ole_freeexceptinfo(EXCEPINFO *pExInfo)
1144 {
1145  SysFreeString(pExInfo->bstrDescription);
1146  SysFreeString(pExInfo->bstrSource);
1147  SysFreeString(pExInfo->bstrHelpFile);
1148 }
1149 
1150 static VALUE
1151 ole_excepinfo2msg(EXCEPINFO *pExInfo)
1152 {
1153  char error_code[40];
1154  char *pSource = NULL;
1155  char *pDescription = NULL;
1156  VALUE error_msg;
1157  if(pExInfo->pfnDeferredFillIn != NULL) {
1158  (*pExInfo->pfnDeferredFillIn)(pExInfo);
1159  }
1160  if (pExInfo->bstrSource != NULL) {
1161  pSource = ole_wc2mb(pExInfo->bstrSource);
1162  }
1163  if (pExInfo->bstrDescription != NULL) {
1164  pDescription = ole_wc2mb(pExInfo->bstrDescription);
1165  }
1166  if(pExInfo->wCode == 0) {
1167  sprintf(error_code, "\n OLE error code:%lX in ", pExInfo->scode);
1168  }
1169  else{
1170  sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode);
1171  }
1172  error_msg = rb_str_new2(error_code);
1173  if(pSource != NULL) {
1174  rb_str_cat(error_msg, pSource, strlen(pSource));
1175  }
1176  else {
1177  rb_str_cat(error_msg, "<Unknown>", 9);
1178  }
1179  rb_str_cat2(error_msg, "\n ");
1180  if(pDescription != NULL) {
1181  rb_str_cat2(error_msg, pDescription);
1182  }
1183  else {
1184  rb_str_cat2(error_msg, "<No Description>");
1185  }
1186  if(pSource) free(pSource);
1187  if(pDescription) free(pDescription);
1188  ole_freeexceptinfo(pExInfo);
1189  return error_msg;
1190 }
1191 
1192 static void
1193 ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...)
1194 {
1195  va_list args;
1196  VALUE msg;
1197  VALUE err_msg;
1198  va_init_list(args, fmt);
1199  msg = rb_vsprintf(fmt, args);
1200  va_end(args);
1201 
1202  err_msg = ole_hresult2msg(hr);
1203  if(err_msg != Qnil) {
1204  rb_str_cat2(msg, "\n");
1205  rb_str_append(msg, err_msg);
1206  }
1207  rb_exc_raise(rb_exc_new3(ecs, msg));
1208 }
1209 
1210 void
1212 {
1213  if (!g_ole_initialized) return;
1214  OleUninitialize();
1216 }
1217 
1218 static void
1219 ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
1220 {
1221  ole_uninitialize();
1222 }
1223 
1224 static void
1226 {
1227  HRESULT hr;
1228 
1229  if(!g_uninitialize_hooked) {
1232  }
1233 
1234  if(g_ole_initialized == FALSE) {
1235  hr = OleInitialize(NULL);
1236  if(FAILED(hr)) {
1237  ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize");
1238  }
1240 
1241  hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter);
1242  if(FAILED(hr)) {
1244  ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter");
1245  }
1246  }
1247 }
1248 
1249 static void
1251  MSG msg;
1252  while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
1253  TranslateMessage(&msg);
1254  DispatchMessage(&msg);
1255  }
1256 }
1257 
1258 static void
1259 ole_free(struct oledata *pole)
1260 {
1261  OLE_FREE(pole->pDispatch);
1262  free(pole);
1263 }
1264 
1265 static void
1266 oletypelib_free(struct oletypelibdata *poletypelib)
1267 {
1268  OLE_FREE(poletypelib->pTypeLib);
1269  free(poletypelib);
1270 }
1271 
1272 static void
1273 oletype_free(struct oletypedata *poletype)
1274 {
1275  OLE_FREE(poletype->pTypeInfo);
1276  free(poletype);
1277 }
1278 
1279 static void
1280 olemethod_free(struct olemethoddata *polemethod)
1281 {
1282  OLE_FREE(polemethod->pTypeInfo);
1283  OLE_FREE(polemethod->pOwnerTypeInfo);
1284  free(polemethod);
1285 }
1286 
1287 static void
1289 {
1290  OLE_FREE(polevar->pTypeInfo);
1291  free(polevar);
1292 }
1293 
1294 static void
1296 {
1297  OLE_FREE(pole->pTypeInfo);
1298  free(pole);
1299 }
1300 
1301 
1302 static LPWSTR
1304 {
1305  rb_encoding *enc;
1306  int cp;
1307  UINT size = 0;
1308  LPWSTR pw;
1309  st_data_t data;
1310  enc = rb_enc_get(vstr);
1311 
1312  if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) {
1313  cp = data;
1314  } else {
1315  cp = ole_encoding2cp(enc);
1316  if (code_page_installed(cp) ||
1317  cp == CP_ACP ||
1318  cp == CP_OEMCP ||
1319  cp == CP_MACCP ||
1320  cp == CP_THREAD_ACP ||
1321  cp == CP_SYMBOL ||
1322  cp == CP_UTF7 ||
1323  cp == CP_UTF8 ||
1324  cp == 51932) {
1325  st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp);
1326  } else {
1327  rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
1328  }
1329  }
1330  if (conv_51932(cp)) {
1331 #ifndef pIMultiLanguage
1332  DWORD dw = 0;
1333  UINT len = RSTRING_LENINT(vstr);
1334  HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
1335  &dw, cp, RSTRING_PTR(vstr), &len, NULL, &size);
1336  if (FAILED(hr)) {
1337  ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
1338  }
1339  pw = SysAllocStringLen(NULL, size);
1340  len = RSTRING_LEN(vstr);
1341  hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
1342  &dw, cp, RSTRING_PTR(vstr), &len, pw, &size);
1343  if (FAILED(hr)) {
1344  ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
1345  }
1346 #endif
1347  return pw;
1348  }
1349  size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0);
1350  pw = SysAllocStringLen(NULL, size);
1351  MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size);
1352  return pw;
1353 }
1354 
1355 static LPWSTR
1356 ole_mb2wc(char *pm, int len)
1357 {
1358  UINT size = 0;
1359  LPWSTR pw;
1360 
1361  if (conv_51932(cWIN32OLE_cp)) {
1362 #ifndef pIMultiLanguage
1363  DWORD dw = 0;
1364  UINT n = len;
1365  HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
1366  &dw, cWIN32OLE_cp, pm, &n, NULL, &size);
1367  if (FAILED(hr)) {
1368  ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
1369  }
1370  pw = SysAllocStringLen(NULL, size);
1371  hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
1372  &dw, cWIN32OLE_cp, pm, &n, pw, &size);
1373  if (FAILED(hr)) {
1374  ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
1375  }
1376 #endif
1377  return pw;
1378  }
1379  size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0);
1380  pw = SysAllocStringLen(NULL, size - 1);
1381  MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size);
1382  return pw;
1383 }
1384 
1385 static VALUE
1386 ole_wc2vstr(LPWSTR pw, BOOL isfree)
1387 {
1388  char *p = ole_wc2mb(pw);
1389  VALUE vstr = rb_enc_str_new(p, strlen(p), cWIN32OLE_enc);
1390  if(isfree)
1391  SysFreeString(pw);
1392  free(p);
1393  return vstr;
1394 }
1395 
1396 static VALUE
1398 {
1399  VALUE obj = Qnil;
1400  int i = 0;
1401  obj = val;
1402  while(TYPE(obj) == T_ARRAY) {
1403  obj = rb_ary_entry(obj, pid[i]);
1404  i++;
1405  }
1406  return obj;
1407 }
1408 
1409 static void *
1410 get_ptr_of_variant(VARIANT *pvar)
1411 {
1412  switch(V_VT(pvar)) {
1413  case VT_UI1:
1414  return &V_UI1(pvar);
1415  break;
1416  case VT_I2:
1417  return &V_I2(pvar);
1418  break;
1419  case VT_UI2:
1420  return &V_UI2(pvar);
1421  break;
1422  case VT_I4:
1423  return &V_I4(pvar);
1424  break;
1425  case VT_UI4:
1426  return &V_UI4(pvar);
1427  break;
1428  case VT_R4:
1429  return &V_R4(pvar);
1430  break;
1431  case VT_R8:
1432  return &V_R8(pvar);
1433  break;
1434 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1435  case VT_I8:
1436  return &V_I8(pvar);
1437  break;
1438  case VT_UI8:
1439  return &V_UI8(pvar);
1440  break;
1441 #endif
1442  case VT_INT:
1443  return &V_INT(pvar);
1444  break;
1445  case VT_UINT:
1446  return &V_UINT(pvar);
1447  break;
1448  case VT_CY:
1449  return &V_CY(pvar);
1450  break;
1451  case VT_DATE:
1452  return &V_DATE(pvar);
1453  break;
1454  case VT_BSTR:
1455  return V_BSTR(pvar);
1456  break;
1457  case VT_DISPATCH:
1458  return V_DISPATCH(pvar);
1459  break;
1460  case VT_ERROR:
1461  return &V_ERROR(pvar);
1462  break;
1463  case VT_BOOL:
1464  return &V_BOOL(pvar);
1465  break;
1466  case VT_UNKNOWN:
1467  return V_UNKNOWN(pvar);
1468  break;
1469  case VT_ARRAY:
1470  return &V_ARRAY(pvar);
1471  break;
1472  default:
1473  return NULL;
1474  break;
1475  }
1476 }
1477 
1478 static VALUE
1479 is_all_index_under(long *pid, long *pub, long dim)
1480 {
1481  long i = 0;
1482  for (i = 0; i < dim; i++) {
1483  if (pid[i] > pub[i]) {
1484  return Qfalse;
1485  }
1486  }
1487  return Qtrue;
1488 }
1489 
1490 static void
1491 ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt)
1492 {
1493  VALUE val1;
1494  HRESULT hr = S_OK;
1495  VARIANT var;
1496  VOID *p = NULL;
1497  long i = n;
1498  while(i >= 0) {
1499  val1 = ole_ary_m_entry(val, pid);
1500  VariantInit(&var);
1501  p = val2variant_ptr(val1, &var, vt);
1502  if (is_all_index_under(pid, pub, dim) == Qtrue) {
1503  if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
1504  (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
1505  rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface");
1506  }
1507  hr = SafeArrayPutElement(psa, pid, p);
1508  }
1509  if (FAILED(hr)) {
1510  ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement");
1511  }
1512  pid[i] += 1;
1513  if (pid[i] > pub[i]) {
1514  pid[i] = 0;
1515  i -= 1;
1516  } else {
1517  i = dim - 1;
1518  }
1519  }
1520 }
1521 
1522 static long
1524  long dim = 0;
1525  long dim1 = 0;
1526  long len = 0;
1527  long i = 0;
1528  if (TYPE(val) == T_ARRAY) {
1529  len = RARRAY_LEN(val);
1530  for (i = 0; i < len; i++) {
1531  dim1 = dimension(rb_ary_entry(val, i));
1532  if (dim < dim1) {
1533  dim = dim1;
1534  }
1535  }
1536  dim += 1;
1537  }
1538  return dim;
1539 }
1540 
1541 static long
1542 ary_len_of_dim(VALUE ary, long dim) {
1543  long ary_len = 0;
1544  long ary_len1 = 0;
1545  long len = 0;
1546  long i = 0;
1547  VALUE val;
1548  if (dim == 0) {
1549  if (TYPE(ary) == T_ARRAY) {
1550  ary_len = RARRAY_LEN(ary);
1551  }
1552  } else {
1553  if (TYPE(ary) == T_ARRAY) {
1554  len = RARRAY_LEN(ary);
1555  for (i = 0; i < len; i++) {
1556  val = rb_ary_entry(ary, i);
1557  ary_len1 = ary_len_of_dim(val, dim-1);
1558  if (ary_len < ary_len1) {
1559  ary_len = ary_len1;
1560  }
1561  }
1562  }
1563  }
1564  return ary_len;
1565 }
1566 
1567 static HRESULT
1568 ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
1569 {
1570  long dim = 0;
1571  int i = 0;
1572  HRESULT hr = S_OK;
1573 
1574  SAFEARRAYBOUND *psab = NULL;
1575  SAFEARRAY *psa = NULL;
1576  long *pub, *pid;
1577 
1578  Check_Type(val, T_ARRAY);
1579 
1580  dim = dimension(val);
1581 
1582  psab = ALLOC_N(SAFEARRAYBOUND, dim);
1583  pub = ALLOC_N(long, dim);
1584  pid = ALLOC_N(long, dim);
1585 
1586  if(!psab || !pub || !pid) {
1587  if(pub) free(pub);
1588  if(psab) free(psab);
1589  if(pid) free(pid);
1590  rb_raise(rb_eRuntimeError, "memory allocation error");
1591  }
1592 
1593  for (i = 0; i < dim; i++) {
1594  psab[i].cElements = ary_len_of_dim(val, i);
1595  psab[i].lLbound = 0;
1596  pub[i] = psab[i].cElements - 1;
1597  pid[i] = 0;
1598  }
1599  /* Create and fill VARIANT array */
1600  if ((vt & ~VT_BYREF) == VT_ARRAY) {
1601  vt = (vt | VT_VARIANT);
1602  }
1603  psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
1604  if (psa == NULL)
1605  hr = E_OUTOFMEMORY;
1606  else
1607  hr = SafeArrayLock(psa);
1608  if (SUCCEEDED(hr)) {
1609  ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK));
1610  hr = SafeArrayUnlock(psa);
1611  }
1612 
1613  if(pub) free(pub);
1614  if(psab) free(psab);
1615  if(pid) free(pid);
1616 
1617  if (SUCCEEDED(hr)) {
1618  V_VT(var) = vt;
1619  V_ARRAY(var) = psa;
1620  }
1621  else {
1622  if (psa != NULL)
1623  SafeArrayDestroy(psa);
1624  }
1625  return hr;
1626 }
1627 
1628 static void
1629 ole_val2variant(VALUE val, VARIANT *var)
1630 {
1631  struct oledata *pole;
1632  struct olevariantdata *pvar;
1633  if(rb_obj_is_kind_of(val, cWIN32OLE)) {
1634  Data_Get_Struct(val, struct oledata, pole);
1635  OLE_ADDREF(pole->pDispatch);
1636  V_VT(var) = VT_DISPATCH;
1637  V_DISPATCH(var) = pole->pDispatch;
1638  return;
1639  }
1641  Data_Get_Struct(val, struct olevariantdata, pvar);
1642  VariantCopy(var, &(pvar->var));
1643  return;
1644  }
1645 
1646  if (rb_obj_is_kind_of(val, rb_cTime)) {
1647  V_VT(var) = VT_DATE;
1648  V_DATE(var) = rbtime2vtdate(val);
1649  return;
1650  }
1651  switch (TYPE(val)) {
1652  case T_ARRAY:
1653  ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY);
1654  break;
1655  case T_STRING:
1656  V_VT(var) = VT_BSTR;
1657  V_BSTR(var) = ole_vstr2wc(val);
1658  break;
1659  case T_FIXNUM:
1660  V_VT(var) = VT_I4;
1661  V_I4(var) = NUM2INT(val);
1662  break;
1663  case T_BIGNUM:
1664  V_VT(var) = VT_R8;
1665  V_R8(var) = rb_big2dbl(val);
1666  break;
1667  case T_FLOAT:
1668  V_VT(var) = VT_R8;
1669  V_R8(var) = NUM2DBL(val);
1670  break;
1671  case T_TRUE:
1672  V_VT(var) = VT_BOOL;
1673  V_BOOL(var) = VARIANT_TRUE;
1674  break;
1675  case T_FALSE:
1676  V_VT(var) = VT_BOOL;
1677  V_BOOL(var) = VARIANT_FALSE;
1678  break;
1679  case T_NIL:
1680  if (g_nil_to == VT_ERROR) {
1681  V_VT(var) = VT_ERROR;
1682  V_ERROR(var) = DISP_E_PARAMNOTFOUND;
1683  }else {
1684  V_VT(var) = VT_EMPTY;
1685  }
1686  break;
1687  default:
1688  V_VT(var) = VT_DISPATCH;
1689  V_DISPATCH(var) = val2dispatch(val);
1690  break;
1691  }
1692 }
1693 
1694 static void
1695 ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
1696 {
1697  if (val == Qnil) {
1698  if (vt == VT_VARIANT) {
1699  ole_val2variant2(val, var);
1700  } else {
1701  V_VT(var) = (vt & ~VT_BYREF);
1702  if (V_VT(var) == VT_DISPATCH) {
1703  V_DISPATCH(var) = NULL;
1704  } else if (V_VT(var) == VT_UNKNOWN) {
1705  V_UNKNOWN(var) = NULL;
1706  }
1707  }
1708  return;
1709  }
1710 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1711  switch(vt & ~VT_BYREF) {
1712  case VT_I8:
1713  V_VT(var) = VT_I8;
1714  V_I8(var) = NUM2I8 (val);
1715  break;
1716  case VT_UI8:
1717  V_VT(var) = VT_UI8;
1718  V_UI8(var) = NUM2UI8(val);
1719  break;
1720  default:
1721  ole_val2variant2(val, var);
1722  break;
1723  }
1724 #else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
1725  ole_val2variant2(val, var);
1726 #endif
1727 }
1728 
1729 static void
1731 {
1732  switch (TYPE(val)) {
1733  case T_STRING:
1734  if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
1735  *V_BSTRREF(var) = ole_vstr2wc(val);
1736  }
1737  break;
1738  case T_FIXNUM:
1739  switch(V_VT(var)) {
1740  case (VT_UI1 | VT_BYREF) :
1741  *V_UI1REF(var) = NUM2CHR(val);
1742  break;
1743  case (VT_I2 | VT_BYREF) :
1744  *V_I2REF(var) = (short)NUM2INT(val);
1745  break;
1746  case (VT_I4 | VT_BYREF) :
1747  *V_I4REF(var) = NUM2INT(val);
1748  break;
1749  case (VT_R4 | VT_BYREF) :
1750  *V_R4REF(var) = (float)NUM2INT(val);
1751  break;
1752  case (VT_R8 | VT_BYREF) :
1753  *V_R8REF(var) = NUM2INT(val);
1754  break;
1755  default:
1756  break;
1757  }
1758  break;
1759  case T_FLOAT:
1760  switch(V_VT(var)) {
1761  case (VT_I2 | VT_BYREF) :
1762  *V_I2REF(var) = (short)NUM2INT(val);
1763  break;
1764  case (VT_I4 | VT_BYREF) :
1765  *V_I4REF(var) = NUM2INT(val);
1766  break;
1767  case (VT_R4 | VT_BYREF) :
1768  *V_R4REF(var) = (float)NUM2DBL(val);
1769  break;
1770  case (VT_R8 | VT_BYREF) :
1771  *V_R8REF(var) = NUM2DBL(val);
1772  break;
1773  default:
1774  break;
1775  }
1776  break;
1777  case T_BIGNUM:
1778  if (V_VT(var) == (VT_R8 | VT_BYREF)) {
1779  *V_R8REF(var) = rb_big2dbl(val);
1780  }
1781  break;
1782  case T_TRUE:
1783  if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
1784  *V_BOOLREF(var) = VARIANT_TRUE;
1785  }
1786  break;
1787  case T_FALSE:
1788  if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
1789  *V_BOOLREF(var) = VARIANT_FALSE;
1790  }
1791  break;
1792  default:
1793  break;
1794  }
1795 }
1796 
1797 static void
1798 ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
1799 {
1800  V_VT(var) = vt;
1801  if (vt == (VT_VARIANT|VT_BYREF)) {
1802  V_VARIANTREF(var) = realvar;
1803  } else {
1804  if (V_VT(realvar) != (vt & ~VT_BYREF)) {
1805  rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
1806  }
1807  switch(vt & ~VT_BYREF) {
1808  case VT_I1:
1809  V_I1REF(var) = &V_I1(realvar);
1810  break;
1811  case VT_UI1:
1812  V_UI1REF(var) = &V_UI1(realvar);
1813  break;
1814  case VT_I2:
1815  V_I2REF(var) = &V_I2(realvar);
1816  break;
1817  case VT_UI2:
1818  V_UI2REF(var) = &V_UI2(realvar);
1819  break;
1820  case VT_I4:
1821  V_I4REF(var) = &V_I4(realvar);
1822  break;
1823  case VT_UI4:
1824  V_UI4REF(var) = &V_UI4(realvar);
1825  break;
1826  case VT_R4:
1827  V_R4REF(var) = &V_R4(realvar);
1828  break;
1829  case VT_R8:
1830  V_R8REF(var) = &V_R8(realvar);
1831  break;
1832 
1833 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1834 #ifdef V_I8REF
1835  case VT_I8:
1836  V_I8REF(var) = &V_I8(realvar);
1837  break;
1838 #endif
1839 #ifdef V_UI8REF
1840  case VT_UI8:
1841  V_UI8REF(var) = &V_UI8(realvar);
1842  break;
1843 #endif
1844 #endif
1845  case VT_INT:
1846  V_INTREF(var) = &V_INT(realvar);
1847  break;
1848 
1849  case VT_UINT:
1850  V_UINTREF(var) = &V_UINT(realvar);
1851  break;
1852 
1853  case VT_CY:
1854  V_CYREF(var) = &V_CY(realvar);
1855  break;
1856  case VT_DATE:
1857  V_DATEREF(var) = &V_DATE(realvar);
1858  break;
1859  case VT_BSTR:
1860  V_BSTRREF(var) = &V_BSTR(realvar);
1861  break;
1862  case VT_DISPATCH:
1863  V_DISPATCHREF(var) = &V_DISPATCH(realvar);
1864  break;
1865  case VT_ERROR:
1866  V_ERRORREF(var) = &V_ERROR(realvar);
1867  break;
1868  case VT_BOOL:
1869  V_BOOLREF(var) = &V_BOOL(realvar);
1870  break;
1871  case VT_UNKNOWN:
1872  V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
1873  break;
1874  case VT_ARRAY:
1875  V_ARRAYREF(var) = &V_ARRAY(realvar);
1876  break;
1877  default:
1878  rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
1879  break;
1880  }
1881  }
1882 }
1883 
1884 static void
1886 {
1887  HRESULT hr = S_OK;
1888 
1889  if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && TYPE(val) == T_STRING) {
1890  long len = RSTRING_LEN(val);
1891  void *pdest = NULL;
1892  SAFEARRAY *p = NULL;
1893  SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
1894  if (!psa) {
1895  rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
1896  }
1897  hr = SafeArrayAccessData(psa, &pdest);
1898  if (SUCCEEDED(hr)) {
1899  memcpy(pdest, RSTRING_PTR(val), len);
1900  SafeArrayUnaccessData(psa);
1901  V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
1902  p = V_ARRAY(&(pvar->realvar));
1903  if (p != NULL) {
1904  SafeArrayDestroy(p);
1905  }
1906  V_ARRAY(&(pvar->realvar)) = psa;
1907  if (vt & VT_BYREF) {
1908  V_VT(&(pvar->var)) = vt;
1909  V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
1910  } else {
1911  hr = VariantCopy(&(pvar->var), &(pvar->realvar));
1912  }
1913  } else {
1914  if (psa)
1915  SafeArrayDestroy(psa);
1916  }
1917  } else if (vt & VT_ARRAY) {
1918  if (val == Qnil) {
1919  V_VT(&(pvar->var)) = vt;
1920  if (vt & VT_BYREF) {
1921  V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
1922  }
1923  } else {
1924  hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
1925  if (SUCCEEDED(hr)) {
1926  if (vt & VT_BYREF) {
1927  V_VT(&(pvar->var)) = vt;
1928  V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
1929  } else {
1930  hr = VariantCopy(&(pvar->var), &(pvar->realvar));
1931  }
1932  }
1933  }
1934 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1935  } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) {
1936  ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF));
1937  ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF));
1938  V_VT(&(pvar->var)) = vt;
1939  if (vt & VT_BYREF) {
1940  ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1941  }
1942 #endif
1943  } else {
1944  if (val == Qnil) {
1945  V_VT(&(pvar->var)) = vt;
1946  if (vt == (VT_BYREF | VT_VARIANT)) {
1947  ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1948  } else {
1949  V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
1950  if (vt & VT_BYREF) {
1951  ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1952  }
1953  }
1954  } else {
1955  ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
1956  if (vt == (VT_BYREF | VT_VARIANT)) {
1957  ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1958  } else if (vt & VT_BYREF) {
1959  if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
1960  hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
1961  cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
1962  }
1963  if (SUCCEEDED(hr)) {
1964  ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1965  }
1966  } else {
1967  if (vt == V_VT(&(pvar->realvar))) {
1968  hr = VariantCopy(&(pvar->var), &(pvar->realvar));
1969  } else {
1970  hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
1971  cWIN32OLE_lcid, 0, vt);
1972  }
1973  }
1974  }
1975  }
1976  if (FAILED(hr)) {
1977  ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
1978  }
1979 }
1980 
1981 static void
1983 {
1984  g_nil_to = VT_EMPTY;
1985  ole_val2variant(val, var);
1986  g_nil_to = VT_ERROR;
1987 }
1988 
1989 static VALUE
1990 make_inspect(const char *class_name, VALUE detail)
1991 {
1992  VALUE str;
1993  str = rb_str_new2("#<");
1994  rb_str_cat2(str, class_name);
1995  rb_str_cat2(str, ":");
1996  rb_str_concat(str, detail);
1997  rb_str_cat2(str, ">");
1998  return str;
1999 }
2000 
2001 static VALUE
2002 default_inspect(VALUE self, const char *class_name)
2003 {
2004  VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
2005  return make_inspect(class_name, detail);
2006 }
2007 
2008 static VALUE
2009 ole_set_member(VALUE self, IDispatch *dispatch)
2010 {
2011  struct oledata *pole;
2012  Data_Get_Struct(self, struct oledata, pole);
2013  if (pole->pDispatch) {
2014  OLE_RELEASE(pole->pDispatch);
2015  pole->pDispatch = NULL;
2016  }
2017  pole->pDispatch = dispatch;
2018  return self;
2019 }
2020 
2021 
2022 static VALUE
2024 {
2025  struct oledata *pole;
2026  VALUE obj;
2027  ole_initialize();
2028  obj = Data_Make_Struct(klass,struct oledata,0,ole_free,pole);
2029  pole->pDispatch = NULL;
2030  return obj;
2031 }
2032 
2033 static VALUE
2035 {
2036  VALUE obj = fole_s_allocate(klass);
2037  ole_set_member(obj, pDispatch);
2038  return obj;
2039 }
2040 
2041 static VALUE
2042 ary_new_dim(VALUE myary, long *pid, long *plb, long dim) {
2043  long i;
2044  VALUE obj = Qnil;
2045  VALUE pobj = Qnil;
2046  long *ids = ALLOC_N(long, dim);
2047  if (!ids) {
2048  rb_raise(rb_eRuntimeError, "memory allocation error");
2049  }
2050  for(i = 0; i < dim; i++) {
2051  ids[i] = pid[i] - plb[i];
2052  }
2053  obj = myary;
2054  pobj = myary;
2055  for(i = 0; i < dim-1; i++) {
2056  obj = rb_ary_entry(pobj, ids[i]);
2057  if (obj == Qnil) {
2058  rb_ary_store(pobj, ids[i], rb_ary_new());
2059  }
2060  obj = rb_ary_entry(pobj, ids[i]);
2061  pobj = obj;
2062  }
2063  if (ids) free(ids);
2064  return obj;
2065 }
2066 
2067 static void
2068 ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val) {
2069  long id = pid[dim - 1] - plb[dim - 1];
2070  VALUE obj = ary_new_dim(myary, pid, plb, dim);
2071  rb_ary_store(obj, id, val);
2072 }
2073 
2074 static VALUE
2075 ole_variant2val(VARIANT *pvar)
2076 {
2077  VALUE obj = Qnil;
2078  HRESULT hr;
2079  while ( V_VT(pvar) == (VT_BYREF | VT_VARIANT) )
2080  pvar = V_VARIANTREF(pvar);
2081 
2082  if(V_ISARRAY(pvar)) {
2083  SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar);
2084  UINT i = 0;
2085  long *pid, *plb, *pub;
2086  VARIANT variant;
2087  VALUE val;
2088  UINT dim = 0;
2089  if (!psa) {
2090  return obj;
2091  }
2092  dim = SafeArrayGetDim(psa);
2093  VariantInit(&variant);
2094  V_VT(&variant) = (V_VT(pvar) & ~VT_ARRAY) | VT_BYREF;
2095 
2096  pid = ALLOC_N(long, dim);
2097  plb = ALLOC_N(long, dim);
2098  pub = ALLOC_N(long, dim);
2099 
2100  if(!pid || !plb || !pub) {
2101  if(pid) free(pid);
2102  if(plb) free(plb);
2103  if(pub) free(pub);
2104  rb_raise(rb_eRuntimeError, "memory allocation error");
2105  }
2106 
2107  for(i = 0; i < dim; ++i) {
2108  SafeArrayGetLBound(psa, i+1, &plb[i]);
2109  SafeArrayGetLBound(psa, i+1, &pid[i]);
2110  SafeArrayGetUBound(psa, i+1, &pub[i]);
2111  }
2112  hr = SafeArrayLock(psa);
2113  if (SUCCEEDED(hr)) {
2114  obj = rb_ary_new();
2115  i = 0;
2116  while (i < dim) {
2117  ary_new_dim(obj, pid, plb, dim);
2118  hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
2119  if (SUCCEEDED(hr)) {
2120  val = ole_variant2val(&variant);
2121  ary_store_dim(obj, pid, plb, dim, val);
2122  }
2123  for (i = 0; i < dim; ++i) {
2124  if (++pid[i] <= pub[i])
2125  break;
2126  pid[i] = plb[i];
2127  }
2128  }
2129  SafeArrayUnlock(psa);
2130  }
2131  if(pid) free(pid);
2132  if(plb) free(plb);
2133  if(pub) free(pub);
2134  return obj;
2135  }
2136  switch(V_VT(pvar) & ~VT_BYREF){
2137  case VT_EMPTY:
2138  break;
2139  case VT_NULL:
2140  break;
2141  case VT_I1:
2142  if(V_ISBYREF(pvar))
2143  obj = INT2NUM((long)*V_I1REF(pvar));
2144  else
2145  obj = INT2NUM((long)V_I1(pvar));
2146  break;
2147 
2148  case VT_UI1:
2149  if(V_ISBYREF(pvar))
2150  obj = INT2NUM((long)*V_UI1REF(pvar));
2151  else
2152  obj = INT2NUM((long)V_UI1(pvar));
2153  break;
2154 
2155  case VT_I2:
2156  if(V_ISBYREF(pvar))
2157  obj = INT2NUM((long)*V_I2REF(pvar));
2158  else
2159  obj = INT2NUM((long)V_I2(pvar));
2160  break;
2161 
2162  case VT_UI2:
2163  if(V_ISBYREF(pvar))
2164  obj = INT2NUM((long)*V_UI2REF(pvar));
2165  else
2166  obj = INT2NUM((long)V_UI2(pvar));
2167  break;
2168 
2169  case VT_I4:
2170  if(V_ISBYREF(pvar))
2171  obj = INT2NUM((long)*V_I4REF(pvar));
2172  else
2173  obj = INT2NUM((long)V_I4(pvar));
2174  break;
2175 
2176  case VT_UI4:
2177  if(V_ISBYREF(pvar))
2178  obj = INT2NUM((long)*V_UI4REF(pvar));
2179  else
2180  obj = INT2NUM((long)V_UI4(pvar));
2181  break;
2182 
2183  case VT_INT:
2184  if(V_ISBYREF(pvar))
2185  obj = INT2NUM((long)*V_INTREF(pvar));
2186  else
2187  obj = INT2NUM((long)V_INT(pvar));
2188  break;
2189 
2190  case VT_UINT:
2191  if(V_ISBYREF(pvar))
2192  obj = INT2NUM((long)*V_UINTREF(pvar));
2193  else
2194  obj = INT2NUM((long)V_UINT(pvar));
2195  break;
2196 
2197 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
2198  case VT_I8:
2199  if(V_ISBYREF(pvar))
2200 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
2201 #ifdef V_I8REF
2202  obj = I8_2_NUM(*V_I8REF(pvar));
2203 #endif
2204 #else
2205  obj = Qnil;
2206 #endif
2207  else
2208  obj = I8_2_NUM(V_I8(pvar));
2209  break;
2210  case VT_UI8:
2211  if(V_ISBYREF(pvar))
2212 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
2213 #ifdef V_UI8REF
2214  obj = UI8_2_NUM(*V_UI8REF(pvar));
2215 #endif
2216 #else
2217  obj = Qnil;
2218 #endif
2219  else
2220  obj = UI8_2_NUM(V_UI8(pvar));
2221  break;
2222 #endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
2223 
2224  case VT_R4:
2225  if(V_ISBYREF(pvar))
2226  obj = rb_float_new(*V_R4REF(pvar));
2227  else
2228  obj = rb_float_new(V_R4(pvar));
2229  break;
2230 
2231  case VT_R8:
2232  if(V_ISBYREF(pvar))
2233  obj = rb_float_new(*V_R8REF(pvar));
2234  else
2235  obj = rb_float_new(V_R8(pvar));
2236  break;
2237 
2238  case VT_BSTR:
2239  {
2240  if(V_ISBYREF(pvar))
2241  obj = ole_wc2vstr(*V_BSTRREF(pvar), FALSE);
2242  else
2243  obj = ole_wc2vstr(V_BSTR(pvar), FALSE);
2244  break;
2245  }
2246 
2247  case VT_ERROR:
2248  if(V_ISBYREF(pvar))
2249  obj = INT2NUM(*V_ERRORREF(pvar));
2250  else
2251  obj = INT2NUM(V_ERROR(pvar));
2252  break;
2253 
2254  case VT_BOOL:
2255  if (V_ISBYREF(pvar))
2256  obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse);
2257  else
2258  obj = (V_BOOL(pvar) ? Qtrue : Qfalse);
2259  break;
2260 
2261  case VT_DISPATCH:
2262  {
2263  IDispatch *pDispatch;
2264 
2265  if (V_ISBYREF(pvar))
2266  pDispatch = *V_DISPATCHREF(pvar);
2267  else
2268  pDispatch = V_DISPATCH(pvar);
2269 
2270  if (pDispatch != NULL ) {
2271  OLE_ADDREF(pDispatch);
2272  obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
2273  }
2274  break;
2275  }
2276 
2277  case VT_UNKNOWN:
2278  {
2279  /* get IDispatch interface from IUnknown interface */
2280  IUnknown *punk;
2281  IDispatch *pDispatch;
2282  void *p;
2283  HRESULT hr;
2284 
2285  if (V_ISBYREF(pvar))
2286  punk = *V_UNKNOWNREF(pvar);
2287  else
2288  punk = V_UNKNOWN(pvar);
2289 
2290  if(punk != NULL) {
2291  hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p);
2292  if(SUCCEEDED(hr)) {
2293  pDispatch = p;
2294  obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
2295  }
2296  }
2297  break;
2298  }
2299 
2300  case VT_DATE:
2301  {
2302  DATE date;
2303  if(V_ISBYREF(pvar))
2304  date = *V_DATEREF(pvar);
2305  else
2306  date = V_DATE(pvar);
2307 
2308  obj = vtdate2rbtime(date);
2309  break;
2310  }
2311  case VT_CY:
2312  default:
2313  {
2314  HRESULT hr;
2315  VARIANT variant;
2316  VariantInit(&variant);
2317  hr = VariantChangeTypeEx(&variant, pvar,
2318  cWIN32OLE_lcid, 0, VT_BSTR);
2319  if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) {
2320  obj = ole_wc2vstr(V_BSTR(&variant), FALSE);
2321  }
2322  VariantClear(&variant);
2323  break;
2324  }
2325  }
2326  return obj;
2327 }
2328 
2329 static LONG
2330 reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
2331 {
2332  return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey);
2333 }
2334 
2335 static LONG
2336 reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
2337 {
2338  return reg_open_key(hkey, StringValuePtr(key), phkey);
2339 }
2340 
2341 static VALUE
2342 reg_enum_key(HKEY hkey, DWORD i)
2343 {
2344  char buf[BUFSIZ + 1];
2345  DWORD size_buf = sizeof(buf);
2346  FILETIME ft;
2347  LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf,
2348  NULL, NULL, NULL, &ft);
2349  if(err == ERROR_SUCCESS) {
2350  buf[BUFSIZ] = '\0';
2351  return rb_str_new2(buf);
2352  }
2353  return Qnil;
2354 }
2355 
2356 static VALUE
2357 reg_get_val(HKEY hkey, const char *subkey)
2358 {
2359  char *pbuf;
2360  DWORD dwtype = 0;
2361  DWORD size = 0;
2362  VALUE val = Qnil;
2363  LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size);
2364 
2365  if (err == ERROR_SUCCESS) {
2366  pbuf = ALLOC_N(char, size + 1);
2367  err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, (BYTE *)pbuf, &size);
2368  if (err == ERROR_SUCCESS) {
2369  pbuf[size] = '\0';
2370  if (dwtype == REG_EXPAND_SZ) {
2371  char* pbuf2 = (char *)pbuf;
2372  DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0);
2373  pbuf = ALLOC_N(char, len + 1);
2374  ExpandEnvironmentStrings(pbuf2, pbuf, len + 1);
2375  free(pbuf2);
2376  }
2377  val = rb_str_new2((char *)pbuf);
2378  }
2379  free(pbuf);
2380  }
2381  return val;
2382 }
2383 
2384 static VALUE
2385 reg_get_val2(HKEY hkey, const char *subkey)
2386 {
2387  HKEY hsubkey;
2388  LONG err;
2389  VALUE val = Qnil;
2390  err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey);
2391  if (err == ERROR_SUCCESS) {
2392  val = reg_get_val(hsubkey, NULL);
2393  RegCloseKey(hsubkey);
2394  }
2395  if (val == Qnil) {
2396  val = reg_get_val(hkey, subkey);
2397  }
2398  return val;
2399 }
2400 
2401 static VALUE
2403 {
2404  VALUE path = Qnil;
2405  path = reg_get_val2(hkey, "win64");
2406  if (path != Qnil) {
2407  return path;
2408  }
2409  path = reg_get_val2(hkey, "win32");
2410  if (path != Qnil) {
2411  return path;
2412  }
2413  path = reg_get_val2(hkey, "win16");
2414  return path;
2415 }
2416 
2417 static VALUE
2419 {
2420  HKEY hroot, hclsid;
2421  LONG err;
2422  VALUE typelib;
2423  char path[MAX_PATH + 1];
2424 
2425  err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot);
2426  if (err != ERROR_SUCCESS) {
2427  return Qnil;
2428  }
2429  err = reg_open_key(hroot, StringValuePtr(ole), &hclsid);
2430  if (err != ERROR_SUCCESS) {
2431  RegCloseKey(hroot);
2432  return Qnil;
2433  }
2434  typelib = reg_get_val2(hclsid, "InprocServer32");
2435  RegCloseKey(hroot);
2436  RegCloseKey(hclsid);
2437  if (typelib != Qnil) {
2438  ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path));
2439  path[MAX_PATH] = '\0';
2440  typelib = rb_str_new2(path);
2441  }
2442  return typelib;
2443 }
2444 
2445 static VALUE
2447 {
2448  HKEY htypelib, hclsid, hversion, hlang;
2449  double fver;
2450  DWORD i, j, k;
2451  LONG err;
2452  BOOL found = FALSE;
2453  VALUE typelib;
2454  VALUE file = Qnil;
2455  VALUE clsid;
2456  VALUE ver;
2457  VALUE lang;
2458 
2459  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
2460  if(err != ERROR_SUCCESS) {
2461  return Qnil;
2462  }
2463  for(i = 0; !found; i++) {
2464  clsid = reg_enum_key(htypelib, i);
2465  if (clsid == Qnil)
2466  break;
2467  err = reg_open_vkey(htypelib, clsid, &hclsid);
2468  if (err != ERROR_SUCCESS)
2469  continue;
2470  fver = 0;
2471  for(j = 0; !found; j++) {
2472  ver = reg_enum_key(hclsid, j);
2473  if (ver == Qnil)
2474  break;
2475  err = reg_open_vkey(hclsid, ver, &hversion);
2476  if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
2477  continue;
2478  fver = atof(StringValuePtr(ver));
2479  typelib = reg_get_val(hversion, NULL);
2480  if (typelib == Qnil)
2481  continue;
2482  if (rb_str_cmp(typelib, ole) == 0) {
2483  for(k = 0; !found; k++) {
2484  lang = reg_enum_key(hversion, k);
2485  if (lang == Qnil)
2486  break;
2487  err = reg_open_vkey(hversion, lang, &hlang);
2488  if (err == ERROR_SUCCESS) {
2489  if ((file = reg_get_typelib_file_path(hlang)) != Qnil)
2490  found = TRUE;
2491  RegCloseKey(hlang);
2492  }
2493  }
2494  }
2495  RegCloseKey(hversion);
2496  }
2497  RegCloseKey(hclsid);
2498  }
2499  RegCloseKey(htypelib);
2500  return file;
2501 }
2502 
2503 static VALUE
2505 {
2506  VALUE file = typelib_file_from_clsid(ole);
2507  if (file != Qnil) {
2508  return file;
2509  }
2510  return typelib_file_from_typelib(ole);
2511 }
2512 
2513 static void
2514 ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self)
2515 {
2516  unsigned int count;
2517  unsigned int index;
2518  int iVar;
2519  ITypeInfo *pTypeInfo;
2520  TYPEATTR *pTypeAttr;
2521  VARDESC *pVarDesc;
2522  HRESULT hr;
2523  unsigned int len;
2524  BSTR bstr;
2525  char *pName = NULL;
2526  VALUE val;
2527  VALUE constant;
2528  ID id;
2529  constant = rb_hash_new();
2530  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
2531  for (index = 0; index < count; index++) {
2532  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo);
2533  if (FAILED(hr))
2534  continue;
2535  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
2536  if(FAILED(hr)) {
2537  OLE_RELEASE(pTypeInfo);
2538  continue;
2539  }
2540  for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) {
2541  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc);
2542  if(FAILED(hr))
2543  continue;
2544  if(pVarDesc->varkind == VAR_CONST &&
2545  !(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
2546  VARFLAG_FRESTRICTED |
2547  VARFLAG_FNONBROWSABLE))) {
2548  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
2549  1, &len);
2550  if(FAILED(hr) || len == 0 || !bstr)
2551  continue;
2552  pName = ole_wc2mb(bstr);
2553  val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
2554  *pName = toupper((int)*pName);
2555  id = rb_intern(pName);
2556  if (rb_is_const_id(id)) {
2557  rb_define_const(klass, pName, val);
2558  }
2559  else {
2560  rb_hash_aset(constant, rb_str_new2(pName), val);
2561  }
2562  SysFreeString(bstr);
2563  if(pName) {
2564  free(pName);
2565  pName = NULL;
2566  }
2567  }
2568  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
2569  }
2570  pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
2571  OLE_RELEASE(pTypeInfo);
2572  }
2573  rb_define_const(klass, "CONSTANTS", constant);
2574 }
2575 
2576 static HRESULT
2577 clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid)
2578 {
2579  HKEY hlm;
2580  HKEY hpid;
2581  VALUE subkey;
2582  LONG err;
2583  char clsid[100];
2584  OLECHAR *pbuf;
2585  DWORD len;
2586  DWORD dwtype;
2587  HRESULT hr = S_OK;
2588  err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm);
2589  if (err != ERROR_SUCCESS)
2590  return HRESULT_FROM_WIN32(err);
2591  subkey = rb_str_new2("SOFTWARE\\Classes\\");
2592  rb_str_concat(subkey, com);
2593  rb_str_cat2(subkey, "\\CLSID");
2594  err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid);
2595  if (err != ERROR_SUCCESS)
2596  hr = HRESULT_FROM_WIN32(err);
2597  else {
2598  len = sizeof(clsid);
2599  err = RegQueryValueEx(hpid, "", NULL, &dwtype, (BYTE *)clsid, &len);
2600  if (err == ERROR_SUCCESS && dwtype == REG_SZ) {
2601  pbuf = ole_mb2wc(clsid, -1);
2602  hr = CLSIDFromString(pbuf, pclsid);
2603  SysFreeString(pbuf);
2604  }
2605  else {
2606  hr = HRESULT_FROM_WIN32(err);
2607  }
2608  RegCloseKey(hpid);
2609  }
2610  RegCloseKey(hlm);
2611  return hr;
2612 }
2613 
2614 static VALUE
2616 {
2617  VALUE ole, host, others;
2618  HRESULT hr;
2619  CLSID clsid;
2620  OLECHAR *pbuf;
2621 
2622  COSERVERINFO serverinfo;
2623  MULTI_QI multi_qi;
2624  DWORD clsctx = CLSCTX_REMOTE_SERVER;
2625 
2626  if (!gole32)
2627  gole32 = LoadLibrary("OLE32");
2628  if (!gole32)
2629  rb_raise(rb_eRuntimeError, "failed to load OLE32");
2630  if (!gCoCreateInstanceEx)
2631  gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*)
2632  GetProcAddress(gole32, "CoCreateInstanceEx");
2633  if (!gCoCreateInstanceEx)
2634  rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment");
2635  rb_scan_args(argc, argv, "2*", &ole, &host, &others);
2636 
2637  pbuf = ole_vstr2wc(ole);
2638  hr = CLSIDFromProgID(pbuf, &clsid);
2639  if (FAILED(hr))
2640  hr = clsid_from_remote(host, ole, &clsid);
2641  if (FAILED(hr))
2642  hr = CLSIDFromString(pbuf, &clsid);
2643  SysFreeString(pbuf);
2644  if (FAILED(hr))
2646  "unknown OLE server: `%s'",
2647  StringValuePtr(ole));
2648  memset(&serverinfo, 0, sizeof(COSERVERINFO));
2649  serverinfo.pwszName = ole_vstr2wc(host);
2650  memset(&multi_qi, 0, sizeof(MULTI_QI));
2651  multi_qi.pIID = &IID_IDispatch;
2652  hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi);
2653  SysFreeString(serverinfo.pwszName);
2654  if (FAILED(hr))
2656  "failed to create DCOM server `%s' in `%s'",
2657  StringValuePtr(ole),
2658  StringValuePtr(host));
2659 
2660  ole_set_member(self, (IDispatch*)multi_qi.pItf);
2661  return self;
2662 }
2663 
2664 static VALUE
2665 ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
2666 {
2667  IBindCtx *pBindCtx;
2668  IMoniker *pMoniker;
2669  IDispatch *pDispatch;
2670  void *p;
2671  HRESULT hr;
2672  OLECHAR *pbuf;
2673  ULONG eaten = 0;
2674 
2675  ole_initialize();
2676 
2677  hr = CreateBindCtx(0, &pBindCtx);
2678  if(FAILED(hr)) {
2680  "failed to create bind context");
2681  }
2682 
2683  pbuf = ole_vstr2wc(moniker);
2684  hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker);
2685  SysFreeString(pbuf);
2686  if(FAILED(hr)) {
2687  OLE_RELEASE(pBindCtx);
2689  "failed to parse display name of moniker `%s'",
2690  StringValuePtr(moniker));
2691  }
2692  hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL,
2693  &IID_IDispatch, &p);
2694  pDispatch = p;
2695  OLE_RELEASE(pMoniker);
2696  OLE_RELEASE(pBindCtx);
2697 
2698  if(FAILED(hr)) {
2700  "failed to bind moniker `%s'",
2701  StringValuePtr(moniker));
2702  }
2703  return create_win32ole_object(self, pDispatch, argc, argv);
2704 }
2705 
2706 /*
2707  * call-seq:
2708  * WIN32OLE.connect( ole ) --> aWIN32OLE
2709  *
2710  * Returns running OLE Automation object or WIN32OLE object from moniker.
2711  * 1st argument should be OLE program id or class id or moniker.
2712  *
2713  * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel.
2714  */
2715 static VALUE
2717 {
2718  VALUE svr_name;
2719  VALUE others;
2720  HRESULT hr;
2721  CLSID clsid;
2722  OLECHAR *pBuf;
2723  IDispatch *pDispatch;
2724  void *p;
2725  IUnknown *pUnknown;
2726 
2727  rb_secure(4);
2728  /* initialize to use OLE */
2729  ole_initialize();
2730 
2731  rb_scan_args(argc, argv, "1*", &svr_name, &others);
2732  SafeStringValue(svr_name);
2733  if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
2734  rb_raise(rb_eSecurityError, "Insecure Object Connection - %s",
2735  StringValuePtr(svr_name));
2736  }
2737 
2738  /* get CLSID from OLE server name */
2739  pBuf = ole_vstr2wc(svr_name);
2740  hr = CLSIDFromProgID(pBuf, &clsid);
2741  if(FAILED(hr)) {
2742  hr = CLSIDFromString(pBuf, &clsid);
2743  }
2744  SysFreeString(pBuf);
2745  if(FAILED(hr)) {
2746  return ole_bind_obj(svr_name, argc, argv, self);
2747  }
2748 
2749  hr = GetActiveObject(&clsid, 0, &pUnknown);
2750  if (FAILED(hr)) {
2752  "OLE server `%s' not running", StringValuePtr(svr_name));
2753  }
2754  hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p);
2755  pDispatch = p;
2756  if(FAILED(hr)) {
2757  OLE_RELEASE(pUnknown);
2759  "failed to create WIN32OLE server `%s'",
2760  StringValuePtr(svr_name));
2761  }
2762 
2763  OLE_RELEASE(pUnknown);
2764 
2765  return create_win32ole_object(self, pDispatch, argc, argv);
2766 }
2767 
2768 /*
2769  * call-seq:
2770  * WIN32OLE.const_load( ole, mod = WIN32OLE)
2771  *
2772  * Defines the constants of OLE Automation server as mod's constants.
2773  * The first argument is WIN32OLE object or type library name.
2774  * If 2nd argument is omitted, the default is WIN32OLE.
2775  * The first letter of Ruby's constant variable name is upper case,
2776  * so constant variable name of WIN32OLE object is capitalized.
2777  * For example, the 'xlTop' constant of Excel is changed to 'XlTop'
2778  * in WIN32OLE.
2779  * If the first letter of constant variabl is not [A-Z], then
2780  * the constant is defined as CONSTANTS hash element.
2781  *
2782  * module EXCEL_CONST
2783  * end
2784  * excel = WIN32OLE.new('Excel.Application')
2785  * WIN32OLE.const_load(excel, EXCEL_CONST)
2786  * puts EXCEL_CONST::XlTop # => -4160
2787  * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541
2788  *
2789  * WIN32OLE.const_load(excel)
2790  * puts WIN32OLE::XlTop # => -4160
2791  *
2792  * module MSO
2793  * end
2794  * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO)
2795  * puts MSO::MsoLineSingle # => 1
2796  */
2797 static VALUE
2799 {
2800  VALUE ole;
2801  VALUE klass;
2802  struct oledata *pole;
2803  ITypeInfo *pTypeInfo;
2804  ITypeLib *pTypeLib;
2805  unsigned int index;
2806  HRESULT hr;
2807  OLECHAR *pBuf;
2808  VALUE file;
2809  LCID lcid = cWIN32OLE_lcid;
2810 
2811  rb_secure(4);
2812  rb_scan_args(argc, argv, "11", &ole, &klass);
2813  if (TYPE(klass) != T_CLASS &&
2814  TYPE(klass) != T_MODULE &&
2815  TYPE(klass) != T_NIL) {
2816  rb_raise(rb_eTypeError, "2nd parameter must be Class or Module");
2817  }
2818  if (rb_obj_is_kind_of(ole, cWIN32OLE)) {
2819  OLEData_Get_Struct(ole, pole);
2820  hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
2821  0, lcid, &pTypeInfo);
2822  if(FAILED(hr)) {
2823  ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
2824  }
2825  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
2826  if(FAILED(hr)) {
2827  OLE_RELEASE(pTypeInfo);
2828  ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib");
2829  }
2830  OLE_RELEASE(pTypeInfo);
2831  if(TYPE(klass) != T_NIL) {
2832  ole_const_load(pTypeLib, klass, self);
2833  }
2834  else {
2835  ole_const_load(pTypeLib, cWIN32OLE, self);
2836  }
2837  OLE_RELEASE(pTypeLib);
2838  }
2839  else if(TYPE(ole) == T_STRING) {
2840  file = typelib_file(ole);
2841  if (file == Qnil) {
2842  file = ole;
2843  }
2844  pBuf = ole_vstr2wc(file);
2845  hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib);
2846  SysFreeString(pBuf);
2847  if (FAILED(hr))
2848  ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
2849  if(TYPE(klass) != T_NIL) {
2850  ole_const_load(pTypeLib, klass, self);
2851  }
2852  else {
2853  ole_const_load(pTypeLib, cWIN32OLE, self);
2854  }
2855  OLE_RELEASE(pTypeLib);
2856  }
2857  else {
2858  rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance");
2859  }
2860  return Qnil;
2861 }
2862 
2863 static VALUE
2864 ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes)
2865 {
2866 
2867  long count;
2868  int i;
2869  HRESULT hr;
2870  BSTR bstr;
2871  ITypeInfo *pTypeInfo;
2872  VALUE type;
2873 
2874  rb_secure(4);
2875  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
2876  for (i = 0; i < count; i++) {
2877  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
2878  &bstr, NULL, NULL, NULL);
2879  if (FAILED(hr))
2880  continue;
2881 
2882  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
2883  if (FAILED(hr))
2884  continue;
2885 
2887  oletype_set_member(type, pTypeInfo, WC2VSTR(bstr));
2888 
2889  rb_ary_push(classes, type);
2890  OLE_RELEASE(pTypeInfo);
2891  }
2892  return classes;
2893 }
2894 
2895 static ULONG
2896 reference_count(struct oledata * pole)
2897 {
2898  ULONG n = 0;
2899  if(pole->pDispatch) {
2900  OLE_ADDREF(pole->pDispatch);
2901  n = OLE_RELEASE(pole->pDispatch);
2902  }
2903  return n;
2904 }
2905 
2906 /*
2907  * call-seq:
2908  * WIN32OLE.ole_reference_count(aWIN32OLE) --> number
2909  *
2910  * Returns reference counter of Dispatch interface of WIN32OLE object.
2911  * You should not use this method because this method
2912  * exists only for debugging WIN32OLE.
2913  */
2914 static VALUE
2916 {
2917  struct oledata * pole;
2918  OLEData_Get_Struct(obj, pole);
2919  return INT2NUM(reference_count(pole));
2920 }
2921 
2922 /*
2923  * call-seq:
2924  * WIN32OLE.ole_free(aWIN32OLE) --> number
2925  *
2926  * Invokes Release method of Dispatch interface of WIN32OLE object.
2927  * You should not use this method because this method
2928  * exists only for debugging WIN32OLE.
2929  * The return value is reference counter of OLE object.
2930  */
2931 static VALUE
2933 {
2934  ULONG n = 0;
2935  struct oledata * pole;
2936  OLEData_Get_Struct(obj, pole);
2937  if(pole->pDispatch) {
2938  if (reference_count(pole) > 0) {
2939  n = OLE_RELEASE(pole->pDispatch);
2940  }
2941  }
2942  return INT2NUM(n);
2943 }
2944 
2945 static HWND
2946 ole_show_help(VALUE helpfile, VALUE helpcontext)
2947 {
2948  FNHTMLHELP *pfnHtmlHelp;
2949  HWND hwnd = 0;
2950 
2951  if(!ghhctrl)
2952  ghhctrl = LoadLibrary("HHCTRL.OCX");
2953  if (!ghhctrl)
2954  return hwnd;
2955  pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA");
2956  if (!pfnHtmlHelp)
2957  return hwnd;
2958  hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
2959  0x0f, NUM2INT(helpcontext));
2960  if (hwnd == 0)
2961  hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
2962  0, NUM2INT(helpcontext));
2963  return hwnd;
2964 }
2965 
2966 /*
2967  * call-seq:
2968  * WIN32OLE.ole_show_help(obj [,helpcontext])
2969  *
2970  * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE
2971  * object or WIN32OLE_METHOD object or helpfile.
2972  *
2973  * excel = WIN32OLE.new('Excel.Application')
2974  * typeobj = excel.ole_type
2975  * WIN32OLE.ole_show_help(typeobj)
2976  */
2977 static VALUE
2979 {
2980  VALUE target;
2981  VALUE helpcontext;
2982  VALUE helpfile;
2983  VALUE name;
2984  HWND hwnd;
2985  rb_scan_args(argc, argv, "11", &target, &helpcontext);
2986  if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) ||
2988  helpfile = rb_funcall(target, rb_intern("helpfile"), 0);
2989  if(strlen(StringValuePtr(helpfile)) == 0) {
2990  name = rb_ivar_get(target, rb_intern("name"));
2991  rb_raise(rb_eRuntimeError, "no helpfile of `%s'",
2992  StringValuePtr(name));
2993  }
2994  helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0);
2995  } else {
2996  helpfile = target;
2997  }
2998  if (TYPE(helpfile) != T_STRING) {
2999  rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)");
3000  }
3001  hwnd = ole_show_help(helpfile, helpcontext);
3002  if(hwnd == 0) {
3003  rb_raise(rb_eRuntimeError, "failed to open help file `%s'",
3004  StringValuePtr(helpfile));
3005  }
3006  return Qnil;
3007 }
3008 
3009 /*
3010  * call-seq:
3011  * WIN32OLE.codepage
3012  *
3013  * Returns current codepage.
3014  * WIN32OLE.codepage # => WIN32OLE::CP_ACP
3015  */
3016 static VALUE
3018 {
3019  return INT2FIX(cWIN32OLE_cp);
3020 }
3021 
3022 static BOOL CALLBACK
3024  if (strtoul(str, NULL, 10) == g_cp_to_check) {
3025  g_cp_installed = TRUE;
3026  return FALSE;
3027  }
3028  return TRUE;
3029 }
3030 
3031 static BOOL
3033 {
3035  g_cp_to_check = cp;
3036  EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED);
3037  return g_cp_installed;
3038 }
3039 
3040 /*
3041  * call-seq:
3042  * WIN32OLE.codepage = CP
3043  *
3044  * Sets current codepage.
3045  * The WIN32OLE.codepage is initialized according to
3046  * Encoding.default_internal.
3047  * If Encoding.default_internal is nil then WIN32OLE.codepage
3048  * is initialized according to Encoding.default_external.
3049  *
3050  * WIN32OLE.codepage = WIN32OLE::CP_UTF8
3051  * WIN32OLE.codepage = 65001
3052  */
3053 static VALUE
3055 {
3056  UINT cp = FIX2INT(vcp);
3057  set_ole_codepage(cp);
3058  /*
3059  * Should this method return old codepage?
3060  */
3061  return Qnil;
3062 }
3063 
3064 /*
3065  * call-seq:
3066  * WIN32OLE.locale -> locale id.
3067  *
3068  * Returns current locale id (lcid). The default locale is
3069  * LOCALE_SYSTEM_DEFAULT.
3070  *
3071  * lcid = WIN32OLE.locale
3072  */
3073 static VALUE
3075 {
3076  return INT2FIX(cWIN32OLE_lcid);
3077 }
3078 
3079 static BOOL
3080 CALLBACK installed_lcid_proc(LPTSTR str)
3081 {
3082  if (strcmp(str, g_lcid_to_check) == 0) {
3084  return FALSE;
3085  }
3086  return TRUE;
3087 }
3088 
3089 static BOOL
3090 lcid_installed(LCID lcid)
3091 {
3093  snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", lcid);
3094  EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED);
3095  return g_lcid_installed;
3096 }
3097 
3098 /*
3099  * call-seq:
3100  * WIN32OLE.locale = lcid
3101  *
3102  * Sets current locale id (lcid).
3103  *
3104  * WIN32OLE.locale = 1033 # set locale English(U.S)
3105  * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
3106  *
3107  */
3108 static VALUE
3110 {
3111  LCID lcid = FIX2INT(vlcid);
3112  if (lcid_installed(lcid)) {
3113  cWIN32OLE_lcid = lcid;
3114  } else {
3115  switch (lcid) {
3116  case LOCALE_SYSTEM_DEFAULT:
3117  case LOCALE_USER_DEFAULT:
3118  cWIN32OLE_lcid = lcid;
3119  break;
3120  default:
3121  rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid);
3122  }
3123  }
3124  return Qnil;
3125 }
3126 
3127 /*
3128  * call-seq:
3129  * WIN32OLE.create_guid
3130  *
3131  * Creates GUID.
3132  * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
3133  */
3134 static VALUE
3136 {
3137  GUID guid;
3138  HRESULT hr;
3139  OLECHAR bstr[80];
3140  int len = 0;
3141  hr = CoCreateGuid(&guid);
3142  if (FAILED(hr)) {
3143  ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID");
3144  }
3145  len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
3146  if (len == 0) {
3147  rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)");
3148  }
3149  return ole_wc2vstr(bstr, FALSE);
3150 }
3151 
3152 /*
3153  * WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize
3154  * are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634).
3155  * You must not use thease method.
3156  */
3157 
3158 /* :nodoc */
3159 static VALUE
3161 {
3162  ole_initialize();
3163  return Qnil;
3164 }
3165 
3166 /* :nodoc */
3167 static VALUE
3169 {
3170  ole_uninitialize();
3171  return Qnil;
3172 }
3173 
3174 /*
3175  * Document-class: WIN32OLE
3176  *
3177  * <code>WIN32OLE</code> objects represent OLE Automation object in Ruby.
3178  *
3179  * By using WIN32OLE, you can access OLE server like VBScript.
3180  *
3181  * Here is sample script.
3182  *
3183  * require 'win32ole'
3184  *
3185  * excel = WIN32OLE.new('Excel.Application')
3186  * excel.visible = true
3187  * workbook = excel.Workbooks.Add();
3188  * worksheet = workbook.Worksheets(1);
3189  * worksheet.Range("A1:D1").value = ["North","South","East","West"];
3190  * worksheet.Range("A2:B2").value = [5.2, 10];
3191  * worksheet.Range("C2").value = 8;
3192  * worksheet.Range("D2").value = 20;
3193  *
3194  * range = worksheet.Range("A1:D2");
3195  * range.select
3196  * chart = workbook.Charts.Add;
3197  *
3198  * workbook.saved = true;
3199  *
3200  * excel.ActiveWorkbook.Close(0);
3201  * excel.Quit();
3202  *
3203  * Unfortunately, Win32OLE doesn't support the argument passed by
3204  * reference directly.
3205  * Instead, Win32OLE provides WIN32OLE::ARGV.
3206  * If you want to get the result value of argument passed by reference,
3207  * you can use WIN32OLE::ARGV.
3208  *
3209  * oleobj.method(arg1, arg2, refargv3)
3210  * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
3211  *
3212  */
3213 
3214 /*
3215  * call-seq:
3216  * WIN32OLE.new(server, [host]) -> WIN32OLE object
3217  *
3218  * Returns a new WIN32OLE object(OLE Automation object).
3219  * The first argument server specifies OLE Automation server.
3220  * The first argument should be CLSID or PROGID.
3221  * If second argument host specified, then returns OLE Automation
3222  * object on host.
3223  *
3224  * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object.
3225  * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
3226  */
3227 static VALUE
3229 {
3230  VALUE svr_name;
3231  VALUE host;
3232  VALUE others;
3233  HRESULT hr;
3234  CLSID clsid;
3235  OLECHAR *pBuf;
3236  IDispatch *pDispatch;
3237  void *p;
3238  rb_secure(4);
3239  rb_call_super(0, 0);
3240  rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
3241 
3242  SafeStringValue(svr_name);
3243  if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
3244  rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
3245  StringValuePtr(svr_name));
3246  }
3247  if (!NIL_P(host)) {
3248  SafeStringValue(host);
3249  if (rb_safe_level() > 0 && OBJ_TAINTED(host)) {
3250  rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
3251  StringValuePtr(svr_name));
3252  }
3253  return ole_create_dcom(argc, argv, self);
3254  }
3255 
3256  /* get CLSID from OLE server name */
3257  pBuf = ole_vstr2wc(svr_name);
3258  hr = CLSIDFromProgID(pBuf, &clsid);
3259  if(FAILED(hr)) {
3260  hr = CLSIDFromString(pBuf, &clsid);
3261  }
3262  SysFreeString(pBuf);
3263  if(FAILED(hr)) {
3265  "unknown OLE server: `%s'",
3266  StringValuePtr(svr_name));
3267  }
3268 
3269  /* get IDispatch interface */
3270  hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
3271  &IID_IDispatch, &p);
3272  pDispatch = p;
3273  if(FAILED(hr)) {
3275  "failed to create WIN32OLE object from `%s'",
3276  StringValuePtr(svr_name));
3277  }
3278 
3279  ole_set_member(self, pDispatch);
3280  return self;
3281 }
3282 
3283 static VALUE
3284 hash2named_arg(VALUE pair, struct oleparam* pOp)
3285 {
3286  unsigned int index, i;
3287  VALUE key, value;
3288  index = pOp->dp.cNamedArgs;
3289 
3290  /*---------------------------------------------
3291  the data-type of key must be String or Symbol
3292  -----------------------------------------------*/
3293  key = rb_ary_entry(pair, 0);
3294  if(TYPE(key) != T_STRING && TYPE(key) != T_SYMBOL) {
3295  /* clear name of dispatch parameters */
3296  for(i = 1; i < index + 1; i++) {
3297  SysFreeString(pOp->pNamedArgs[i]);
3298  }
3299  /* clear dispatch parameters */
3300  for(i = 0; i < index; i++ ) {
3301  VariantClear(&(pOp->dp.rgvarg[i]));
3302  }
3303  /* raise an exception */
3304  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
3305  }
3306  if (TYPE(key) == T_SYMBOL) {
3307  key = rb_sym_to_s(key);
3308  }
3309 
3310  /* pNamedArgs[0] is <method name>, so "index + 1" */
3311  pOp->pNamedArgs[index + 1] = ole_vstr2wc(key);
3312 
3313  value = rb_ary_entry(pair, 1);
3314  VariantInit(&(pOp->dp.rgvarg[index]));
3315  ole_val2variant(value, &(pOp->dp.rgvarg[index]));
3316 
3317  pOp->dp.cNamedArgs += 1;
3318  return Qnil;
3319 }
3320 
3321 static VALUE
3322 set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
3323 {
3325 
3326  Check_Type(argv, T_ARRAY);
3327  rb_ary_clear(argv);
3328  while (end-- > beg) {
3329  rb_ary_push(argv, ole_variant2val(&realargs[end]));
3330  VariantClear(&realargs[end]);
3331  }
3332  return argv;
3333 }
3334 
3335 static VALUE
3336 ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
3337 {
3338  LCID lcid = cWIN32OLE_lcid;
3339  struct oledata *pole;
3340  HRESULT hr;
3341  VALUE cmd;
3342  VALUE paramS;
3343  VALUE param;
3344  VALUE obj;
3345  VALUE v;
3346 
3347  BSTR wcmdname;
3348 
3349  DISPID DispID;
3350  DISPID* pDispID;
3351  EXCEPINFO excepinfo;
3352  VARIANT result;
3353  VARIANTARG* realargs = NULL;
3354  unsigned int argErr = 0;
3355  unsigned int i;
3356  unsigned int cNamedArgs;
3357  int n;
3358  struct oleparam op;
3359  struct olevariantdata *pvar;
3360  memset(&excepinfo, 0, sizeof(EXCEPINFO));
3361 
3362  VariantInit(&result);
3363 
3364  op.dp.rgvarg = NULL;
3365  op.dp.rgdispidNamedArgs = NULL;
3366  op.dp.cNamedArgs = 0;
3367  op.dp.cArgs = 0;
3368 
3369  rb_scan_args(argc, argv, "1*", &cmd, &paramS);
3370  if(TYPE(cmd) != T_STRING && TYPE(cmd) != T_SYMBOL && !is_bracket) {
3371  rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
3372  }
3373  if (TYPE(cmd) == T_SYMBOL) {
3374  cmd = rb_sym_to_s(cmd);
3375  }
3376  OLEData_Get_Struct(self, pole);
3377  if(!pole->pDispatch) {
3378  rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
3379  }
3380  if (is_bracket) {
3381  DispID = DISPID_VALUE;
3382  argc += 1;
3383  rb_ary_unshift(paramS, cmd);
3384  } else {
3385  wcmdname = ole_vstr2wc(cmd);
3386  hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
3387  &wcmdname, 1, lcid, &DispID);
3388  SysFreeString(wcmdname);
3389  if(FAILED(hr)) {
3391  "unknown property or method: `%s'",
3392  StringValuePtr(cmd));
3393  }
3394  }
3395 
3396  /* pick up last argument of method */
3397  param = rb_ary_entry(paramS, argc-2);
3398 
3399  op.dp.cNamedArgs = 0;
3400 
3401  /* if last arg is hash object */
3402  if(TYPE(param) == T_HASH) {
3403  /*------------------------------------------
3404  hash object ==> named dispatch parameters
3405  --------------------------------------------*/
3406  cNamedArgs = NUM2INT(rb_funcall(param, rb_intern("length"), 0));
3407  op.dp.cArgs = cNamedArgs + argc - 2;
3408  op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
3409  op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
3410  rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op);
3411 
3412  pDispID = ALLOCA_N(DISPID, cNamedArgs + 1);
3413  op.pNamedArgs[0] = ole_vstr2wc(cmd);
3414  hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch,
3415  &IID_NULL,
3416  op.pNamedArgs,
3417  op.dp.cNamedArgs + 1,
3418  lcid, pDispID);
3419  for(i = 0; i < op.dp.cNamedArgs + 1; i++) {
3420  SysFreeString(op.pNamedArgs[i]);
3421  op.pNamedArgs[i] = NULL;
3422  }
3423  if(FAILED(hr)) {
3424  /* clear dispatch parameters */
3425  for(i = 0; i < op.dp.cArgs; i++ ) {
3426  VariantClear(&op.dp.rgvarg[i]);
3427  }
3429  "failed to get named argument info: `%s'",
3430  StringValuePtr(cmd));
3431  }
3432  op.dp.rgdispidNamedArgs = &(pDispID[1]);
3433  }
3434  else {
3435  cNamedArgs = 0;
3436  op.dp.cArgs = argc - 1;
3437  op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
3438  if (op.dp.cArgs > 0) {
3439  op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
3440  }
3441  }
3442  /*--------------------------------------
3443  non hash args ==> dispatch parameters
3444  ----------------------------------------*/
3445  if(op.dp.cArgs > cNamedArgs) {
3446  realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1);
3447  for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3448  n = op.dp.cArgs - i + cNamedArgs - 1;
3449  VariantInit(&realargs[n]);
3450  VariantInit(&op.dp.rgvarg[n]);
3451  param = rb_ary_entry(paramS, i-cNamedArgs);
3452  if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
3453  Data_Get_Struct(param, struct olevariantdata, pvar);
3454  VariantCopy(&op.dp.rgvarg[n], &(pvar->var));
3455  } else {
3456  ole_val2variant(param, &realargs[n]);
3457  V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF;
3458  V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n];
3459  }
3460  }
3461  }
3462  /* apparent you need to call propput, you need this */
3463  if (wFlags & DISPATCH_PROPERTYPUT) {
3464  if (op.dp.cArgs == 0)
3465  ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error");
3466 
3467  op.dp.cNamedArgs = 1;
3468  op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
3469  op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
3470  }
3471 
3472  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3473  &IID_NULL, lcid, wFlags, &op.dp,
3474  &result, &excepinfo, &argErr);
3475 
3476  if (FAILED(hr)) {
3477  /* retry to call args by value */
3478  if(op.dp.cArgs >= cNamedArgs) {
3479  for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3480  n = op.dp.cArgs - i + cNamedArgs - 1;
3481  param = rb_ary_entry(paramS, i-cNamedArgs);
3482  ole_val2variant(param, &op.dp.rgvarg[n]);
3483  }
3484  if (hr == DISP_E_EXCEPTION) {
3485  ole_freeexceptinfo(&excepinfo);
3486  }
3487  memset(&excepinfo, 0, sizeof(EXCEPINFO));
3488  VariantInit(&result);
3489  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3490  &IID_NULL, lcid, wFlags,
3491  &op.dp, &result,
3492  &excepinfo, &argErr);
3493 
3494  /* mega kludge. if a method in WORD is called and we ask
3495  * for a result when one is not returned then
3496  * hResult == DISP_E_EXCEPTION. this only happens on
3497  * functions whose DISPID > 0x8000 */
3498  if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) {
3499  if (hr == DISP_E_EXCEPTION) {
3500  ole_freeexceptinfo(&excepinfo);
3501  }
3502  memset(&excepinfo, 0, sizeof(EXCEPINFO));
3503  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3504  &IID_NULL, lcid, wFlags,
3505  &op.dp, NULL,
3506  &excepinfo, &argErr);
3507 
3508  }
3509  for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3510  n = op.dp.cArgs - i + cNamedArgs - 1;
3511  VariantClear(&op.dp.rgvarg[n]);
3512  }
3513  }
3514 
3515  if (FAILED(hr)) {
3516  /* retry after converting nil to VT_EMPTY */
3517  if (op.dp.cArgs > cNamedArgs) {
3518  for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3519  n = op.dp.cArgs - i + cNamedArgs - 1;
3520  param = rb_ary_entry(paramS, i-cNamedArgs);
3521  ole_val2variant2(param, &op.dp.rgvarg[n]);
3522  }
3523  if (hr == DISP_E_EXCEPTION) {
3524  ole_freeexceptinfo(&excepinfo);
3525  }
3526  memset(&excepinfo, 0, sizeof(EXCEPINFO));
3527  VariantInit(&result);
3528  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3529  &IID_NULL, lcid, wFlags,
3530  &op.dp, &result,
3531  &excepinfo, &argErr);
3532  for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3533  n = op.dp.cArgs - i + cNamedArgs - 1;
3534  VariantClear(&op.dp.rgvarg[n]);
3535  }
3536  }
3537  }
3538 
3539  }
3540  /* clear dispatch parameter */
3541  if(op.dp.cArgs > cNamedArgs) {
3542  for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3543  n = op.dp.cArgs - i + cNamedArgs - 1;
3544  param = rb_ary_entry(paramS, i-cNamedArgs);
3545  if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
3546  ole_val2variant(param, &realargs[n]);
3547  }
3548  }
3549  set_argv(realargs, cNamedArgs, op.dp.cArgs);
3550  }
3551  else {
3552  for(i = 0; i < op.dp.cArgs; i++) {
3553  VariantClear(&op.dp.rgvarg[i]);
3554  }
3555  }
3556 
3557  if (FAILED(hr)) {
3558  v = ole_excepinfo2msg(&excepinfo);
3559  ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s",
3560  StringValuePtr(cmd),
3561  StringValuePtr(v));
3562  }
3563  obj = ole_variant2val(&result);
3564  VariantClear(&result);
3565  return obj;
3566 }
3567 
3568 /*
3569  * call-seq:
3570  * WIN32OLE#invoke(method, [arg1,...]) => return value of method.
3571  *
3572  * Runs OLE method.
3573  * The first argument specifies the method name of OLE Automation object.
3574  * The others specify argument of the <i>method</i>.
3575  * If you can not execute <i>method</i> directly, then use this method instead.
3576  *
3577  * excel = WIN32OLE.new('Excel.Application')
3578  * excel.invoke('Quit') # => same as excel.Quit
3579  *
3580  */
3581 static VALUE
3583 {
3584  return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
3585 }
3586 
3587 static VALUE
3588 ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
3589 {
3590  HRESULT hr;
3591  struct oledata *pole;
3592  unsigned int argErr = 0;
3593  EXCEPINFO excepinfo;
3594  VARIANT result;
3595  DISPPARAMS dispParams;
3596  VARIANTARG* realargs = NULL;
3597  int i, j;
3598  VALUE obj = Qnil;
3599  VALUE tp, param;
3600  VALUE v;
3601  VARTYPE vt;
3602 
3603  Check_Type(args, T_ARRAY);
3604  Check_Type(types, T_ARRAY);
3605 
3606  memset(&excepinfo, 0, sizeof(EXCEPINFO));
3607  memset(&dispParams, 0, sizeof(DISPPARAMS));
3608  VariantInit(&result);
3609  OLEData_Get_Struct(self, pole);
3610 
3611  dispParams.cArgs = RARRAY_LEN(args);
3612  dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs);
3613  realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs);
3614  for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--)
3615  {
3616  VariantInit(&realargs[i]);
3617  VariantInit(&dispParams.rgvarg[i]);
3618  tp = rb_ary_entry(types, j);
3619  vt = (VARTYPE)FIX2INT(tp);
3620  V_VT(&dispParams.rgvarg[i]) = vt;
3621  param = rb_ary_entry(args, j);
3622  if (param == Qnil)
3623  {
3624 
3625  V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR;
3626  V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND;
3627  }
3628  else
3629  {
3630  if (vt & VT_ARRAY)
3631  {
3632  int ent;
3633  LPBYTE pb;
3634  short* ps;
3635  LPLONG pl;
3636  VARIANT* pv;
3637  CY *py;
3638  VARTYPE v;
3639  SAFEARRAYBOUND rgsabound[1];
3640  Check_Type(param, T_ARRAY);
3641  rgsabound[0].lLbound = 0;
3642  rgsabound[0].cElements = RARRAY_LEN(param);
3643  v = vt & ~(VT_ARRAY | VT_BYREF);
3644  V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound);
3645  V_VT(&realargs[i]) = VT_ARRAY | v;
3646  SafeArrayLock(V_ARRAY(&realargs[i]));
3647  pb = V_ARRAY(&realargs[i])->pvData;
3648  ps = V_ARRAY(&realargs[i])->pvData;
3649  pl = V_ARRAY(&realargs[i])->pvData;
3650  py = V_ARRAY(&realargs[i])->pvData;
3651  pv = V_ARRAY(&realargs[i])->pvData;
3652  for (ent = 0; ent < (int)rgsabound[0].cElements; ent++)
3653  {
3654  VARIANT velem;
3655  VALUE elem = rb_ary_entry(param, ent);
3656  ole_val2variant(elem, &velem);
3657  if (v != VT_VARIANT)
3658  {
3659  VariantChangeTypeEx(&velem, &velem,
3660  cWIN32OLE_lcid, 0, v);
3661  }
3662  switch (v)
3663  {
3664  /* 128 bits */
3665  case VT_VARIANT:
3666  *pv++ = velem;
3667  break;
3668  /* 64 bits */
3669  case VT_R8:
3670  case VT_CY:
3671  case VT_DATE:
3672  *py++ = V_CY(&velem);
3673  break;
3674  /* 16 bits */
3675  case VT_BOOL:
3676  case VT_I2:
3677  case VT_UI2:
3678  *ps++ = V_I2(&velem);
3679  break;
3680  /* 8 bites */
3681  case VT_UI1:
3682  case VT_I1:
3683  *pb++ = V_UI1(&velem);
3684  break;
3685  /* 32 bits */
3686  default:
3687  *pl++ = V_I4(&velem);
3688  break;
3689  }
3690  }
3691  SafeArrayUnlock(V_ARRAY(&realargs[i]));
3692  }
3693  else
3694  {
3695  ole_val2variant(param, &realargs[i]);
3696  if ((vt & (~VT_BYREF)) != VT_VARIANT)
3697  {
3698  hr = VariantChangeTypeEx(&realargs[i], &realargs[i],
3699  cWIN32OLE_lcid, 0,
3700  (VARTYPE)(vt & (~VT_BYREF)));
3701  if (hr != S_OK)
3702  {
3703  rb_raise(rb_eTypeError, "not valid value");
3704  }
3705  }
3706  }
3707  if ((vt & VT_BYREF) || vt == VT_VARIANT)
3708  {
3709  if (vt == VT_VARIANT)
3710  V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF;
3711  switch (vt & (~VT_BYREF))
3712  {
3713  /* 128 bits */
3714  case VT_VARIANT:
3715  V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i];
3716  break;
3717  /* 64 bits */
3718  case VT_R8:
3719  case VT_CY:
3720  case VT_DATE:
3721  V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]);
3722  break;
3723  /* 16 bits */
3724  case VT_BOOL:
3725  case VT_I2:
3726  case VT_UI2:
3727  V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]);
3728  break;
3729  /* 8 bites */
3730  case VT_UI1:
3731  case VT_I1:
3732  V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]);
3733  break;
3734  /* 32 bits */
3735  default:
3736  V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]);
3737  break;
3738  }
3739  }
3740  else
3741  {
3742  /* copy 64 bits of data */
3743  V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]);
3744  }
3745  }
3746  }
3747 
3748  if (dispkind & DISPATCH_PROPERTYPUT) {
3749  dispParams.cNamedArgs = 1;
3750  dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
3751  dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
3752  }
3753 
3754  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid),
3755  &IID_NULL, cWIN32OLE_lcid,
3756  dispkind,
3757  &dispParams, &result,
3758  &excepinfo, &argErr);
3759 
3760  if (FAILED(hr)) {
3761  v = ole_excepinfo2msg(&excepinfo);
3762  ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s",
3763  NUM2INT(dispid),
3764  StringValuePtr(v));
3765  }
3766 
3767  /* clear dispatch parameter */
3768  if(dispParams.cArgs > 0) {
3769  set_argv(realargs, 0, dispParams.cArgs);
3770  }
3771 
3772  obj = ole_variant2val(&result);
3773  VariantClear(&result);
3774  return obj;
3775 }
3776 
3777 /*
3778  * call-seq:
3779  * WIN32OLE#_invoke(dispid, args, types)
3780  *
3781  * Runs the early binding method.
3782  * The 1st argument specifies dispatch ID,
3783  * the 2nd argument specifies the array of arguments,
3784  * the 3rd argument specifies the array of the type of arguments.
3785  *
3786  * excel = WIN32OLE.new('Excel.Application')
3787  * excel._invoke(302, [], []) # same effect as excel.Quit
3788  */
3789 static VALUE
3790 fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
3791 {
3792  return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD);
3793 }
3794 
3795 /*
3796  * call-seq:
3797  * WIN32OLE#_getproperty(dispid, args, types)
3798  *
3799  * Runs the early binding method to get property.
3800  * The 1st argument specifies dispatch ID,
3801  * the 2nd argument specifies the array of arguments,
3802  * the 3rd argument specifies the array of the type of arguments.
3803  *
3804  * excel = WIN32OLE.new('Excel.Application')
3805  * puts excel._getproperty(558, [], []) # same effect as puts excel.visible
3806  */
3807 static VALUE
3808 fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
3809 {
3810  return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET);
3811 }
3812 
3813 /*
3814  * call-seq:
3815  * WIN32OLE#_setproperty(dispid, args, types)
3816  *
3817  * Runs the early binding method to set property.
3818  * The 1st argument specifies dispatch ID,
3819  * the 2nd argument specifies the array of arguments,
3820  * the 3rd argument specifies the array of the type of arguments.
3821  *
3822  * excel = WIN32OLE.new('Excel.Application')
3823  * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true
3824  */
3825 static VALUE
3826 fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
3827 {
3828  return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT);
3829 }
3830 
3831 /*
3832  * call-seq:
3833  * WIN32OLE[a1, a2, ...]=val
3834  *
3835  * Sets the value to WIN32OLE object specified by a1, a2, ...
3836  *
3837  * dict = WIN32OLE.new('Scripting.Dictionary')
3838  * dict.add('ruby', 'RUBY')
3839  * dict['ruby'] = 'Ruby'
3840  * puts dict['ruby'] # => 'Ruby'
3841  *
3842  * Remark: You can not use this method to set the property value.
3843  *
3844  * excel = WIN32OLE.new('Excel.Application')
3845  * # excel['Visible'] = true # This is error !!!
3846  * excel.Visible = true # You should to use this style to set the property.
3847  *
3848  */
3849 static VALUE
3851 {
3852  return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE);
3853 }
3854 
3855 /*
3856  * call-seq:
3857  * WIN32OLE.setproperty('property', [arg1, arg2,...] val)
3858  *
3859  * Sets property of OLE object.
3860  * When you want to set property with argument, you can use this method.
3861  *
3862  * excel = WIN32OLE.new('Excel.Application')
3863  * excel.Visible = true
3864  * book = excel.workbooks.add
3865  * sheet = book.worksheets(1)
3866  * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10.
3867  */
3868 static VALUE
3870 {
3871  return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE);
3872 }
3873 
3874 /*
3875  * call-seq:
3876  * WIN32OLE[a1,a2,...]
3877  *
3878  * Returns the value of Collection specified by a1, a2,....
3879  *
3880  * dict = WIN32OLE.new('Scripting.Dictionary')
3881  * dict.add('ruby', 'Ruby')
3882  * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')')
3883  *
3884  * Remark: You can not use this method to get the property.
3885  * excel = WIN32OLE.new('Excel.Application')
3886  * # puts excel['Visible'] This is error !!!
3887  * puts excel.Visible # You should to use this style to get the property.
3888  *
3889  */
3890 static VALUE
3892 {
3893  return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE);
3894 }
3895 
3896 static VALUE
3897 ole_propertyput(VALUE self, VALUE property, VALUE value)
3898 {
3899  struct oledata *pole;
3900  unsigned argErr;
3901  unsigned int index;
3902  HRESULT hr;
3903  EXCEPINFO excepinfo;
3904  DISPID dispID = DISPID_VALUE;
3905  DISPID dispIDParam = DISPID_PROPERTYPUT;
3906  USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF;
3907  DISPPARAMS dispParams;
3908  VARIANTARG propertyValue[2];
3909  OLECHAR* pBuf[1];
3910  VALUE v;
3911  LCID lcid = cWIN32OLE_lcid;
3912  dispParams.rgdispidNamedArgs = &dispIDParam;
3913  dispParams.rgvarg = propertyValue;
3914  dispParams.cNamedArgs = 1;
3915  dispParams.cArgs = 1;
3916 
3917  VariantInit(&propertyValue[0]);
3918  VariantInit(&propertyValue[1]);
3919  memset(&excepinfo, 0, sizeof(excepinfo));
3920 
3921  OLEData_Get_Struct(self, pole);
3922 
3923  /* get ID from property name */
3924  pBuf[0] = ole_vstr2wc(property);
3925  hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL,
3926  pBuf, 1, lcid, &dispID);
3927  SysFreeString(pBuf[0]);
3928  pBuf[0] = NULL;
3929 
3930  if(FAILED(hr)) {
3932  "unknown property or method: `%s'",
3933  StringValuePtr(property));
3934  }
3935  /* set property value */
3936  ole_val2variant(value, &propertyValue[0]);
3937  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL,
3938  lcid, wFlags, &dispParams,
3939  NULL, &excepinfo, &argErr);
3940 
3941  for(index = 0; index < dispParams.cArgs; ++index) {
3942  VariantClear(&propertyValue[index]);
3943  }
3944  if (FAILED(hr)) {
3945  v = ole_excepinfo2msg(&excepinfo);
3946  ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s",
3947  StringValuePtr(property),
3948  StringValuePtr(v));
3949  }
3950  return Qnil;
3951 }
3952 
3953 /*
3954  * call-seq:
3955  * WIN32OLE#ole_free
3956  *
3957  * invokes Release method of Dispatch interface of WIN32OLE object.
3958  * Usually, you do not need to call this method because Release method
3959  * called automatically when WIN32OLE object garbaged.
3960  *
3961  */
3962 static VALUE
3964 {
3965  struct oledata *pole;
3966  rb_secure(4);
3967  OLEData_Get_Struct(self, pole);
3968  OLE_FREE(pole->pDispatch);
3969  pole->pDispatch = NULL;
3970  return Qnil;
3971 }
3972 
3973 static VALUE
3975 {
3976  VARIANT variant;
3977  VALUE obj = Qnil;
3978  IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
3979  VariantInit(&variant);
3980  while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) {
3981  obj = ole_variant2val(&variant);
3982  VariantClear(&variant);
3983  VariantInit(&variant);
3984  rb_yield(obj);
3985  }
3986  return Qnil;
3987 }
3988 
3989 static VALUE
3991 {
3992  IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
3993  OLE_RELEASE(pEnum);
3994  return Qnil;
3995 }
3996 
3997 /*
3998  * call-seq:
3999  * WIN32OLE#each {|i|...}
4000  *
4001  * Iterates over each item of OLE collection which has IEnumVARIANT interface.
4002  *
4003  * excel = WIN32OLE.new('Excel.Application')
4004  * book = excel.workbooks.add
4005  * sheets = book.worksheets(1)
4006  * cells = sheets.cells("A1:A5")
4007  * cells.each do |cell|
4008  * cell.value = 10
4009  * end
4010  */
4011 static VALUE
4013 {
4014  LCID lcid = cWIN32OLE_lcid;
4015 
4016  struct oledata *pole;
4017 
4018  unsigned int argErr;
4019  EXCEPINFO excepinfo;
4020  DISPPARAMS dispParams;
4021  VARIANT result;
4022  HRESULT hr;
4023  IEnumVARIANT *pEnum = NULL;
4024  void *p;
4025 
4026  RETURN_ENUMERATOR(self, 0, 0);
4027 
4028  VariantInit(&result);
4029  dispParams.rgvarg = NULL;
4030  dispParams.rgdispidNamedArgs = NULL;
4031  dispParams.cNamedArgs = 0;
4032  dispParams.cArgs = 0;
4033  memset(&excepinfo, 0, sizeof(excepinfo));
4034 
4035  OLEData_Get_Struct(self, pole);
4036  hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM,
4037  &IID_NULL, lcid,
4038  DISPATCH_METHOD | DISPATCH_PROPERTYGET,
4039  &dispParams, &result,
4040  &excepinfo, &argErr);
4041 
4042  if (FAILED(hr)) {
4043  VariantClear(&result);
4044  ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface");
4045  }
4046 
4047  if (V_VT(&result) == VT_UNKNOWN) {
4048  hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result),
4049  &IID_IEnumVARIANT,
4050  &p);
4051  pEnum = p;
4052  } else if (V_VT(&result) == VT_DISPATCH) {
4053  hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result),
4054  &IID_IEnumVARIANT,
4055  &p);
4056  pEnum = p;
4057  }
4058  if (FAILED(hr) || !pEnum) {
4059  VariantClear(&result);
4060  ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface");
4061  }
4062 
4063  VariantClear(&result);
4064  rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
4065  return Qnil;
4066 }
4067 
4068 /*
4069  * call-seq:
4070  * WIN32OLE#method_missing(id [,arg1, arg2, ...])
4071  *
4072  * Calls WIN32OLE#invoke method.
4073  */
4074 static VALUE
4076 {
4077  ID id;
4078  const char* mname;
4079  int n;
4080  id = rb_to_id(argv[0]);
4081  mname = rb_id2name(id);
4082  if(!mname) {
4083  rb_raise(rb_eRuntimeError, "fail: unknown method or property");
4084  }
4085  n = strlen(mname);
4086  if(mname[n-1] == '=') {
4087  argv[0] = rb_enc_str_new(mname, n-1, cWIN32OLE_enc);
4088 
4089  return ole_propertyput(self, argv[0], argv[1]);
4090  }
4091  else {
4092  argv[0] = rb_enc_str_new(mname, n, cWIN32OLE_enc);
4093  return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
4094  }
4095 }
4096 
4097 static VALUE
4098 ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name)
4099 {
4100  HRESULT hr;
4101  TYPEATTR *pTypeAttr;
4102  BSTR bstr;
4103  FUNCDESC *pFuncDesc;
4104  WORD i;
4105  VALUE fname;
4106  VALUE method = Qnil;
4107  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4108  if (FAILED(hr)) {
4109  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4110  }
4111  for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) {
4112  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
4113  if (FAILED(hr))
4114  continue;
4115 
4116  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
4117  &bstr, NULL, NULL, NULL);
4118  if (FAILED(hr)) {
4119  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
4120  continue;
4121  }
4122  fname = WC2VSTR(bstr);
4123  if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) {
4124  olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname);
4125  method = self;
4126  }
4127  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
4128  pFuncDesc=NULL;
4129  }
4130  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4131  return method;
4132 }
4133 
4134 static VALUE
4135 olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
4136 {
4137  HRESULT hr;
4138  TYPEATTR *pTypeAttr;
4139  WORD i;
4140  HREFTYPE href;
4141  ITypeInfo *pRefTypeInfo;
4142  VALUE method = Qnil;
4143  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4144  if (FAILED(hr)) {
4145  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4146  }
4147  method = ole_method_sub(self, 0, pTypeInfo, name);
4148  if (method != Qnil) {
4149  return method;
4150  }
4151  for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){
4152  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
4153  if(FAILED(hr))
4154  continue;
4155  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
4156  if (FAILED(hr))
4157  continue;
4158  method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name);
4159  OLE_RELEASE(pRefTypeInfo);
4160  }
4161  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4162  return method;
4163 }
4164 
4165 static VALUE
4166 ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask)
4167 {
4168  HRESULT hr;
4169  TYPEATTR *pTypeAttr;
4170  BSTR bstr;
4171  FUNCDESC *pFuncDesc;
4172  VALUE method;
4173  WORD i;
4174  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4175  if (FAILED(hr)) {
4176  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4177  }
4178  for(i = 0; i < pTypeAttr->cFuncs; i++) {
4179  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
4180  if (FAILED(hr))
4181  continue;
4182 
4183  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
4184  &bstr, NULL, NULL, NULL);
4185  if (FAILED(hr)) {
4186  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
4187  continue;
4188  }
4189  if(pFuncDesc->invkind & mask) {
4191  olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo,
4192  i, WC2VSTR(bstr));
4193  rb_ary_push(methods, method);
4194  }
4195  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
4196  pFuncDesc=NULL;
4197  }
4198  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4199 
4200  return methods;
4201 }
4202 
4203 static VALUE
4204 ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
4205 {
4206  HRESULT hr;
4207  TYPEATTR *pTypeAttr;
4208  WORD i;
4209  HREFTYPE href;
4210  ITypeInfo *pRefTypeInfo;
4211  VALUE methods = rb_ary_new();
4212  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4213  if (FAILED(hr)) {
4214  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4215  }
4216 
4217  ole_methods_sub(0, pTypeInfo, methods, mask);
4218  for(i=0; i < pTypeAttr->cImplTypes; i++){
4219  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
4220  if(FAILED(hr))
4221  continue;
4222  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
4223  if (FAILED(hr))
4224  continue;
4225  ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask);
4226  OLE_RELEASE(pRefTypeInfo);
4227  }
4228  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4229  return methods;
4230 }
4231 
4232 static HRESULT
4233 typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti)
4234 {
4235  ITypeInfo *pTypeInfo;
4236  ITypeLib *pTypeLib;
4237  BSTR bstr;
4238  VALUE type;
4239  UINT i;
4240  UINT count;
4241  LCID lcid = cWIN32OLE_lcid;
4242  HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
4243  0, lcid, &pTypeInfo);
4244  if(FAILED(hr)) {
4245  ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
4246  }
4247  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo,
4248  -1,
4249  &bstr,
4250  NULL, NULL, NULL);
4251  type = WC2VSTR(bstr);
4252  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
4253  OLE_RELEASE(pTypeInfo);
4254  if (FAILED(hr)) {
4255  ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib");
4256  }
4257  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
4258  for (i = 0; i < count; i++) {
4259  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
4260  &bstr, NULL, NULL, NULL);
4261  if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) {
4262  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
4263  if (SUCCEEDED(hr)) {
4264  *ppti = pTypeInfo;
4265  break;
4266  }
4267  }
4268  }
4269  OLE_RELEASE(pTypeLib);
4270  return hr;
4271 }
4272 
4273 static VALUE
4274 ole_methods(VALUE self, int mask)
4275 {
4276  ITypeInfo *pTypeInfo;
4277  HRESULT hr;
4278  VALUE methods;
4279  struct oledata *pole;
4280 
4281  OLEData_Get_Struct(self, pole);
4282  methods = rb_ary_new();
4283 
4284  hr = typeinfo_from_ole(pole, &pTypeInfo);
4285  if(FAILED(hr))
4286  return methods;
4287  rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask));
4288  OLE_RELEASE(pTypeInfo);
4289  return methods;
4290 }
4291 
4292 /*
4293  * call-seq:
4294  * WIN32OLE#ole_methods
4295  *
4296  * Returns the array of WIN32OLE_METHOD object.
4297  * The element is OLE method of WIN32OLE object.
4298  *
4299  * excel = WIN32OLE.new('Excel.Application')
4300  * methods = excel.ole_methods
4301  *
4302  */
4303 static VALUE
4305 {
4306  return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
4307 }
4308 
4309 /*
4310  * call-seq:
4311  * WIN32OLE#ole_get_methods
4312  *
4313  * Returns the array of WIN32OLE_METHOD object .
4314  * The element of the array is property (gettable) of WIN32OLE object.
4315  *
4316  * excel = WIN32OLE.new('Excel.Application')
4317  * properties = excel.ole_get_methods
4318  */
4319 static VALUE
4321 {
4322  return ole_methods( self, INVOKE_PROPERTYGET);
4323 }
4324 
4325 /*
4326  * call-seq:
4327  * WIN32OLE#ole_put_methods
4328  *
4329  * Returns the array of WIN32OLE_METHOD object .
4330  * The element of the array is property (settable) of WIN32OLE object.
4331  *
4332  * excel = WIN32OLE.new('Excel.Application')
4333  * properties = excel.ole_put_methods
4334  */
4335 static VALUE
4337 {
4338  return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF);
4339 }
4340 
4341 /*
4342  * call-seq:
4343  * WIN32OLE#ole_func_methods
4344  *
4345  * Returns the array of WIN32OLE_METHOD object .
4346  * The element of the array is property (settable) of WIN32OLE object.
4347  *
4348  * excel = WIN32OLE.new('Excel.Application')
4349  * properties = excel.ole_func_methods
4350  *
4351  */
4352 static VALUE
4354 {
4355  return ole_methods( self, INVOKE_FUNC);
4356 }
4357 
4358 static VALUE
4359 ole_type_from_itypeinfo(ITypeInfo *pTypeInfo)
4360 {
4361  ITypeLib *pTypeLib;
4362  VALUE type = Qnil;
4363  HRESULT hr;
4364  unsigned int index;
4365  BSTR bstr;
4366 
4367  hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index );
4368  if(FAILED(hr)) {
4369  return Qnil;
4370  }
4371  hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index,
4372  &bstr, NULL, NULL, NULL);
4373  OLE_RELEASE(pTypeLib);
4374  if (FAILED(hr)) {
4375  return Qnil;
4376  }
4378  oletype_set_member(type, pTypeInfo, WC2VSTR(bstr));
4379  return type;
4380 }
4381 
4382 /*
4383  * call-seq:
4384  * WIN32OLE#ole_type
4385  *
4386  * Returns WIN32OLE_TYPE object.
4387  *
4388  * excel = WIN32OLE.new('Excel.Application')
4389  * tobj = excel.ole_type
4390  */
4391 static VALUE
4393 {
4394  ITypeInfo *pTypeInfo;
4395  HRESULT hr;
4396  struct oledata *pole;
4397  LCID lcid = cWIN32OLE_lcid;
4398  VALUE type = Qnil;
4399 
4400  OLEData_Get_Struct(self, pole);
4401 
4402  hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo );
4403  if(FAILED(hr)) {
4404  ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
4405  }
4406  type = ole_type_from_itypeinfo(pTypeInfo);
4407  OLE_RELEASE(pTypeInfo);
4408  if (type == Qnil) {
4409  rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo");
4410  }
4411  return type;
4412 }
4413 
4414 static VALUE
4415 ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
4416 {
4417  HRESULT hr;
4418  ITypeLib *pTypeLib;
4419  unsigned int index;
4420  VALUE retval = Qnil;
4421 
4422  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
4423  if(FAILED(hr)) {
4424  return Qnil;
4425  }
4426  retval = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0);
4427  oletypelib_set_member(retval, pTypeLib);
4428  return retval;
4429 }
4430 
4431 /*
4432  * call-seq:
4433  * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object
4434  *
4435  * Returns the WIN32OLE_TYPELIB object. The object represents the
4436  * type library which contains the WIN32OLE object.
4437  *
4438  * excel = WIN32OLE.new('Excel.Application')
4439  * tlib = excel.ole_typelib
4440  * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library'
4441  */
4442 static VALUE
4444 {
4445  struct oledata *pole;
4446  HRESULT hr;
4447  ITypeInfo *pTypeInfo;
4448  LCID lcid = cWIN32OLE_lcid;
4449  VALUE vtlib = Qnil;
4450 
4451  OLEData_Get_Struct(self, pole);
4452  hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
4453  0, lcid, &pTypeInfo);
4454  if(FAILED(hr)) {
4455  ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
4456  }
4457  vtlib = ole_typelib_from_itypeinfo(pTypeInfo);
4458  OLE_RELEASE(pTypeInfo);
4459  if (vtlib == Qnil) {
4460  rb_raise(rb_eRuntimeError, "failed to get type library info.");
4461  }
4462  return vtlib;
4463 }
4464 
4465 /*
4466  * call-seq:
4467  * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object
4468  *
4469  * Returns WIN32OLE object for a specific dispatch or dual
4470  * interface specified by iid.
4471  *
4472  * ie = WIN32OLE.new('InternetExplorer.Application')
4473  * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp
4474  */
4475 static VALUE
4477 {
4478  HRESULT hr;
4479  OLECHAR *pBuf;
4480  IID iid;
4481  struct oledata *pole;
4482  IDispatch *pDispatch;
4483  void *p;
4484 
4485  pBuf = ole_vstr2wc(str_iid);
4486  hr = CLSIDFromString(pBuf, &iid);
4487  SysFreeString(pBuf);
4488  if(FAILED(hr)) {
4490  "invalid iid: `%s'",
4491  StringValuePtr(str_iid));
4492  }
4493 
4494  OLEData_Get_Struct(self, pole);
4495  if(!pole->pDispatch) {
4496  rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
4497  }
4498 
4499  hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid,
4500  &p);
4501  if(FAILED(hr)) {
4503  "failed to get interface `%s'",
4504  StringValuePtr(str_iid));
4505  }
4506 
4507  pDispatch = p;
4508  return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
4509 }
4510 
4511 /*
4512  * call-seq:
4513  * WIN32OLE#ole_respond_to?(method) -> true or false
4514  *
4515  * Returns true when OLE object has OLE method, otherwise returns false.
4516  *
4517  * ie = WIN32OLE.new('InternetExplorer.Application')
4518  * ie.ole_respond_to?("gohome") => true
4519  */
4520 static VALUE
4522 {
4523  struct oledata *pole;
4524  BSTR wcmdname;
4525  DISPID DispID;
4526  HRESULT hr;
4527  rb_secure(4);
4528  if(TYPE(method) != T_STRING && TYPE(method) != T_SYMBOL) {
4529  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
4530  }
4531  if (TYPE(method) == T_SYMBOL) {
4532  method = rb_sym_to_s(method);
4533  }
4534  OLEData_Get_Struct(self, pole);
4535  wcmdname = ole_vstr2wc(method);
4536  hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
4537  &wcmdname, 1, cWIN32OLE_lcid, &DispID);
4538  SysFreeString(wcmdname);
4539  return SUCCEEDED(hr) ? Qtrue : Qfalse;
4540 }
4541 
4542 static HRESULT
4543 ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
4544 {
4545  HRESULT hr;
4546  ITypeLib *pTypeLib;
4547  UINT i;
4548 
4549  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
4550  if (FAILED(hr)) {
4551  return hr;
4552  }
4553 
4554  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
4555  name, helpstr,
4556  helpcontext, helpfile);
4557  if (FAILED(hr)) {
4558  OLE_RELEASE(pTypeLib);
4559  return hr;
4560  }
4561  OLE_RELEASE(pTypeLib);
4562  return hr;
4563 }
4564 
4565 static VALUE
4566 ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
4567 {
4568  HRESULT hr;
4569  BSTR bstr;
4570  ITypeInfo *pRefTypeInfo;
4571  VALUE type = Qnil;
4572 
4573  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
4574  V_UNION1(pTypeDesc, hreftype),
4575  &pRefTypeInfo);
4576  if(FAILED(hr))
4577  return Qnil;
4578  hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL);
4579  if(FAILED(hr)) {
4580  OLE_RELEASE(pRefTypeInfo);
4581  return Qnil;
4582  }
4583  OLE_RELEASE(pRefTypeInfo);
4584  type = WC2VSTR(bstr);
4585  if(typedetails != Qnil)
4586  rb_ary_push(typedetails, type);
4587  return type;
4588 }
4589 
4590 static VALUE
4591 ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
4592 {
4593  TYPEDESC *p = pTypeDesc;
4594  VALUE type = rb_str_new2("");
4595 
4596  if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) {
4597  p = V_UNION1(p, lptdesc);
4598  type = ole_typedesc2val(pTypeInfo, p, typedetails);
4599  }
4600  return type;
4601 }
4602 
4603 static VALUE
4604 ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
4605 {
4606  VALUE str;
4607  VALUE typestr = Qnil;
4608  switch(pTypeDesc->vt) {
4609  case VT_I2:
4610  typestr = rb_str_new2("I2");
4611  break;
4612  case VT_I4:
4613  typestr = rb_str_new2("I4");
4614  break;
4615  case VT_R4:
4616  typestr = rb_str_new2("R4");
4617  break;
4618  case VT_R8:
4619  typestr = rb_str_new2("R8");
4620  break;
4621  case VT_CY:
4622  typestr = rb_str_new2("CY");
4623  break;
4624  case VT_DATE:
4625  typestr = rb_str_new2("DATE");
4626  break;
4627  case VT_BSTR:
4628  typestr = rb_str_new2("BSTR");
4629  break;
4630  case VT_BOOL:
4631  typestr = rb_str_new2("BOOL");
4632  break;
4633  case VT_VARIANT:
4634  typestr = rb_str_new2("VARIANT");
4635  break;
4636  case VT_DECIMAL:
4637  typestr = rb_str_new2("DECIMAL");
4638  break;
4639  case VT_I1:
4640  typestr = rb_str_new2("I1");
4641  break;
4642  case VT_UI1:
4643  typestr = rb_str_new2("UI1");
4644  break;
4645  case VT_UI2:
4646  typestr = rb_str_new2("UI2");
4647  break;
4648  case VT_UI4:
4649  typestr = rb_str_new2("UI4");
4650  break;
4651 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
4652  case VT_I8:
4653  typestr = rb_str_new2("I8");
4654  break;
4655  case VT_UI8:
4656  typestr = rb_str_new2("UI8");
4657  break;
4658 #endif
4659  case VT_INT:
4660  typestr = rb_str_new2("INT");
4661  break;
4662  case VT_UINT:
4663  typestr = rb_str_new2("UINT");
4664  break;
4665  case VT_VOID:
4666  typestr = rb_str_new2("VOID");
4667  break;
4668  case VT_HRESULT:
4669  typestr = rb_str_new2("HRESULT");
4670  break;
4671  case VT_PTR:
4672  typestr = rb_str_new2("PTR");
4673  if(typedetails != Qnil)
4674  rb_ary_push(typedetails, typestr);
4675  return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
4676  case VT_SAFEARRAY:
4677  typestr = rb_str_new2("SAFEARRAY");
4678  if(typedetails != Qnil)
4679  rb_ary_push(typedetails, typestr);
4680  return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
4681  case VT_CARRAY:
4682  typestr = rb_str_new2("CARRAY");
4683  break;
4684  case VT_USERDEFINED:
4685  typestr = rb_str_new2("USERDEFINED");
4686  if (typedetails != Qnil)
4687  rb_ary_push(typedetails, typestr);
4688  str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails);
4689  if (str != Qnil) {
4690  return str;
4691  }
4692  return typestr;
4693  case VT_UNKNOWN:
4694  typestr = rb_str_new2("UNKNOWN");
4695  break;
4696  case VT_DISPATCH:
4697  typestr = rb_str_new2("DISPATCH");
4698  break;
4699  case VT_ERROR:
4700  typestr = rb_str_new2("ERROR");
4701  break;
4702  case VT_LPWSTR:
4703  typestr = rb_str_new2("LPWSTR");
4704  break;
4705  case VT_LPSTR:
4706  typestr = rb_str_new2("LPSTR");
4707  break;
4708  default:
4709  typestr = rb_str_new2("Unknown Type ");
4710  rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10));
4711  break;
4712  }
4713  if (typedetails != Qnil)
4714  rb_ary_push(typedetails, typestr);
4715  return typestr;
4716 }
4717 
4718 /*
4719  * call-seq:
4720  * WIN32OLE#ole_method_help(method)
4721  *
4722  * Returns WIN32OLE_METHOD object corresponding with method
4723  * specified by 1st argument.
4724  *
4725  * excel = WIN32OLE.new('Excel.Application')
4726  * method = excel.ole_method_help('Quit')
4727  *
4728  */
4729 static VALUE
4731 {
4732  ITypeInfo *pTypeInfo;
4733  HRESULT hr;
4734  struct oledata *pole;
4735  VALUE method, obj;
4736 
4737  SafeStringValue(cmdname);
4738  OLEData_Get_Struct(self, pole);
4739  hr = typeinfo_from_ole(pole, &pTypeInfo);
4740  if(FAILED(hr))
4741  ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo");
4743  obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname);
4744  OLE_RELEASE(pTypeInfo);
4745  if (obj == Qnil)
4746  rb_raise(eWIN32OLERuntimeError, "not found %s",
4747  StringValuePtr(cmdname));
4748  return obj;
4749 }
4750 
4751 /*
4752  * call-seq:
4753  * WIN32OLE#ole_activex_initialize() -> Qnil
4754  *
4755  * Initialize WIN32OLE object(ActiveX Control) by calling
4756  * IPersistMemory::InitNew.
4757  *
4758  * Before calling OLE method, some kind of the ActiveX controls
4759  * created with MFC should be initialized by calling
4760  * IPersistXXX::InitNew.
4761  *
4762  * If and only if you received the exception "HRESULT error code:
4763  * 0x8000ffff catastrophic failure", try this method before
4764  * invoking any ole_method.
4765  *
4766  * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control")
4767  * obj.ole_activex_initialize
4768  * obj.method(...)
4769  *
4770  */
4771 static VALUE
4773 {
4774  struct oledata *pole;
4775  IPersistMemory *pPersistMemory;
4776  void *p;
4777 
4778  HRESULT hr = S_OK;
4779 
4780  OLEData_Get_Struct(self, pole);
4781 
4782  hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p);
4783  pPersistMemory = p;
4784  if (SUCCEEDED(hr)) {
4785  hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory);
4786  OLE_RELEASE(pPersistMemory);
4787  if (SUCCEEDED(hr)) {
4788  return Qnil;
4789  }
4790  }
4791 
4792  if (FAILED(hr)) {
4793  ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control");
4794  }
4795 
4796  return Qnil;
4797 }
4798 
4799 /*
4800  * call-seq:
4801  * WIN32OLE_TYPE.ole_classes(typelib)
4802  *
4803  * Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library.
4804  * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead.
4805  */
4806 static VALUE
4808 {
4809  VALUE obj;
4810 
4811  /*
4812  rb_warn("%s is obsolete; use %s instead.",
4813  "WIN32OLE_TYPE.ole_classes",
4814  "WIN32OLE_TYPELIB.new(typelib).ole_types");
4815  */
4816  obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib);
4817  return rb_funcall(obj, rb_intern("ole_types"), 0);
4818 }
4819 
4820 /*
4821  * call-seq:
4822  * WIN32OLE_TYPE.typelibs
4823  *
4824  * Returns array of type libraries.
4825  * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead.
4826  *
4827  */
4828 static VALUE
4830 {
4831  /*
4832  rb_warn("%s is obsolete. use %s instead.",
4833  "WIN32OLE_TYPE.typelibs",
4834  "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}");
4835  */
4836  return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}");
4837 }
4838 
4839 /*
4840  * call-seq:
4841  * WIN32OLE_TYPE.progids
4842  *
4843  * Returns array of ProgID.
4844  */
4845 static VALUE
4847 {
4848  HKEY hclsids, hclsid;
4849  DWORD i;
4850  LONG err;
4851  VALUE clsid;
4852  VALUE v = rb_str_new2("");
4853  VALUE progids = rb_ary_new();
4854 
4855  err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids);
4856  if(err != ERROR_SUCCESS) {
4857  return progids;
4858  }
4859  for(i = 0; ; i++) {
4860  clsid = reg_enum_key(hclsids, i);
4861  if (clsid == Qnil)
4862  break;
4863  err = reg_open_vkey(hclsids, clsid, &hclsid);
4864  if (err != ERROR_SUCCESS)
4865  continue;
4866  if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil)
4867  rb_ary_push(progids, v);
4868  if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil)
4869  rb_ary_push(progids, v);
4870  RegCloseKey(hclsid);
4871  }
4872  RegCloseKey(hclsids);
4873  return progids;
4874 }
4875 
4876 static VALUE
4878 {
4879  struct oletypedata *poletype;
4880  VALUE obj;
4881  ole_initialize();
4882  obj = Data_Make_Struct(klass,struct oletypedata,0,oletype_free,poletype);
4883  poletype->pTypeInfo = NULL;
4884  return obj;
4885 }
4886 
4887 static VALUE
4889 {
4890  struct oletypedata *ptype;
4891  Data_Get_Struct(self, struct oletypedata, ptype);
4892  rb_ivar_set(self, rb_intern("name"), name);
4893  ptype->pTypeInfo = pTypeInfo;
4894  if(pTypeInfo) OLE_ADDREF(pTypeInfo);
4895  return self;
4896 }
4897 
4898 static VALUE
4899 oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
4900 {
4901 
4902  long count;
4903  int i;
4904  HRESULT hr;
4905  BSTR bstr;
4906  VALUE typelib;
4907  ITypeInfo *pTypeInfo;
4908 
4909  VALUE found = Qfalse;
4910 
4911  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
4912  for (i = 0; i < count && found == Qfalse; i++) {
4913  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
4914  if (FAILED(hr))
4915  continue;
4916  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
4917  &bstr, NULL, NULL, NULL);
4918  if (FAILED(hr))
4919  continue;
4920  typelib = WC2VSTR(bstr);
4921  if (rb_str_cmp(oleclass, typelib) == 0) {
4922  oletype_set_member(self, pTypeInfo, typelib);
4923  found = Qtrue;
4924  }
4925  OLE_RELEASE(pTypeInfo);
4926  }
4927  return found;
4928 }
4929 
4930 /*
4931  * Document-class: WIN32OLE_TYPELIB
4932  *
4933  * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information.
4934  */
4935 
4936 static VALUE
4937 oletypelib_set_member(VALUE self, ITypeLib *pTypeLib)
4938 {
4939  struct oletypelibdata *ptlib;
4940  Data_Get_Struct(self, struct oletypelibdata, ptlib);
4941  ptlib->pTypeLib = pTypeLib;
4942  return self;
4943 }
4944 
4945 static ITypeLib *
4947 {
4948  struct oletypelibdata *ptlib;
4949  Data_Get_Struct(self, struct oletypelibdata, ptlib);
4950  return ptlib->pTypeLib;
4951 }
4952 
4953 static void
4954 oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr)
4955 {
4956  HRESULT hr;
4957  hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr);
4958  if (FAILED(hr)) {
4960  "failed to get library attribute(TLIBATTR) from ITypeLib");
4961  }
4962 }
4963 
4964 /*
4965  * call-seq:
4966  *
4967  * WIN32OLE_TYPELIB.typelibs
4968  *
4969  * Returns the array of WIN32OLE_TYPELIB object.
4970  *
4971  * tlibs = WIN32OLE_TYPELIB.typelibs
4972  *
4973  */
4974 static VALUE
4976 {
4977  HKEY htypelib, hguid;
4978  DWORD i, j;
4979  LONG err;
4980  VALUE guid;
4981  VALUE version;
4982  VALUE name = Qnil;
4983  VALUE typelibs = rb_ary_new();
4984  VALUE typelib = Qnil;
4985  HRESULT hr;
4986  ITypeLib *pTypeLib;
4987 
4988  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
4989  if(err != ERROR_SUCCESS) {
4990  return typelibs;
4991  }
4992  for(i = 0; ; i++) {
4993  guid = reg_enum_key(htypelib, i);
4994  if (guid == Qnil)
4995  break;
4996  err = reg_open_vkey(htypelib, guid, &hguid);
4997  if (err != ERROR_SUCCESS)
4998  continue;
4999  for(j = 0; ; j++) {
5000  version = reg_enum_key(hguid, j);
5001  if (version == Qnil)
5002  break;
5003  if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) {
5004  hr = oletypelib_from_guid(guid, version, &pTypeLib);
5005  if (SUCCEEDED(hr)) {
5006  typelib = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0);
5007  oletypelib_set_member(typelib, pTypeLib);
5008  rb_ary_push(typelibs, typelib);
5009  }
5010  }
5011  }
5012  RegCloseKey(hguid);
5013  }
5014  RegCloseKey(htypelib);
5015  return typelibs;
5016 }
5017 
5018 static VALUE
5020 {
5021  VALUE version_str = Qnil;
5022  VALUE minor_str = Qnil;
5023  if (major == Qnil) {
5024  return Qnil;
5025  }
5026  version_str = rb_String(major);
5027  if (minor != Qnil) {
5028  minor_str = rb_String(minor);
5029  rb_str_cat2(version_str, ".");
5030  rb_str_append(version_str, minor_str);
5031  }
5032  return version_str;
5033 }
5034 
5035 static VALUE
5037 {
5038  HKEY htypelib, hguid, hversion;
5039  double fver;
5040  DWORD j;
5041  LONG err;
5042  VALUE found = Qfalse;
5043  VALUE tlib;
5044  VALUE ver;
5045  VALUE version_str;
5046  VALUE version = Qnil;
5047  VALUE typelib = Qnil;
5048  HRESULT hr;
5049  ITypeLib *pTypeLib;
5050 
5051  VALUE guid = rb_ary_entry(args, 0);
5052  version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2));
5053 
5054  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
5055  if(err != ERROR_SUCCESS) {
5056  return Qfalse;
5057  }
5058  err = reg_open_vkey(htypelib, guid, &hguid);
5059  if (err != ERROR_SUCCESS) {
5060  RegCloseKey(htypelib);
5061  return Qfalse;
5062  }
5063  if (version_str != Qnil) {
5064  err = reg_open_vkey(hguid, version_str, &hversion);
5065  if (err == ERROR_SUCCESS) {
5066  tlib = reg_get_val(hversion, NULL);
5067  if (tlib != Qnil) {
5068  typelib = tlib;
5069  version = version_str;
5070  }
5071  }
5072  RegCloseKey(hversion);
5073  } else {
5074  fver = 0.0;
5075  for(j = 0; ;j++) {
5076  ver = reg_enum_key(hguid, j);
5077  if (ver == Qnil)
5078  break;
5079  err = reg_open_vkey(hguid, ver, &hversion);
5080  if (err != ERROR_SUCCESS)
5081  continue;
5082  tlib = reg_get_val(hversion, NULL);
5083  if (tlib == Qnil) {
5084  RegCloseKey(hversion);
5085  continue;
5086  }
5087  if (fver < atof(StringValuePtr(ver))) {
5088  fver = atof(StringValuePtr(ver));
5089  version = ver;
5090  typelib = tlib;
5091  }
5092  RegCloseKey(hversion);
5093  }
5094  }
5095  RegCloseKey(hguid);
5096  RegCloseKey(htypelib);
5097  if (typelib != Qnil) {
5098  hr = oletypelib_from_guid(guid, version, &pTypeLib);
5099  if (SUCCEEDED(hr)) {
5100  found = Qtrue;
5101  oletypelib_set_member(self, pTypeLib);
5102  }
5103  }
5104  return found;
5105 }
5106 
5107 static VALUE
5109 {
5110  HKEY htypelib, hguid, hversion;
5111  DWORD i, j;
5112  LONG err;
5113  VALUE found = Qfalse;
5114  VALUE tlib;
5115  VALUE guid;
5116  VALUE ver;
5117  HRESULT hr;
5118  ITypeLib *pTypeLib;
5119 
5120  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
5121  if(err != ERROR_SUCCESS) {
5122  return Qfalse;
5123  }
5124  for(i = 0; !found; i++) {
5125  guid = reg_enum_key(htypelib, i);
5126  if (guid == Qnil)
5127  break;
5128  err = reg_open_vkey(htypelib, guid, &hguid);
5129  if (err != ERROR_SUCCESS)
5130  continue;
5131  for(j = 0; found == Qfalse; j++) {
5132  ver = reg_enum_key(hguid, j);
5133  if (ver == Qnil)
5134  break;
5135  err = reg_open_vkey(hguid, ver, &hversion);
5136  if (err != ERROR_SUCCESS)
5137  continue;
5138  tlib = reg_get_val(hversion, NULL);
5139  if (tlib == Qnil) {
5140  RegCloseKey(hversion);
5141  continue;
5142  }
5143  if (rb_str_cmp(typelib, tlib) == 0) {
5144  hr = oletypelib_from_guid(guid, ver, &pTypeLib);
5145  if (SUCCEEDED(hr)) {
5146  oletypelib_set_member(self, pTypeLib);
5147  found = Qtrue;
5148  }
5149  }
5150  RegCloseKey(hversion);
5151  }
5152  RegCloseKey(hguid);
5153  }
5154  RegCloseKey(htypelib);
5155  return found;
5156 }
5157 
5158 static VALUE
5160 {
5161  struct oletypelibdata *poletypelib;
5162  VALUE obj;
5163  ole_initialize();
5164  obj = Data_Make_Struct(klass, struct oletypelibdata, 0, oletypelib_free, poletypelib);
5165  poletypelib->pTypeLib = NULL;
5166  return obj;
5167 }
5168 
5169 /*
5170  * call-seq:
5171  * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object
5172  *
5173  * Returns a new WIN32OLE_TYPELIB object.
5174  *
5175  * The first argument <i>typelib</i> specifies OLE type library name or GUID or
5176  * OLE library file.
5177  * The second argument is major version or version of the type library.
5178  * The third argument is minor version.
5179  * The second argument and third argument are optional.
5180  * If the first argument is type library name, then the second and third argument
5181  * are ignored.
5182  *
5183  * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5184  * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}')
5185  * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3)
5186  * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
5187  * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
5188  * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library'
5189  * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library'
5190  * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library'
5191  * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library'
5192  * puts tlib5.name # -> 'Microsoft Shell Controls And Automation'
5193  *
5194  */
5195 static VALUE
5197 {
5198  VALUE found = Qfalse;
5199  VALUE typelib = Qnil;
5200  int len = 0;
5201  OLECHAR * pbuf;
5202  ITypeLib *pTypeLib;
5203  HRESULT hr = S_OK;
5204 
5205  len = RARRAY_LEN(args);
5206  if (len < 1 || len > 3) {
5207  rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
5208  }
5209 
5210  typelib = rb_ary_entry(args, 0);
5211 
5212  SafeStringValue(typelib);
5213 
5214  found = oletypelib_search_registry(self, typelib);
5215  if (found == Qfalse) {
5216  found = oletypelib_search_registry2(self, args);
5217  }
5218  if (found == Qfalse) {
5219  pbuf = ole_vstr2wc(typelib);
5220  hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
5221  SysFreeString(pbuf);
5222  if (SUCCEEDED(hr)) {
5223  found = Qtrue;
5224  oletypelib_set_member(self, pTypeLib);
5225  }
5226  }
5227 
5228  if (found == Qfalse) {
5229  rb_raise(eWIN32OLERuntimeError, "not found type library `%s`",
5230  StringValuePtr(typelib));
5231  }
5232  return self;
5233 }
5234 
5235 /*
5236  * call-seq:
5237  * WIN32OLE_TYPELIB#guid -> The guid string.
5238  *
5239  * Returns guid string which specifies type library.
5240  *
5241  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5242  * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}'
5243  */
5244 static VALUE
5246 {
5247  ITypeLib *pTypeLib;
5248  OLECHAR bstr[80];
5249  VALUE guid = Qnil;
5250  int len;
5251  TLIBATTR *pTLibAttr;
5252 
5253  pTypeLib = oletypelib_get_typelib(self);
5254  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
5255  len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
5256  if (len > 3) {
5257  guid = ole_wc2vstr(bstr, FALSE);
5258  }
5259  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5260  return guid;
5261 }
5262 
5263 /*
5264  * call-seq:
5265  * WIN32OLE_TYPELIB#name -> The type library name
5266  *
5267  * Returns the type library name.
5268  *
5269  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5270  * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library'
5271  */
5272 static VALUE
5274 {
5275  ITypeLib *pTypeLib;
5276  HRESULT hr;
5277  BSTR bstr;
5278  VALUE name;
5279  pTypeLib = oletypelib_get_typelib(self);
5280  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
5281  NULL, &bstr, NULL, NULL);
5282 
5283  if (FAILED(hr)) {
5284  ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib");
5285  }
5286  name = WC2VSTR(bstr);
5287  return rb_enc_str_new(StringValuePtr(name), strlen(StringValuePtr(name)), cWIN32OLE_enc);
5288 }
5289 
5290 /*
5291  * call-seq:
5292  * WIN32OLE_TYPELIB#version -> The type library version.
5293  *
5294  * Returns the type library version.
5295  *
5296  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5297  * puts tlib.version #-> 1.3
5298  */
5299 static VALUE
5301 {
5302  TLIBATTR *pTLibAttr;
5303  VALUE major;
5304  VALUE minor;
5305  ITypeLib *pTypeLib;
5306 
5307  pTypeLib = oletypelib_get_typelib(self);
5308  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
5309  major = INT2NUM(pTLibAttr->wMajorVerNum);
5310  minor = INT2NUM(pTLibAttr->wMinorVerNum);
5311  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5312  return rb_Float(make_version_str(major, minor));
5313 }
5314 
5315 /*
5316  * call-seq:
5317  * WIN32OLE_TYPELIB#major_version -> The type library major version.
5318  *
5319  * Returns the type library major version.
5320  *
5321  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5322  * puts tlib.major_version # -> 1
5323  */
5324 static VALUE
5326 {
5327  TLIBATTR *pTLibAttr;
5328  VALUE major;
5329  ITypeLib *pTypeLib;
5330  pTypeLib = oletypelib_get_typelib(self);
5331  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
5332 
5333  major = INT2NUM(pTLibAttr->wMajorVerNum);
5334  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5335  return major;
5336 }
5337 
5338 /*
5339  * call-seq:
5340  * WIN32OLE_TYPELIB#minor_version -> The type library minor version.
5341  *
5342  * Returns the type library minor version.
5343  *
5344  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5345  * puts tlib.minor_version # -> 3
5346  */
5347 static VALUE
5349 {
5350  TLIBATTR *pTLibAttr;
5351  VALUE minor;
5352  ITypeLib *pTypeLib;
5353  pTypeLib = oletypelib_get_typelib(self);
5354  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
5355  minor = INT2NUM(pTLibAttr->wMinorVerNum);
5356  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5357  return minor;
5358 }
5359 
5360 static VALUE
5362 {
5363  int k;
5364  LONG err;
5365  HKEY hkey;
5366  HKEY hlang;
5367  VALUE lang;
5368  VALUE path = Qnil;
5369 
5370  VALUE key = rb_str_new2("TypeLib\\");
5371  rb_str_concat(key, guid);
5372  rb_str_cat2(key, "\\");
5373  rb_str_concat(key, version);
5374 
5375  err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey);
5376  if (err != ERROR_SUCCESS) {
5377  return Qnil;
5378  }
5379  for(k = 0; path == Qnil; k++) {
5380  lang = reg_enum_key(hkey, k);
5381  if (lang == Qnil)
5382  break;
5383  err = reg_open_vkey(hkey, lang, &hlang);
5384  if (err == ERROR_SUCCESS) {
5385  path = reg_get_typelib_file_path(hlang);
5386  RegCloseKey(hlang);
5387  }
5388  }
5389  RegCloseKey(hkey);
5390  return path;
5391 }
5392 
5393 static HRESULT
5394 oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib)
5395 {
5396  VALUE path;
5397  OLECHAR *pBuf;
5398  HRESULT hr;
5399  path = oletypelib_path(guid, version);
5400  if (path == Qnil) {
5401  return E_UNEXPECTED;
5402  }
5403  pBuf = ole_vstr2wc(path);
5404  hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib);
5405  SysFreeString(pBuf);
5406  return hr;
5407 }
5408 
5409 /*
5410  * call-seq:
5411  * WIN32OLE_TYPELIB#path -> The type library file path.
5412  *
5413  * Returns the type library file path.
5414  *
5415  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5416  * puts tlib.path #-> 'C:\...\EXCEL9.OLB'
5417  */
5418 static VALUE
5420 {
5421  TLIBATTR *pTLibAttr;
5422  HRESULT hr = S_OK;
5423  BSTR bstr;
5424  LCID lcid = cWIN32OLE_lcid;
5425  VALUE path;
5426  ITypeLib *pTypeLib;
5427 
5428  pTypeLib = oletypelib_get_typelib(self);
5429  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
5430  hr = QueryPathOfRegTypeLib(&pTLibAttr->guid,
5431  pTLibAttr->wMajorVerNum,
5432  pTLibAttr->wMinorVerNum,
5433  lcid,
5434  &bstr);
5435  if (FAILED(hr)) {
5436  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5437  ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib");
5438  }
5439 
5440  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5441  path = WC2VSTR(bstr);
5442  return rb_enc_str_new(StringValuePtr(path), strlen(StringValuePtr(path)), cWIN32OLE_enc);
5443 }
5444 
5445 /*
5446  * call-seq:
5447  * WIN32OLE_TYPELIB#visible?
5448  *
5449  * Returns true if the type library information is not hidden.
5450  * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN,
5451  * the method returns false, otherwise, returns true.
5452  * If the method fails to access the TLIBATTR information, then
5453  * WIN32OLERuntimeError is raised.
5454  *
5455  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5456  * tlib.visible? # => true
5457  */
5458 static VALUE
5460 {
5461  ITypeLib *pTypeLib = NULL;
5462  VALUE visible = Qtrue;
5463  TLIBATTR *pTLibAttr;
5464 
5465  pTypeLib = oletypelib_get_typelib(self);
5466  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
5467 
5468  if ((pTLibAttr->wLibFlags == 0) ||
5469  (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) ||
5470  (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) {
5471  visible = Qfalse;
5472  }
5473  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5474  return visible;
5475 }
5476 
5477 /*
5478  * call-seq:
5479  * WIN32OLE_TYPELIB#library_name
5480  *
5481  * Returns library name.
5482  * If the method fails to access library name, WIN32OLERuntimeError is raised.
5483  *
5484  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5485  * tlib.library_name # => Excel
5486  */
5487 static VALUE
5489 {
5490  HRESULT hr;
5491  ITypeLib *pTypeLib = NULL;
5492  VALUE libname = Qnil;
5493  BSTR bstr;
5494 
5495  pTypeLib = oletypelib_get_typelib(self);
5496  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
5497  &bstr, NULL, NULL, NULL);
5498  if (FAILED(hr)) {
5499  ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name");
5500  }
5501  libname = WC2VSTR(bstr);
5502  return libname;
5503 }
5504 
5505 
5506 /*
5507  * call-seq:
5508  * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library.
5509  *
5510  * Returns the type library file path.
5511  *
5512  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5513  * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...]
5514  */
5515 static VALUE
5517 {
5518  ITypeLib *pTypeLib = NULL;
5519  VALUE classes = rb_ary_new();
5520  pTypeLib = oletypelib_get_typelib(self);
5521  ole_types_from_typelib(pTypeLib, classes);
5522  return classes;
5523 }
5524 
5525 /*
5526  * call-seq:
5527  * WIN32OLE_TYPELIB#inspect -> String
5528  *
5529  * Returns the type library name with class name.
5530  *
5531  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5532  * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>"
5533  */
5534 static VALUE
5536 {
5537  return default_inspect(self, "WIN32OLE_TYPELIB");
5538 }
5539 
5540 /*
5541  * Document-class: WIN32OLE_TYPE
5542  *
5543  * <code>WIN32OLE_TYPE</code> objects represent OLE type libarary information.
5544  */
5545 
5546 /*
5547  * call-seq:
5548  * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object
5549  *
5550  * Returns a new WIN32OLE_TYPE object.
5551  * The first argument <i>typelib</i> specifies OLE type library name.
5552  * The second argument specifies OLE class name.
5553  *
5554  * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5555  * # => WIN32OLE_TYPE object of Application class of Excel.
5556  */
5557 static VALUE
5558 foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
5559 {
5560  VALUE file;
5561  OLECHAR * pbuf;
5562  ITypeLib *pTypeLib;
5563  HRESULT hr;
5564 
5565  SafeStringValue(oleclass);
5566  SafeStringValue(typelib);
5567  file = typelib_file(typelib);
5568  if (file == Qnil) {
5569  file = typelib;
5570  }
5571  pbuf = ole_vstr2wc(file);
5572  hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
5573  if (FAILED(hr))
5574  ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
5575  SysFreeString(pbuf);
5576  if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) {
5577  OLE_RELEASE(pTypeLib);
5578  rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`",
5579  StringValuePtr(oleclass), StringValuePtr(typelib));
5580  }
5581  OLE_RELEASE(pTypeLib);
5582  return self;
5583 }
5584 
5585 /*
5586  * call-seq:
5587  * WIN32OLE_TYPE#name #=> OLE type name
5588  *
5589  * Returns OLE type name.
5590  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5591  * puts tobj.name # => Application
5592  */
5593 static VALUE
5595 {
5596  return rb_ivar_get(self, rb_intern("name"));
5597 }
5598 
5599 static VALUE
5600 ole_ole_type(ITypeInfo *pTypeInfo)
5601 {
5602  HRESULT hr;
5603  TYPEATTR *pTypeAttr;
5604  VALUE type = Qnil;
5605  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5606  if(FAILED(hr)){
5607  return type;
5608  }
5609  switch(pTypeAttr->typekind) {
5610  case TKIND_ENUM:
5611  type = rb_str_new2("Enum");
5612  break;
5613  case TKIND_RECORD:
5614  type = rb_str_new2("Record");
5615  break;
5616  case TKIND_MODULE:
5617  type = rb_str_new2("Module");
5618  break;
5619  case TKIND_INTERFACE:
5620  type = rb_str_new2("Interface");
5621  break;
5622  case TKIND_DISPATCH:
5623  type = rb_str_new2("Dispatch");
5624  break;
5625  case TKIND_COCLASS:
5626  type = rb_str_new2("Class");
5627  break;
5628  case TKIND_ALIAS:
5629  type = rb_str_new2("Alias");
5630  break;
5631  case TKIND_UNION:
5632  type = rb_str_new2("Union");
5633  break;
5634  case TKIND_MAX:
5635  type = rb_str_new2("Max");
5636  break;
5637  default:
5638  type = Qnil;
5639  break;
5640  }
5641  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5642  return type;
5643 }
5644 
5645 /*
5646  * call-seq:
5647  * WIN32OLE_TYPE#ole_type #=> OLE type string.
5648  *
5649  * returns type of OLE class.
5650  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5651  * puts tobj.ole_type # => Class
5652  */
5653 static VALUE
5655 {
5656  struct oletypedata *ptype;
5657  Data_Get_Struct(self, struct oletypedata, ptype);
5658  return ole_ole_type(ptype->pTypeInfo);
5659 }
5660 
5661 static VALUE
5663 {
5664  HRESULT hr;
5665  TYPEATTR *pTypeAttr;
5666  int len;
5667  OLECHAR bstr[80];
5668  VALUE guid = Qnil;
5669  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5670  if (FAILED(hr))
5671  return guid;
5672  len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
5673  if (len > 3) {
5674  guid = ole_wc2vstr(bstr, FALSE);
5675  }
5676  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5677  return guid;
5678 }
5679 
5680 /*
5681  * call-seq:
5682  * WIN32OLE_TYPE#guid #=> GUID
5683  *
5684  * Returns GUID.
5685  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5686  * puts tobj.guid # => {00024500-0000-0000-C000-000000000046}
5687  */
5688 static VALUE
5690 {
5691  struct oletypedata *ptype;
5692  Data_Get_Struct(self, struct oletypedata, ptype);
5693  return ole_type_guid(ptype->pTypeInfo);
5694 }
5695 
5696 static VALUE
5698 {
5699  HRESULT hr;
5700  TYPEATTR *pTypeAttr;
5701  OLECHAR *pbuf;
5702  VALUE progid = Qnil;
5703  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5704  if (FAILED(hr))
5705  return progid;
5706  hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf);
5707  if (SUCCEEDED(hr)) {
5708  progid = ole_wc2vstr(pbuf, FALSE);
5709  CoTaskMemFree(pbuf);
5710  }
5711  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5712  return progid;
5713 }
5714 
5715 /*
5716  * call-seq:
5717  * WIN32OLE_TYPE#progid #=> ProgID
5718  *
5719  * Returns ProgID if it exists. If not found, then returns nil.
5720  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5721  * puts tobj.progid # => Excel.Application.9
5722  */
5723 static VALUE
5725 {
5726  struct oletypedata *ptype;
5727  Data_Get_Struct(self, struct oletypedata, ptype);
5728  return ole_type_progid(ptype->pTypeInfo);
5729 }
5730 
5731 
5732 static VALUE
5734 {
5735  HRESULT hr;
5736  TYPEATTR *pTypeAttr;
5737  VALUE visible;
5738  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5739  if (FAILED(hr))
5740  return Qtrue;
5741  if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) {
5742  visible = Qfalse;
5743  } else {
5744  visible = Qtrue;
5745  }
5746  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5747  return visible;
5748 }
5749 
5750 /*
5751  * call-seq:
5752  * WIN32OLE_TYPE#visible #=> true or false
5753  *
5754  * Returns true if the OLE class is public.
5755  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5756  * puts tobj.visible # => true
5757  */
5758 static VALUE
5760 {
5761  struct oletypedata *ptype;
5762  Data_Get_Struct(self, struct oletypedata, ptype);
5763  return ole_type_visible(ptype->pTypeInfo);
5764 }
5765 
5766 static VALUE
5768 {
5769  VALUE ver;
5770  TYPEATTR *pTypeAttr;
5771  HRESULT hr;
5772  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5773  if (FAILED(hr))
5774  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5775  ver = INT2FIX(pTypeAttr->wMajorVerNum);
5776  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5777  return ver;
5778 }
5779 
5780 /*
5781  * call-seq:
5782  * WIN32OLE_TYPE#major_version
5783  *
5784  * Returns major version.
5785  * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
5786  * puts tobj.major_version # => 8
5787  */
5788 static VALUE
5790 {
5791  struct oletypedata *ptype;
5792  Data_Get_Struct(self, struct oletypedata, ptype);
5793  return ole_type_major_version(ptype->pTypeInfo);
5794 }
5795 
5796 static VALUE
5798 {
5799  VALUE ver;
5800  TYPEATTR *pTypeAttr;
5801  HRESULT hr;
5802  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5803  if (FAILED(hr))
5804  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5805  ver = INT2FIX(pTypeAttr->wMinorVerNum);
5806  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5807  return ver;
5808 }
5809 
5810 /*
5811  * call-seq:
5812  * WIN32OLE_TYPE#minor_version #=> OLE minor version
5813  *
5814  * Returns minor version.
5815  * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
5816  * puts tobj.minor_version # => 2
5817  */
5818 static VALUE
5820 {
5821  struct oletypedata *ptype;
5822  Data_Get_Struct(self, struct oletypedata, ptype);
5823  return ole_type_minor_version(ptype->pTypeInfo);
5824 }
5825 
5826 static VALUE
5828 {
5829  VALUE typekind;
5830  TYPEATTR *pTypeAttr;
5831  HRESULT hr;
5832  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5833  if (FAILED(hr))
5834  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5835  typekind = INT2FIX(pTypeAttr->typekind);
5836  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5837  return typekind;
5838 }
5839 
5840 /*
5841  * call-seq:
5842  * WIN32OLE_TYPE#typekind #=> number of type.
5843  *
5844  * Returns number which represents type.
5845  * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
5846  * puts tobj.typekind # => 4
5847  *
5848  */
5849 static VALUE
5851 {
5852  struct oletypedata *ptype;
5853  Data_Get_Struct(self, struct oletypedata, ptype);
5854  return ole_type_typekind(ptype->pTypeInfo);
5855 }
5856 
5857 static VALUE
5859 {
5860  HRESULT hr;
5861  BSTR bhelpstr;
5862  hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL);
5863  if(FAILED(hr)) {
5864  return Qnil;
5865  }
5866  return WC2VSTR(bhelpstr);
5867 }
5868 
5869 /*
5870  * call-seq:
5871  * WIN32OLE_TYPE#helpstring #=> help string.
5872  *
5873  * Returns help string.
5874  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
5875  * puts tobj.helpstring # => Web Browser interface
5876  */
5877 static VALUE
5879 {
5880  struct oletypedata *ptype;
5881  Data_Get_Struct(self, struct oletypedata, ptype);
5882  return ole_type_helpstring(ptype->pTypeInfo);
5883 }
5884 
5885 static VALUE
5887 {
5888  HRESULT hr;
5889  TYPEATTR *pTypeAttr;
5890  VALUE alias = Qnil;
5891  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5892  if (FAILED(hr))
5893  return alias;
5894  if(pTypeAttr->typekind != TKIND_ALIAS) {
5895  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5896  return alias;
5897  }
5898  alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil);
5899  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5900  return alias;
5901 }
5902 
5903 /*
5904  * call-seq:
5905  * WIN32OLE_TYPE#src_type #=> OLE source class
5906  *
5907  * Returns source class when the OLE class is 'Alias'.
5908  * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType')
5909  * puts tobj.src_type # => I4
5910  *
5911  */
5912 static VALUE
5914 {
5915  struct oletypedata *ptype;
5916  Data_Get_Struct(self, struct oletypedata, ptype);
5917  return ole_type_src_type(ptype->pTypeInfo);
5918 }
5919 
5920 static VALUE
5922 {
5923  HRESULT hr;
5924  BSTR bhelpfile;
5925  hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile);
5926  if(FAILED(hr)) {
5927  return Qnil;
5928  }
5929  return WC2VSTR(bhelpfile);
5930 }
5931 
5932 /*
5933  * call-seq:
5934  * WIN32OLE_TYPE#helpfile
5935  *
5936  * Returns helpfile path. If helpfile is not found, then returns nil.
5937  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5938  * puts tobj.helpfile # => C:\...\VBAXL9.CHM
5939  *
5940  */
5941 static VALUE
5943 {
5944  struct oletypedata *ptype;
5945  Data_Get_Struct(self, struct oletypedata, ptype);
5946  return ole_type_helpfile(ptype->pTypeInfo);
5947 }
5948 
5949 static VALUE
5951 {
5952  HRESULT hr;
5953  DWORD helpcontext;
5954  hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL,
5955  &helpcontext, NULL);
5956  if(FAILED(hr))
5957  return Qnil;
5958  return INT2FIX(helpcontext);
5959 }
5960 
5961 /*
5962  * call-seq:
5963  * WIN32OLE_TYPE#helpcontext
5964  *
5965  * Returns helpcontext. If helpcontext is not found, then returns nil.
5966  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5967  * puts tobj.helpfile # => 131185
5968  */
5969 static VALUE
5971 {
5972  struct oletypedata *ptype;
5973  Data_Get_Struct(self, struct oletypedata, ptype);
5974  return ole_type_helpcontext(ptype->pTypeInfo);
5975 }
5976 
5977 /*
5978  * call-seq:
5979  * WIN32OLE_TYPE#ole_typelib
5980  *
5981  * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE
5982  * object. If it is not found, then returns nil.
5983  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5984  * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library'
5985  */
5986 static VALUE
5988 {
5989  struct oletypedata *ptype;
5990  Data_Get_Struct(self, struct oletypedata, ptype);
5991  return ole_typelib_from_itypeinfo(ptype->pTypeInfo);
5992 }
5993 
5994 static VALUE
5995 ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
5996 {
5997  HRESULT hr;
5998  ITypeInfo *pRefTypeInfo;
5999  HREFTYPE href;
6000  WORD i;
6001  VALUE type;
6002  TYPEATTR *pTypeAttr;
6003  int flags;
6004 
6005  VALUE types = rb_ary_new();
6006  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
6007  if (FAILED(hr)) {
6008  return types;
6009  }
6010  for (i = 0; i < pTypeAttr->cImplTypes; i++) {
6011  hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
6012  if (FAILED(hr))
6013  continue;
6014 
6015  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
6016  if (FAILED(hr))
6017  continue;
6018  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
6019  if (FAILED(hr))
6020  continue;
6021 
6022  if ((flags & implflags) == implflags) {
6023  type = ole_type_from_itypeinfo(pRefTypeInfo);
6024  if (type != Qnil) {
6025  rb_ary_push(types, type);
6026  }
6027  }
6028 
6029  OLE_RELEASE(pRefTypeInfo);
6030  }
6031  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
6032  return types;
6033 }
6034 
6035 /*
6036  * call-seq:
6037  * WIN32OLE_TYPE#implemented_ole_types
6038  *
6039  * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
6040  * object.
6041  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
6042  * p tobj.implemented_ole_types # => [_Worksheet, DocEvents]
6043  */
6044 static VALUE
6046 {
6047  struct oletypedata *ptype;
6048  Data_Get_Struct(self, struct oletypedata, ptype);
6049  return ole_type_impl_ole_types(ptype->pTypeInfo, 0);
6050 }
6051 
6052 /*
6053  * call-seq:
6054  * WIN32OLE_TYPE#source_ole_types
6055  *
6056  * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
6057  * object and having IMPLTYPEFLAG_FSOURCE.
6058  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
6059  * p tobj.source_ole_types
6060  * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>]
6061  */
6062 static VALUE
6064 {
6065  struct oletypedata *ptype;
6066  Data_Get_Struct(self, struct oletypedata, ptype);
6067  return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE);
6068 }
6069 
6070 /*
6071  * call-seq:
6072  * WIN32OLE_TYPE#default_event_sources
6073  *
6074  * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
6075  * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT.
6076  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
6077  * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>]
6078  */
6079 static VALUE
6081 {
6082  struct oletypedata *ptype;
6083  Data_Get_Struct(self, struct oletypedata, ptype);
6084  return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT);
6085 }
6086 
6087 /*
6088  * call-seq:
6089  * WIN32OLE_TYPE#default_ole_types
6090  *
6091  * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
6092  * object and having IMPLTYPEFLAG_FDEFAULT.
6093  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
6094  * p tobj.default_ole_types
6095  * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>]
6096  */
6097 static VALUE
6099 {
6100  struct oletypedata *ptype;
6101  Data_Get_Struct(self, struct oletypedata, ptype);
6102  return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT);
6103 }
6104 
6105 /*
6106  * call-seq:
6107  * WIN32OLE_TYPE#inspect -> String
6108  *
6109  * Returns the type name with class name.
6110  *
6111  * ie = WIN32OLE.new('InternetExplorer.Application')
6112  * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2>
6113  */
6114 static VALUE
6116 {
6117  return default_inspect(self, "WIN32OLE_TYPE");
6118 }
6119 
6120 static VALUE
6122 {
6123  HRESULT hr;
6124  TYPEATTR *pTypeAttr;
6125  WORD i;
6126  UINT len;
6127  BSTR bstr;
6128  VARDESC *pVarDesc;
6129  struct olevariabledata *pvar;
6130  VALUE var;
6131  VALUE variables = rb_ary_new();
6132  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
6133  if (FAILED(hr)) {
6134  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
6135  }
6136 
6137  for(i = 0; i < pTypeAttr->cVars; i++) {
6138  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc);
6139  if(FAILED(hr))
6140  continue;
6141  len = 0;
6142  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
6143  1, &len);
6144  if(FAILED(hr) || len == 0 || !bstr)
6145  continue;
6146 
6148  0,olevariable_free,pvar);
6149  pvar->pTypeInfo = pTypeInfo;
6150  OLE_ADDREF(pTypeInfo);
6151  pvar->index = i;
6152  rb_ivar_set(var, rb_intern("name"), WC2VSTR(bstr));
6153  rb_ary_push(variables, var);
6154 
6155  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6156  pVarDesc = NULL;
6157  }
6158  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
6159  return variables;
6160 }
6161 
6162 /*
6163  * call-seq:
6164  * WIN32OLE_TYPE#variables
6165  *
6166  * Returns array of WIN32OLE_VARIABLE objects which represent variables
6167  * defined in OLE class.
6168  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6169  * vars = tobj.variables
6170  * vars.each do |v|
6171  * puts "#{v.name} = #{v.value}"
6172  * end
6173  *
6174  * The result of above sample script is follows:
6175  * xlChart = -4109
6176  * xlDialogSheet = -4116
6177  * xlExcel4IntlMacroSheet = 4
6178  * xlExcel4MacroSheet = 3
6179  * xlWorksheet = -4167
6180  *
6181  */
6182 static VALUE
6184 {
6185  struct oletypedata *ptype;
6186  Data_Get_Struct(self, struct oletypedata, ptype);
6187  return ole_variables(ptype->pTypeInfo);
6188 }
6189 
6190 /*
6191  * call-seq:
6192  * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects.
6193  *
6194  * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in
6195  * OLE type library.
6196  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
6197  * methods = tobj.ole_methods.collect{|m|
6198  * m.name
6199  * }
6200  * # => ['Activate', 'Copy', 'Delete',....]
6201  */
6202 static VALUE
6204 {
6205  struct oletypedata *ptype;
6206  Data_Get_Struct(self, struct oletypedata, ptype);
6207  return ole_methods_from_typeinfo(ptype->pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
6208 }
6209 
6210 /*
6211  * Document-class: WIN32OLE_VARIABLE
6212  *
6213  * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information.
6214  */
6215 
6216 /*
6217  * call-seq:
6218  * WIN32OLE_VARIABLE#name
6219  *
6220  * Returns the name of variable.
6221  *
6222  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6223  * variables = tobj.variables
6224  * variables.each do |variable|
6225  * puts "#{variable.name}"
6226  * end
6227  *
6228  * The result of above script is following:
6229  * xlChart
6230  * xlDialogSheet
6231  * xlExcel4IntlMacroSheet
6232  * xlExcel4MacroSheet
6233  * xlWorksheet
6234  *
6235  */
6236 static VALUE
6238 {
6239  return rb_ivar_get(self, rb_intern("name"));
6240 }
6241 
6242 static VALUE
6243 ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
6244 {
6245  VARDESC *pVarDesc;
6246  HRESULT hr;
6247  VALUE type;
6248  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6249  if (FAILED(hr))
6250  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
6251  type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil);
6252  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6253  return type;
6254 }
6255 
6256 /*
6257  * call-seq:
6258  * WIN32OLE_VARIABLE#ole_type
6259  *
6260  * Returns OLE type string.
6261  *
6262  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6263  * variables = tobj.variables
6264  * variables.each do |variable|
6265  * puts "#{variable.ole_type} #{variable.name}"
6266  * end
6267  *
6268  * The result of above script is following:
6269  * INT xlChart
6270  * INT xlDialogSheet
6271  * INT xlExcel4IntlMacroSheet
6272  * INT xlExcel4MacroSheet
6273  * INT xlWorksheet
6274  *
6275  */
6276 static VALUE
6278 {
6279  struct olevariabledata *pvar;
6280  Data_Get_Struct(self, struct olevariabledata, pvar);
6281  return ole_variable_ole_type(pvar->pTypeInfo, pvar->index);
6282 }
6283 
6284 static VALUE
6285 ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
6286 {
6287  VARDESC *pVarDesc;
6288  HRESULT hr;
6289  VALUE type = rb_ary_new();
6290  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6291  if (FAILED(hr))
6292  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
6293  ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type);
6294  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6295  return type;
6296 }
6297 
6298 /*
6299  * call-seq:
6300  * WIN32OLE_VARIABLE#ole_type_detail
6301  *
6302  * Returns detail information of type. The information is array of type.
6303  *
6304  * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS')
6305  * variable = tobj.variables.find {|variable| variable.name == 'lFlags'}
6306  * tdetail = variable.ole_type_detail
6307  * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"]
6308  *
6309  */
6310 static VALUE
6312 {
6313  struct olevariabledata *pvar;
6314  Data_Get_Struct(self, struct olevariabledata, pvar);
6315  return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index);
6316 }
6317 
6318 static VALUE
6319 ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
6320 {
6321  VARDESC *pVarDesc;
6322  HRESULT hr;
6323  VALUE val = Qnil;
6324  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6325  if (FAILED(hr))
6326  return Qnil;
6327  if(pVarDesc->varkind == VAR_CONST)
6328  val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
6329  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6330  return val;
6331 }
6332 
6333 /*
6334  * call-seq:
6335  * WIN32OLE_VARIABLE#value
6336  *
6337  * Returns value if value is exists. If the value does not exist,
6338  * this method returns nil.
6339  *
6340  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6341  * variables = tobj.variables
6342  * variables.each do |variable|
6343  * puts "#{variable.name} #{variable.value}"
6344  * end
6345  *
6346  * The result of above script is following:
6347  * xlChart = -4109
6348  * xlDialogSheet = -4116
6349  * xlExcel4IntlMacroSheet = 4
6350  * xlExcel4MacroSheet = 3
6351  * xlWorksheet = -4167
6352  *
6353  */
6354 static VALUE
6356 {
6357  struct olevariabledata *pvar;
6358  Data_Get_Struct(self, struct olevariabledata, pvar);
6359  return ole_variable_value(pvar->pTypeInfo, pvar->index);
6360 }
6361 
6362 static VALUE
6363 ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
6364 {
6365  VARDESC *pVarDesc;
6366  HRESULT hr;
6367  VALUE visible = Qfalse;
6368  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6369  if (FAILED(hr))
6370  return visible;
6371  if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
6372  VARFLAG_FRESTRICTED |
6373  VARFLAG_FNONBROWSABLE))) {
6374  visible = Qtrue;
6375  }
6376  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6377  return visible;
6378 }
6379 
6380 /*
6381  * call-seq:
6382  * WIN32OLE_VARIABLE#visible?
6383  *
6384  * Returns true if the variable is public.
6385  *
6386  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6387  * variables = tobj.variables
6388  * variables.each do |variable|
6389  * puts "#{variable.name} #{variable.visible?}"
6390  * end
6391  *
6392  * The result of above script is following:
6393  * xlChart true
6394  * xlDialogSheet true
6395  * xlExcel4IntlMacroSheet true
6396  * xlExcel4MacroSheet true
6397  * xlWorksheet true
6398  *
6399  */
6400 static VALUE
6402 {
6403  struct olevariabledata *pvar;
6404  Data_Get_Struct(self, struct olevariabledata, pvar);
6405  return ole_variable_visible(pvar->pTypeInfo, pvar->index);
6406 }
6407 
6408 static VALUE
6409 ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
6410 {
6411  VARDESC *pVarDesc;
6412  HRESULT hr;
6413  VALUE kind = rb_str_new2("UNKNOWN");
6414  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6415  if (FAILED(hr))
6416  return kind;
6417  switch(pVarDesc->varkind) {
6418  case VAR_PERINSTANCE:
6419  kind = rb_str_new2("PERINSTANCE");
6420  break;
6421  case VAR_STATIC:
6422  kind = rb_str_new2("STATIC");
6423  break;
6424  case VAR_CONST:
6425  kind = rb_str_new2("CONSTANT");
6426  break;
6427  case VAR_DISPATCH:
6428  kind = rb_str_new2("DISPATCH");
6429  break;
6430  default:
6431  break;
6432  }
6433  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6434  return kind;
6435 }
6436 
6437 /*
6438  * call-seq:
6439  * WIN32OLE_VARIABLE#variable_kind
6440  *
6441  * Returns variable kind string.
6442  *
6443  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6444  * variables = tobj.variables
6445  * variables.each do |variable|
6446  * puts "#{variable.name} #{variable.variable_kind}"
6447  * end
6448  *
6449  * The result of above script is following:
6450  * xlChart CONSTANT
6451  * xlDialogSheet CONSTANT
6452  * xlExcel4IntlMacroSheet CONSTANT
6453  * xlExcel4MacroSheet CONSTANT
6454  * xlWorksheet CONSTANT
6455  */
6456 static VALUE
6458 {
6459  struct olevariabledata *pvar;
6460  Data_Get_Struct(self, struct olevariabledata, pvar);
6461  return ole_variable_kind(pvar->pTypeInfo, pvar->index);
6462 }
6463 
6464 static VALUE
6465 ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
6466 {
6467  VARDESC *pVarDesc;
6468  HRESULT hr;
6469  VALUE kind = Qnil;
6470  hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6471  if (FAILED(hr))
6472  return kind;
6473  pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6474  kind = INT2FIX(pVarDesc->varkind);
6475  return kind;
6476 }
6477 
6478 /*
6479  * call-seq:
6480  * WIN32OLE_VARIABLE#varkind
6481  *
6482  * Returns the number which represents variable kind.
6483  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6484  * variables = tobj.variables
6485  * variables.each do |variable|
6486  * puts "#{variable.name} #{variable.varkind}"
6487  * end
6488  *
6489  * The result of above script is following:
6490  * xlChart 2
6491  * xlDialogSheet 2
6492  * xlExcel4IntlMacroSheet 2
6493  * xlExcel4MacroSheet 2
6494  * xlWorksheet 2
6495  */
6496 static VALUE
6498 {
6499  struct olevariabledata *pvar;
6500  Data_Get_Struct(self, struct olevariabledata, pvar);
6501  return ole_variable_varkind(pvar->pTypeInfo, pvar->index);
6502 }
6503 
6504 /*
6505  * call-seq:
6506  * WIN32OLE_VARIABLE#inspect -> String
6507  *
6508  * Returns the OLE variable name and the value with class name.
6509  *
6510  */
6511 static VALUE
6513 {
6514  VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
6515  rb_str_cat2(detail, "=");
6516  rb_str_concat(detail, rb_funcall(rb_funcall(self, rb_intern("value"), 0), rb_intern("inspect"), 0));
6517  return make_inspect("WIN32OLE_VARIABLE", detail);
6518 }
6519 
6520 /*
6521  * Document-class: WIN32OLE_METHOD
6522  *
6523  * <code>WIN32OLE_METHOD</code> objects represent OLE method information.
6524  */
6525 
6526 static VALUE
6527 olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name)
6528 {
6529  struct olemethoddata *pmethod;
6530  Data_Get_Struct(self, struct olemethoddata, pmethod);
6531  pmethod->pTypeInfo = pTypeInfo;
6532  OLE_ADDREF(pTypeInfo);
6533  pmethod->pOwnerTypeInfo = pOwnerTypeInfo;
6534  if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo);
6535  pmethod->index = index;
6536  rb_ivar_set(self, rb_intern("name"), name);
6537  return self;
6538 }
6539 
6540 static VALUE
6542 {
6543  struct olemethoddata *pmethod;
6544  VALUE obj;
6545  obj = Data_Make_Struct(klass,
6546  struct olemethoddata,
6547  0, olemethod_free, pmethod);
6548  pmethod->pTypeInfo = NULL;
6549  pmethod->pOwnerTypeInfo = NULL;
6550  pmethod->index = 0;
6551  return obj;
6552 }
6553 
6554 /*
6555  * call-seq:
6556  * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object
6557  *
6558  * Returns a new WIN32OLE_METHOD object which represents the information
6559  * about OLE method.
6560  * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object.
6561  * The second argument <i>method</i> specifies OLE method name defined OLE class
6562  * which represents WIN32OLE_TYPE object.
6563  *
6564  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6565  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
6566  */
6567 static VALUE
6568 folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
6569 {
6570  struct oletypedata *ptype;
6571  VALUE obj = Qnil;
6572  if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) {
6573  SafeStringValue(method);
6574  Data_Get_Struct(oletype, struct oletypedata, ptype);
6575  obj = olemethod_from_typeinfo(self, ptype->pTypeInfo, method);
6576  if (obj == Qnil) {
6577  rb_raise(eWIN32OLERuntimeError, "not found %s",
6578  StringValuePtr(method));
6579  }
6580  }
6581  else {
6582  rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object");
6583  }
6584  return obj;
6585 }
6586 
6587 /*
6588  * call-seq
6589  * WIN32OLE_METHOD#name
6590  *
6591  * Returns the name of the method.
6592  *
6593  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6594  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
6595  * puts method.name # => SaveAs
6596  *
6597  */
6598 static VALUE
6600 {
6601  return rb_ivar_get(self, rb_intern("name"));
6602 }
6603 
6604 static VALUE
6605 ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
6606 {
6607  FUNCDESC *pFuncDesc;
6608  HRESULT hr;
6609  VALUE type;
6610 
6611  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6612  if (FAILED(hr))
6613  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
6614 
6615  type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil);
6616  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6617  return type;
6618 }
6619 
6620 /*
6621  * call-seq:
6622  * WIN32OLE_METHOD#return_type
6623  *
6624  * Returns string of return value type of method.
6625  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6626  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6627  * puts method.return_type # => Workbook
6628  *
6629  */
6630 static VALUE
6632 {
6633  struct olemethoddata *pmethod;
6634  Data_Get_Struct(self, struct olemethoddata, pmethod);
6635  return ole_method_return_type(pmethod->pTypeInfo, pmethod->index);
6636 }
6637 
6638 static VALUE
6639 ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
6640 {
6641  FUNCDESC *pFuncDesc;
6642  HRESULT hr;
6643  VALUE vvt;
6644 
6645  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6646  if (FAILED(hr))
6647  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
6648 
6649  vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt);
6650  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6651  return vvt;
6652 }
6653 
6654 /*
6655  * call-seq:
6656  * WIN32OLE_METHOD#return_vtype
6657  *
6658  * Returns number of return value type of method.
6659  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6660  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6661  * puts method.return_vtype # => 26
6662  *
6663  */
6664 static VALUE
6666 {
6667  struct olemethoddata *pmethod;
6668  Data_Get_Struct(self, struct olemethoddata, pmethod);
6669  return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index);
6670 }
6671 
6672 static VALUE
6673 ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
6674 {
6675  FUNCDESC *pFuncDesc;
6676  HRESULT hr;
6677  VALUE type = rb_ary_new();
6678 
6679  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6680  if (FAILED(hr))
6681  return type;
6682 
6683  ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type);
6684  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6685  return type;
6686 }
6687 
6688 /*
6689  * call-seq:
6690  * WIN32OLE_METHOD#return_type_detail
6691  *
6692  * Returns detail information of return value type of method.
6693  * The information is array.
6694  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6695  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6696  * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"]
6697  */
6698 static VALUE
6700 {
6701  struct olemethoddata *pmethod;
6702  Data_Get_Struct(self, struct olemethoddata, pmethod);
6703  return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index);
6704 }
6705 
6706 static VALUE
6707 ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index)
6708 {
6709  FUNCDESC *pFuncDesc;
6710  HRESULT hr;
6711  VALUE invkind;
6712  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6713  if(FAILED(hr))
6714  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
6715  invkind = INT2FIX(pFuncDesc->invkind);
6716  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6717  return invkind;
6718 }
6719 
6720 static VALUE
6721 ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
6722 {
6723  VALUE type = rb_str_new2("UNKNOWN");
6724  VALUE invkind = ole_method_invkind(pTypeInfo, method_index);
6725  if((FIX2INT(invkind) & INVOKE_PROPERTYGET) &&
6726  (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) {
6727  type = rb_str_new2("PROPERTY");
6728  } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) {
6729  type = rb_str_new2("PROPERTYGET");
6730  } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) {
6731  type = rb_str_new2("PROPERTYPUT");
6732  } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) {
6733  type = rb_str_new2("PROPERTYPUTREF");
6734  } else if(FIX2INT(invkind) & INVOKE_FUNC) {
6735  type = rb_str_new2("FUNC");
6736  }
6737  return type;
6738 }
6739 
6740 /*
6741  * call-seq:
6742  * WIN32OLE_MTHOD#invkind
6743  *
6744  * Returns the method invoke kind.
6745  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6746  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6747  * puts method.invkind # => 1
6748  *
6749  */
6750 static VALUE
6752 {
6753  struct olemethoddata *pmethod;
6754  Data_Get_Struct(self, struct olemethoddata, pmethod);
6755  return ole_method_invkind(pmethod->pTypeInfo, pmethod->index);
6756 }
6757 
6758 /*
6759  * call-seq:
6760  * WIN32OLE_METHOD#invoke_kind
6761  *
6762  * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY"
6763  * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF"
6764  * or "FUNC".
6765  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6766  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6767  * puts method.invoke_kind # => "FUNC"
6768  */
6769 static VALUE
6771 {
6772  struct olemethoddata *pmethod;
6773  Data_Get_Struct(self, struct olemethoddata, pmethod);
6774  return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index);
6775 }
6776 
6777 static VALUE
6778 ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
6779 {
6780  FUNCDESC *pFuncDesc;
6781  HRESULT hr;
6782  VALUE visible;
6783  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6784  if(FAILED(hr))
6785  return Qfalse;
6786  if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED |
6787  FUNCFLAG_FHIDDEN |
6788  FUNCFLAG_FNONBROWSABLE)) {
6789  visible = Qfalse;
6790  } else {
6791  visible = Qtrue;
6792  }
6793  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6794  return visible;
6795 }
6796 
6797 /*
6798  * call-seq:
6799  * WIN32OLE_METHOD#visible?
6800  *
6801  * Returns true if the method is public.
6802  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6803  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6804  * puts method.visible? # => true
6805  */
6806 static VALUE
6808 {
6809  struct olemethoddata *pmethod;
6810  Data_Get_Struct(self, struct olemethoddata, pmethod);
6811  return ole_method_visible(pmethod->pTypeInfo, pmethod->index);
6812 }
6813 
6814 static VALUE
6815 ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
6816 {
6817  TYPEATTR *pTypeAttr;
6818  HRESULT hr;
6819  WORD i;
6820  int flags;
6821  HREFTYPE href;
6822  ITypeInfo *pRefTypeInfo;
6823  FUNCDESC *pFuncDesc;
6824  BSTR bstr;
6825  VALUE name;
6826  VALUE event = Qfalse;
6827 
6828  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
6829  if (FAILED(hr))
6830  return event;
6831  if(pTypeAttr->typekind != TKIND_COCLASS) {
6832  pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
6833  return event;
6834  }
6835  for (i = 0; i < pTypeAttr->cImplTypes; i++) {
6836  hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
6837  if (FAILED(hr))
6838  continue;
6839 
6840  if (flags & IMPLTYPEFLAG_FSOURCE) {
6841  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
6842  i, &href);
6843  if (FAILED(hr))
6844  continue;
6845  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
6846  href, &pRefTypeInfo);
6847  if (FAILED(hr))
6848  continue;
6849  hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index,
6850  &pFuncDesc);
6851  if (FAILED(hr)) {
6852  OLE_RELEASE(pRefTypeInfo);
6853  continue;
6854  }
6855 
6856  hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo,
6857  pFuncDesc->memid,
6858  &bstr, NULL, NULL, NULL);
6859  if (FAILED(hr)) {
6860  pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
6861  OLE_RELEASE(pRefTypeInfo);
6862  continue;
6863  }
6864 
6865  name = WC2VSTR(bstr);
6866  pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
6867  OLE_RELEASE(pRefTypeInfo);
6868  if (rb_str_cmp(method_name, name) == 0) {
6869  event = Qtrue;
6870  break;
6871  }
6872  }
6873  }
6874  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
6875  return event;
6876 }
6877 
6878 /*
6879  * call-seq:
6880  * WIN32OLE_METHOD#event?
6881  *
6882  * Returns true if the method is event.
6883  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6884  * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
6885  * puts method.event? # => true
6886  *
6887  */
6888 static VALUE
6890 {
6891  struct olemethoddata *pmethod;
6892  Data_Get_Struct(self, struct olemethoddata, pmethod);
6893  if (!pmethod->pOwnerTypeInfo)
6894  return Qfalse;
6895  return ole_method_event(pmethod->pOwnerTypeInfo,
6896  pmethod->index,
6897  rb_ivar_get(self, rb_intern("name")));
6898 }
6899 
6900 /*
6901  * call-seq:
6902  * WIN32OLE_METHOD#event_interface
6903  *
6904  * Returns event interface name if the method is event.
6905  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6906  * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
6907  * puts method.event_interface # => WorkbookEvents
6908  */
6909 static VALUE
6911 {
6912  BSTR name;
6913  struct olemethoddata *pmethod;
6914  HRESULT hr;
6915  Data_Get_Struct(self, struct olemethoddata, pmethod);
6916  if(folemethod_event(self) == Qtrue) {
6917  hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL);
6918  if(SUCCEEDED(hr))
6919  return WC2VSTR(name);
6920  }
6921  return Qnil;
6922 }
6923 
6924 static VALUE
6926  ITypeInfo *pTypeInfo,
6927  UINT method_index,
6928  BSTR *name,
6929  BSTR *helpstr,
6930  DWORD *helpcontext,
6931  BSTR *helpfile
6932  )
6933 {
6934  FUNCDESC *pFuncDesc;
6935  HRESULT hr;
6936  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6937  if (FAILED(hr))
6938  return hr;
6939  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
6940  name, helpstr,
6941  helpcontext, helpfile);
6942  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6943  return hr;
6944 }
6945 
6946 static VALUE
6947 ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
6948 {
6949  HRESULT hr;
6950  BSTR bhelpstring;
6951  hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring,
6952  NULL, NULL);
6953  if (FAILED(hr))
6954  return Qnil;
6955  return WC2VSTR(bhelpstring);
6956 }
6957 
6958 /*
6959  * call-seq:
6960  * WIN32OLE_METHOD#helpstring
6961  *
6962  * Returns help string of OLE method. If the help string is not found,
6963  * then the method returns nil.
6964  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
6965  * method = WIN32OLE_METHOD.new(tobj, 'Navigate')
6966  * puts method.helpstring # => Navigates to a URL or file.
6967  *
6968  */
6969 static VALUE
6971 {
6972  struct olemethoddata *pmethod;
6973  Data_Get_Struct(self, struct olemethoddata, pmethod);
6974  return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index);
6975 }
6976 
6977 static VALUE
6978 ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
6979 {
6980  HRESULT hr;
6981  BSTR bhelpfile;
6982  hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
6983  NULL, &bhelpfile);
6984  if (FAILED(hr))
6985  return Qnil;
6986  return WC2VSTR(bhelpfile);
6987 }
6988 
6989 /*
6990  * call-seq:
6991  * WIN32OLE_METHOD#helpfile
6992  *
6993  * Returns help file. If help file is not found, then
6994  * the method returns nil.
6995  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6996  * method = WIN32OLE_METHOD.new(tobj, 'Add')
6997  * puts method.helpfile # => C:\...\VBAXL9.CHM
6998  */
6999 static VALUE
7001 {
7002  struct olemethoddata *pmethod;
7003  Data_Get_Struct(self, struct olemethoddata, pmethod);
7004 
7005  return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index);
7006 }
7007 
7008 static VALUE
7009 ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
7010 {
7011  HRESULT hr;
7012  DWORD helpcontext = 0;
7013  hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
7014  &helpcontext, NULL);
7015  if (FAILED(hr))
7016  return Qnil;
7017  return INT2FIX(helpcontext);
7018 }
7019 
7020 /*
7021  * call-seq:
7022  * WIN32OLE_METHOD#helpcontext
7023  *
7024  * Returns help context.
7025  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
7026  * method = WIN32OLE_METHOD.new(tobj, 'Add')
7027  * puts method.helpcontext # => 65717
7028  */
7029 static VALUE
7031 {
7032  struct olemethoddata *pmethod;
7033  Data_Get_Struct(self, struct olemethoddata, pmethod);
7034  return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index);
7035 }
7036 
7037 static VALUE
7038 ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
7039 {
7040  FUNCDESC *pFuncDesc;
7041  HRESULT hr;
7042  VALUE dispid = Qnil;
7043  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7044  if (FAILED(hr))
7045  return dispid;
7046  dispid = INT2NUM(pFuncDesc->memid);
7047  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7048  return dispid;
7049 }
7050 
7051 /*
7052  * call-seq:
7053  * WIN32OLE_METHOD#dispid
7054  *
7055  * Returns dispatch ID.
7056  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
7057  * method = WIN32OLE_METHOD.new(tobj, 'Add')
7058  * puts method.dispid # => 181
7059  */
7060 static VALUE
7062 {
7063  struct olemethoddata *pmethod;
7064  Data_Get_Struct(self, struct olemethoddata, pmethod);
7065  return ole_method_dispid(pmethod->pTypeInfo, pmethod->index);
7066 }
7067 
7068 static VALUE
7069 ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
7070 {
7071  FUNCDESC *pFuncDesc;
7072  HRESULT hr;
7073  VALUE offset_vtbl = Qnil;
7074  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7075  if (FAILED(hr))
7076  return offset_vtbl;
7077  offset_vtbl = INT2FIX(pFuncDesc->oVft);
7078  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7079  return offset_vtbl;
7080 }
7081 
7082 /*
7083  * call-seq:
7084  * WIN32OLE_METHOD#offset_vtbl
7085  *
7086  * Returns the offset ov VTBL.
7087  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
7088  * method = WIN32OLE_METHOD.new(tobj, 'Add')
7089  * puts method.offset_vtbl # => 40
7090  */
7091 static VALUE
7093 {
7094  struct olemethoddata *pmethod;
7095  Data_Get_Struct(self, struct olemethoddata, pmethod);
7096  return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index);
7097 }
7098 
7099 static VALUE
7100 ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
7101 {
7102  FUNCDESC *pFuncDesc;
7103  HRESULT hr;
7104  VALUE size_params = Qnil;
7105  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7106  if (FAILED(hr))
7107  return size_params;
7108  size_params = INT2FIX(pFuncDesc->cParams);
7109  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7110  return size_params;
7111 }
7112 
7113 /*
7114  * call-seq:
7115  * WIN32OLE_METHOD#size_params
7116  *
7117  * Returns the size of arguments of the method.
7118  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7119  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7120  * puts method.size_params # => 11
7121  *
7122  */
7123 static VALUE
7125 {
7126  struct olemethoddata *pmethod;
7127  Data_Get_Struct(self, struct olemethoddata, pmethod);
7128  return ole_method_size_params(pmethod->pTypeInfo, pmethod->index);
7129 }
7130 
7131 static VALUE
7132 ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
7133 {
7134  FUNCDESC *pFuncDesc;
7135  HRESULT hr;
7136  VALUE size_opt_params = Qnil;
7137  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7138  if (FAILED(hr))
7139  return size_opt_params;
7140  size_opt_params = INT2FIX(pFuncDesc->cParamsOpt);
7141  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7142  return size_opt_params;
7143 }
7144 
7145 /*
7146  * call-seq:
7147  * WIN32OLE_METHOD#size_opt_params
7148  *
7149  * Returns the size of optional parameters.
7150  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7151  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7152  * puts method.size_opt_params # => 4
7153  */
7154 static VALUE
7156 {
7157  struct olemethoddata *pmethod;
7158  Data_Get_Struct(self, struct olemethoddata, pmethod);
7159  return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index);
7160 }
7161 
7162 static VALUE
7163 ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
7164 {
7165  FUNCDESC *pFuncDesc;
7166  HRESULT hr;
7167  BSTR *bstrs;
7168  UINT len, i;
7169  struct oleparamdata *pparam;
7170  VALUE param;
7171  VALUE params = rb_ary_new();
7172  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7173  if (FAILED(hr))
7174  return params;
7175 
7176  len = 0;
7177  bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
7178  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
7179  bstrs, pFuncDesc->cParams + 1,
7180  &len);
7181  if (FAILED(hr)) {
7182  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7183  return params;
7184  }
7185  SysFreeString(bstrs[0]);
7186  if (pFuncDesc->cParams > 0) {
7187  for(i = 1; i < len; i++) {
7188  param = Data_Make_Struct(cWIN32OLE_PARAM, struct oleparamdata, 0,
7189  oleparam_free, pparam);
7190  pparam->pTypeInfo = pTypeInfo;
7191  OLE_ADDREF(pTypeInfo);
7192  pparam->method_index = method_index;
7193  pparam->index = i - 1;
7194  rb_ivar_set(param, rb_intern("name"), WC2VSTR(bstrs[i]));
7195  rb_ary_push(params, param);
7196  }
7197  }
7198  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7199  return params;
7200 }
7201 
7202 
7203 /*
7204  * call-seq:
7205  * WIN32OLE_METHOD#params
7206  *
7207  * returns array of WIN32OLE_PARAM object corresponding with method parameters.
7208  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7209  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7210  * p method.params # => [Filename, FileFormat, Password, WriteResPassword,
7211  * ReadOnlyRecommended, CreateBackup, AccessMode,
7212  * ConflictResolution, AddToMru, TextCodepage,
7213  * TextVisualLayout]
7214  */
7215 static VALUE
7217 {
7218  struct olemethoddata *pmethod;
7219  Data_Get_Struct(self, struct olemethoddata, pmethod);
7220  return ole_method_params(pmethod->pTypeInfo, pmethod->index);
7221 }
7222 
7223 /*
7224  * call-seq:
7225  * WIN32OLE_METHOD#inspect -> String
7226  *
7227  * Returns the method name with class name.
7228  *
7229  */
7230 static VALUE
7232 {
7233  return default_inspect(self, "WIN32OLE_METHOD");
7234 }
7235 
7236 /*
7237  * Document-class: WIN32OLE_PARAM
7238  *
7239  * <code>WIN32OLE_PARAM</code> objects represent param information of
7240  * the OLE method.
7241  */
7243 {
7244  struct oleparamdata *pparam;
7245  VALUE obj;
7246  obj = Data_Make_Struct(klass,
7247  struct oleparamdata,
7248  0, oleparam_free, pparam);
7249  pparam->pTypeInfo = NULL;
7250  pparam->method_index = 0;
7251  pparam->index = 0;
7252  return obj;
7253 }
7254 
7255 static VALUE
7256 oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index)
7257 {
7258  FUNCDESC *pFuncDesc;
7259  HRESULT hr;
7260  BSTR *bstrs;
7261  UINT len;
7262  struct oleparamdata *pparam;
7263  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7264  if (FAILED(hr))
7265  ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc");
7266 
7267  len = 0;
7268  bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
7269  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
7270  bstrs, pFuncDesc->cParams + 1,
7271  &len);
7272  if (FAILED(hr)) {
7273  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7274  ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames");
7275  }
7276  SysFreeString(bstrs[0]);
7277  if (param_index < 1 || len <= (UINT)param_index)
7278  {
7279  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7280  rb_raise(rb_eIndexError, "index of param must be in 1..%d", len);
7281  }
7282 
7283  Data_Get_Struct(self, struct oleparamdata, pparam);
7284  pparam->pTypeInfo = pTypeInfo;
7285  OLE_ADDREF(pTypeInfo);
7286  pparam->method_index = method_index;
7287  pparam->index = param_index - 1;
7288  rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index]));
7289 
7290  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7291  return self;
7292 }
7293 
7294 static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n)
7295 {
7296  struct olemethoddata *pmethod;
7297  Data_Get_Struct(olemethod, struct olemethoddata, pmethod);
7298  return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n);
7299 }
7300 
7301 static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n)
7302 {
7303  int idx;
7304  if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) {
7305  rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object");
7306  }
7307  idx = FIX2INT(n);
7308  return oleparam_ole_param(self, olemethod, idx);
7309 }
7310 
7311 /*
7312  * call-seq:
7313  * WIN32OLE_PARAM#name
7314  *
7315  * Returns name.
7316  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7317  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7318  * param1 = method.params[0]
7319  * puts param1.name # => Filename
7320  */
7321 static VALUE
7323 {
7324  return rb_ivar_get(self, rb_intern("name"));
7325 }
7326 
7327 static VALUE
7328 ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
7329 {
7330  FUNCDESC *pFuncDesc;
7331  HRESULT hr;
7332  VALUE type = rb_str_new2("unknown type");
7333  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7334  if (FAILED(hr))
7335  return type;
7336  type = ole_typedesc2val(pTypeInfo,
7337  &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil);
7338  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7339  return type;
7340 }
7341 
7342 /*
7343  * call-seq:
7344  * WIN32OLE_PARAM#ole_type
7345  *
7346  * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method).
7347  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7348  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7349  * param1 = method.params[0]
7350  * puts param1.ole_type # => VARIANT
7351  */
7352 static VALUE
7354 {
7355  struct oleparamdata *pparam;
7356  Data_Get_Struct(self, struct oleparamdata, pparam);
7357  return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index,
7358  pparam->index);
7359 }
7360 
7361 static VALUE
7363 {
7364  FUNCDESC *pFuncDesc;
7365  HRESULT hr;
7366  VALUE typedetail = rb_ary_new();
7367  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7368  if (FAILED(hr))
7369  return typedetail;
7370  ole_typedesc2val(pTypeInfo,
7371  &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail);
7372  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7373  return typedetail;
7374 }
7375 
7376 /*
7377  * call-seq:
7378  * WIN32OLE_PARAM#ole_type_detail
7379  *
7380  * Returns detail information of type of argument.
7381  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction')
7382  * method = WIN32OLE_METHOD.new(tobj, 'SumIf')
7383  * param1 = method.params[0]
7384  * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"]
7385  */
7386 static VALUE
7388 {
7389  struct oleparamdata *pparam;
7390  Data_Get_Struct(self, struct oleparamdata, pparam);
7391  return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index,
7392  pparam->index);
7393 }
7394 
7395 static VALUE
7396 ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask)
7397 {
7398  FUNCDESC *pFuncDesc;
7399  HRESULT hr;
7400  VALUE ret = Qfalse;
7401  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7402  if(FAILED(hr))
7403  return ret;
7404  if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask)
7405  ret = Qtrue;
7406  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7407  return ret;
7408 }
7409 
7410 /*
7411  * call-seq:
7412  * WIN32OLE_PARAM#input?
7413  *
7414  * Returns true if the parameter is input.
7415  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7416  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7417  * param1 = method.params[0]
7418  * puts param1.input? # => true
7419  */
7421 {
7422  struct oleparamdata *pparam;
7423  Data_Get_Struct(self, struct oleparamdata, pparam);
7424  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7425  pparam->index, PARAMFLAG_FIN);
7426 }
7427 
7428 /*
7429  * call-seq:
7430  * WIN32OLE#output?
7431  *
7432  * Returns true if argument is output.
7433  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents')
7434  * method = WIN32OLE_METHOD.new(tobj, 'NewWindow')
7435  * method.params.each do |param|
7436  * puts "#{param.name} #{param.output?}"
7437  * end
7438  *
7439  * The result of above script is following:
7440  * URL false
7441  * Flags false
7442  * TargetFrameName false
7443  * PostData false
7444  * Headers false
7445  * Processed true
7446  */
7448 {
7449  struct oleparamdata *pparam;
7450  Data_Get_Struct(self, struct oleparamdata, pparam);
7451  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7452  pparam->index, PARAMFLAG_FOUT);
7453 }
7454 
7455 /*
7456  * call-seq:
7457  * WIN32OLE_PARAM#optional?
7458  *
7459  * Returns true if argument is optional.
7460  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7461  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7462  * param1 = method.params[0]
7463  * puts "#{param1.name} #{param1.optional?}" # => Filename true
7464  */
7466 {
7467  struct oleparamdata *pparam;
7468  Data_Get_Struct(self, struct oleparamdata, pparam);
7469  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7470  pparam->index, PARAMFLAG_FOPT);
7471 }
7472 
7473 /*
7474  * call-seq:
7475  * WIN32OLE_PARAM#retval?
7476  *
7477  * Returns true if argument is return value.
7478  * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library',
7479  * 'DirectPlayLobbyConnection')
7480  * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName')
7481  * param = method.params[0]
7482  * puts "#{param.name} #{param.retval?}" # => name true
7483  */
7485 {
7486  struct oleparamdata *pparam;
7487  Data_Get_Struct(self, struct oleparamdata, pparam);
7488  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7489  pparam->index, PARAMFLAG_FRETVAL);
7490 }
7491 
7492 static VALUE
7494 {
7495  FUNCDESC *pFuncDesc;
7496  ELEMDESC *pElemDesc;
7497  PARAMDESCEX * pParamDescEx;
7498  HRESULT hr;
7499  USHORT wParamFlags;
7500  USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT;
7501  VALUE defval = Qnil;
7502  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7503  if (FAILED(hr))
7504  return defval;
7505  pElemDesc = &pFuncDesc->lprgelemdescParam[index];
7506  wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags;
7507  if ((wParamFlags & mask) == mask) {
7508  pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex;
7509  defval = ole_variant2val(&pParamDescEx->varDefaultValue);
7510  }
7511  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7512  return defval;
7513 }
7514 
7515 /*
7516  * call-seq:
7517  * WIN32OLE_PARAM#default
7518  *
7519  * Returns default value. If the default value does not exist,
7520  * this method returns nil.
7521  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7522  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7523  * method.params.each do |param|
7524  * if param.default
7525  * puts "#{param.name} (= #{param.default})"
7526  * else
7527  * puts "#{param}"
7528  * end
7529  * end
7530  *
7531  * The above script result is following:
7532  * Filename
7533  * FileFormat
7534  * Password
7535  * WriteResPassword
7536  * ReadOnlyRecommended
7537  * CreateBackup
7538  * AccessMode (= 1)
7539  * ConflictResolution
7540  * AddToMru
7541  * TextCodepage
7542  * TextVisualLayout
7543  */
7545 {
7546  struct oleparamdata *pparam;
7547  Data_Get_Struct(self, struct oleparamdata, pparam);
7548  return ole_param_default(pparam->pTypeInfo, pparam->method_index,
7549  pparam->index);
7550 }
7551 
7552 /*
7553  * call-seq:
7554  * WIN32OLE_PARAM#inspect -> String
7555  *
7556  * Returns the parameter name with class name. If the parameter has default value,
7557  * then returns name=value string with class name.
7558  *
7559  */
7560 static VALUE
7562 {
7563  VALUE detail = foleparam_name(self);
7564  VALUE defval = foleparam_default(self);
7565  if (defval != Qnil) {
7566  rb_str_cat2(detail, "=");
7567  rb_str_concat(detail, rb_funcall(defval, rb_intern("inspect"), 0));
7568  }
7569  return make_inspect("WIN32OLE_PARAM", detail);
7570 }
7571 
7572 /*
7573  * Document-class: WIN32OLE_EVENT
7574  *
7575  * <code>WIN32OLE_EVENT</code> objects controls OLE event.
7576  */
7577 
7580 
7581 void EVENTSINK_Destructor(PIEVENTSINKOBJ);
7582 
7583 STDMETHODIMP
7585  PEVENTSINK pEV,
7586  REFIID iid,
7587  LPVOID* ppv
7588  ) {
7589  if (IsEqualIID(iid, &IID_IUnknown) ||
7590  IsEqualIID(iid, &IID_IDispatch) ||
7591  IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) {
7592  *ppv = pEV;
7593  }
7594  else {
7595  *ppv = NULL;
7596  return E_NOINTERFACE;
7597  }
7598  ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
7599  return NOERROR;
7600 }
7601 
7604  PEVENTSINK pEV
7605  ){
7606  PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
7607  return ++pEVObj->m_cRef;
7608 }
7609 
7610 STDMETHODIMP_(ULONG) EVENTSINK_Release(
7611  PEVENTSINK pEV
7612  ) {
7613  PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
7614  --pEVObj->m_cRef;
7615  if(pEVObj->m_cRef != 0)
7616  return pEVObj->m_cRef;
7617  EVENTSINK_Destructor(pEVObj);
7618  return 0;
7619 }
7620 
7622  PEVENTSINK pEV,
7623  UINT *pct
7624  ) {
7625  *pct = 0;
7626  return NOERROR;
7627 }
7628 
7630  PEVENTSINK pEV,
7631  UINT info,
7632  LCID lcid,
7633  ITypeInfo **pInfo
7634  ) {
7635  *pInfo = NULL;
7636  return DISP_E_BADINDEX;
7637 }
7638 
7640  PEVENTSINK pEventSink,
7641  REFIID riid,
7642  OLECHAR **szNames,
7643  UINT cNames,
7644  LCID lcid,
7645  DISPID *pDispID
7646  ) {
7647  ITypeInfo *pTypeInfo;
7648  PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
7649  pTypeInfo = pEV->pTypeInfo;
7650  if (pTypeInfo) {
7651  return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
7652  }
7653  return DISP_E_UNKNOWNNAME;
7654 }
7655 
7656 static long
7658 {
7659  VALUE event;
7660  VALUE event_name;
7661  long i, len;
7662  long ret = -1;
7663  len = RARRAY_LEN(ary);
7664  for(i = 0; i < len; i++) {
7665  event = rb_ary_entry(ary, i);
7666  event_name = rb_ary_entry(event, 1);
7667  if(NIL_P(event_name) && NIL_P(ev)) {
7668  ret = i;
7669  break;
7670  }
7671  else if (TYPE(ev) == T_STRING &&
7672  TYPE(event_name) == T_STRING &&
7673  rb_str_cmp(ev, event_name) == 0) {
7674  ret = i;
7675  break;
7676  }
7677  }
7678  return ret;
7679 }
7680 
7681 static VALUE
7682 ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
7683 {
7684  VALUE event;
7685  VALUE def_event;
7686  VALUE event_name;
7687  int i, len;
7688  *is_default = FALSE;
7689  def_event = Qnil;
7690  len = RARRAY_LEN(ary);
7691  for(i = 0; i < len; i++) {
7692  event = rb_ary_entry(ary, i);
7693  event_name = rb_ary_entry(event, 1);
7694  if(NIL_P(event_name)) {
7695  *is_default = TRUE;
7696  def_event = event;
7697  }
7698  else if (rb_str_cmp(ev, event_name) == 0) {
7699  *is_default = FALSE;
7700  return event;
7701  }
7702  }
7703  return def_event;
7704 }
7705 static VALUE
7706 ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
7707 {
7708  VALUE mid;
7709 
7710  *is_default_handler = FALSE;
7711  mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev)));
7712  if (rb_respond_to(handler, mid)) {
7713  return mid;
7714  }
7715  mid = rb_intern("method_missing");
7716  if (rb_respond_to(handler, mid)) {
7717  *is_default_handler = TRUE;
7718  return mid;
7719  }
7720  return Qnil;
7721 }
7722 
7723 static void
7725 {
7726  long at = -1;
7727  at = ole_search_event_at(ary, ev);
7728  if (at >= 0) {
7729  rb_ary_delete_at(ary, at);
7730  }
7731 }
7732 
7733 static void
7734 hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
7735 {
7736  BSTR *bstrs;
7737  HRESULT hr;
7738  UINT len, i;
7739  VARIANT *pvar;
7740  VALUE val;
7741  VALUE key;
7742  len = 0;
7743  bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
7744  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
7745  bstrs, pdispparams->cArgs + 1,
7746  &len);
7747  if (FAILED(hr))
7748  return;
7749 
7750  for (i = 0; i < len - 1; i++) {
7751  key = WC2VSTR(bstrs[i + 1]);
7752  val = rb_hash_aref(hash, INT2FIX(i));
7753  if (val == Qnil)
7754  val = rb_hash_aref(hash, key);
7755  if (val == Qnil)
7756  val = rb_hash_aref(hash, rb_str_intern(key));
7757  pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
7758  ole_val2ptr_variant(val, pvar);
7759  }
7760 }
7761 
7762 static VALUE
7764 {
7765  VALUE ret = Qnil;
7766  ret = rb_hash_aref(hash, rb_str_new2("return"));
7767  if (ret == Qnil)
7768  ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
7769  return ret;
7770 }
7771 
7772 static void
7773 ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
7774 {
7775  int i;
7776  VALUE v;
7777  VARIANT *pvar;
7778  for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) {
7779  v = rb_ary_entry(ary, i);
7780  pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
7781  ole_val2ptr_variant(v, pvar);
7782  }
7783 }
7784 
7785 static VALUE
7787 {
7788  VALUE *parg = (VALUE *)arg;
7789  VALUE handler = parg[0];
7790  VALUE mid = parg[1];
7791  VALUE args = parg[2];
7792  return rb_apply(handler, mid, args);
7793 }
7794 
7795 static VALUE
7797 {
7798 
7799  VALUE error;
7800  VALUE e = rb_errinfo();
7801  VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
7802  VALUE msg = rb_funcall(e, rb_intern("message"), 0);
7803  bt = rb_ary_entry(bt, 0);
7804  error = rb_sprintf("%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e));
7806  rb_backtrace();
7807  ruby_finalize();
7808  exit(-1);
7809 
7810  return Qnil;
7811 }
7812 
7813 STDMETHODIMP EVENTSINK_Invoke(
7814  PEVENTSINK pEventSink,
7815  DISPID dispid,
7816  REFIID riid,
7817  LCID lcid,
7818  WORD wFlags,
7819  DISPPARAMS *pdispparams,
7820  VARIANT *pvarResult,
7821  EXCEPINFO *pexcepinfo,
7822  UINT *puArgErr
7823  ) {
7824 
7825  HRESULT hr;
7826  BSTR bstr;
7827  unsigned int count;
7828  unsigned int i;
7829  ITypeInfo *pTypeInfo;
7830  VARIANT *pvar;
7831  VALUE ary, obj, event, args, outargv, ev, result;
7832  VALUE handler = Qnil;
7833  VALUE arg[3];
7834  VALUE mid;
7835  VALUE is_outarg = Qfalse;
7836  BOOL is_default_handler = FALSE;
7837  int state;
7838 
7839  PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
7840  pTypeInfo = pEV->pTypeInfo;
7841  obj = evs_entry(pEV->m_event_id);
7842  if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
7843  return NOERROR;
7844  }
7845 
7846  ary = rb_ivar_get(obj, id_events);
7847  if (NIL_P(ary) || TYPE(ary) != T_ARRAY) {
7848  return NOERROR;
7849  }
7850  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
7851  &bstr, 1, &count);
7852  if (FAILED(hr)) {
7853  return NOERROR;
7854  }
7855  ev = WC2VSTR(bstr);
7856  event = ole_search_event(ary, ev, &is_default_handler);
7857  if (TYPE(event) == T_ARRAY) {
7858  handler = rb_ary_entry(event, 0);
7859  mid = rb_intern("call");
7860  is_outarg = rb_ary_entry(event, 3);
7861  } else {
7862  handler = rb_ivar_get(obj, rb_intern("handler"));
7863  if (handler == Qnil) {
7864  return NOERROR;
7865  }
7866  mid = ole_search_handler_method(handler, ev, &is_default_handler);
7867  }
7868  if (handler == Qnil || mid == Qnil) {
7869  return NOERROR;
7870  }
7871 
7872  args = rb_ary_new();
7873  if (is_default_handler) {
7874  rb_ary_push(args, ev);
7875  }
7876 
7877  /* make argument of event handler */
7878  for (i = 0; i < pdispparams->cArgs; ++i) {
7879  pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
7880  rb_ary_push(args, ole_variant2val(pvar));
7881  }
7882  outargv = Qnil;
7883  if (is_outarg == Qtrue) {
7884  outargv = rb_ary_new();
7885  rb_ary_push(args, outargv);
7886  }
7887 
7888  /*
7889  * if exception raised in event callback,
7890  * then you receive cfp consistency error.
7891  * to avoid this error we use begin rescue end.
7892  * and the exception raised then error message print
7893  * and exit ruby process by Win32OLE itself.
7894  */
7895  arg[0] = handler;
7896  arg[1] = mid;
7897  arg[2] = args;
7898  result = rb_protect(exec_callback, (VALUE)arg, &state);
7899  if (state != 0) {
7901  }
7902  if(TYPE(result) == T_HASH) {
7903  hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
7904  result = hash2result(result);
7905  }else if (is_outarg == Qtrue && TYPE(outargv) == T_ARRAY) {
7906  ary2ptr_dispparams(outargv, pdispparams);
7907  }
7908 
7909  if (pvarResult) {
7910  VariantInit(pvarResult);
7911  ole_val2variant(result, pvarResult);
7912  }
7913 
7914  return NOERROR;
7915 }
7916 
7917 PIEVENTSINKOBJ
7919  PIEVENTSINKOBJ pEv;
7920  if (!g_IsEventSinkVtblInitialized) {
7922  vtEventSink.AddRef = EVENTSINK_AddRef;
7923  vtEventSink.Release = EVENTSINK_Release;
7924  vtEventSink.Invoke = EVENTSINK_Invoke;
7925  vtEventSink.GetIDsOfNames = EVENTSINK_GetIDsOfNames;
7926  vtEventSink.GetTypeInfoCount = EVENTSINK_GetTypeInfoCount;
7927  vtEventSink.GetTypeInfo = EVENTSINK_GetTypeInfo;
7928 
7929  g_IsEventSinkVtblInitialized = TRUE;
7930  }
7931  pEv = ALLOC_N(IEVENTSINKOBJ, 1);
7932  if(pEv == NULL) return NULL;
7933  pEv->lpVtbl = &vtEventSink;
7934  pEv->m_cRef = 0;
7935  pEv->m_event_id = 0;
7936  pEv->pTypeInfo = NULL;
7937  return pEv;
7938 }
7939 
7941  PIEVENTSINKOBJ pEVObj
7942  ) {
7943  if(pEVObj != NULL) {
7944  OLE_RELEASE(pEVObj->pTypeInfo);
7945  free(pEVObj);
7946  pEVObj = NULL;
7947  }
7948 }
7949 
7950 static HRESULT
7951 find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
7952 {
7953  HRESULT hr;
7954  IDispatch *pDispatch;
7955  ITypeInfo *pTypeInfo;
7956  ITypeLib *pTypeLib;
7957  TYPEATTR *pTypeAttr;
7958  HREFTYPE RefType;
7959  ITypeInfo *pImplTypeInfo;
7960  TYPEATTR *pImplTypeAttr;
7961 
7962  struct oledata *pole;
7963  unsigned int index;
7964  unsigned int count;
7965  int type;
7966  BSTR bstr;
7967  char *pstr;
7968 
7969  BOOL is_found = FALSE;
7970  LCID lcid = cWIN32OLE_lcid;
7971 
7972  OLEData_Get_Struct(ole, pole);
7973 
7974  pDispatch = pole->pDispatch;
7975 
7976  hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo);
7977  if (FAILED(hr))
7978  return hr;
7979 
7980  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
7981  &pTypeLib,
7982  &index);
7983  OLE_RELEASE(pTypeInfo);
7984  if (FAILED(hr))
7985  return hr;
7986 
7987  if (!pitf) {
7988  hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
7989  piid,
7990  ppTypeInfo);
7991  OLE_RELEASE(pTypeLib);
7992  return hr;
7993  }
7994  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
7995  for (index = 0; index < count; index++) {
7996  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
7997  index,
7998  &pTypeInfo);
7999  if (FAILED(hr))
8000  break;
8001  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
8002 
8003  if(FAILED(hr)) {
8004  OLE_RELEASE(pTypeInfo);
8005  break;
8006  }
8007  if(pTypeAttr->typekind == TKIND_COCLASS) {
8008  for (type = 0; type < pTypeAttr->cImplTypes; type++) {
8009  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
8010  type,
8011  &RefType);
8012  if (FAILED(hr))
8013  break;
8014  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
8015  RefType,
8016  &pImplTypeInfo);
8017  if (FAILED(hr))
8018  break;
8019 
8020  hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo,
8021  -1,
8022  &bstr,
8023  NULL, NULL, NULL);
8024  if (FAILED(hr)) {
8025  OLE_RELEASE(pImplTypeInfo);
8026  break;
8027  }
8028  pstr = ole_wc2mb(bstr);
8029  if (strcmp(pitf, pstr) == 0) {
8030  hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo,
8031  &pImplTypeAttr);
8032  if (SUCCEEDED(hr)) {
8033  is_found = TRUE;
8034  *piid = pImplTypeAttr->guid;
8035  if (ppTypeInfo) {
8036  *ppTypeInfo = pImplTypeInfo;
8037  (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo));
8038  }
8039  pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo,
8040  pImplTypeAttr);
8041  }
8042  }
8043  free(pstr);
8044  OLE_RELEASE(pImplTypeInfo);
8045  if (is_found || FAILED(hr))
8046  break;
8047  }
8048  }
8049 
8050  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
8051  OLE_RELEASE(pTypeInfo);
8052  if (is_found || FAILED(hr))
8053  break;
8054  }
8055  OLE_RELEASE(pTypeLib);
8056  if(!is_found)
8057  return E_NOINTERFACE;
8058  return hr;
8059 }
8060 
8061 static HRESULT
8063  ITypeInfo *pTypeInfo,
8064  TYPEATTR *pTypeAttr,
8065  ITypeInfo **pCOTypeInfo,
8066  TYPEATTR **pCOTypeAttr)
8067 {
8068  HRESULT hr = E_NOINTERFACE;
8069  ITypeLib *pTypeLib;
8070  int count;
8071  BOOL found = FALSE;
8072  ITypeInfo *pTypeInfo2;
8073  TYPEATTR *pTypeAttr2;
8074  int flags;
8075  int i,j;
8076  HREFTYPE href;
8077  ITypeInfo *pRefTypeInfo;
8078  TYPEATTR *pRefTypeAttr;
8079 
8080  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
8081  if (FAILED(hr)) {
8082  return hr;
8083  }
8084  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
8085  for (i = 0; i < count && !found; i++) {
8086  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
8087  if (FAILED(hr))
8088  continue;
8089  hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
8090  if (FAILED(hr)) {
8091  OLE_RELEASE(pTypeInfo2);
8092  continue;
8093  }
8094  if (pTypeAttr2->typekind != TKIND_COCLASS) {
8095  OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
8096  OLE_RELEASE(pTypeInfo2);
8097  continue;
8098  }
8099  for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
8100  hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
8101  if (FAILED(hr))
8102  continue;
8103  if (!(flags & IMPLTYPEFLAG_FDEFAULT))
8104  continue;
8105  hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
8106  if (FAILED(hr))
8107  continue;
8108  hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
8109  if (FAILED(hr))
8110  continue;
8111  hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
8112  if (FAILED(hr)) {
8113  OLE_RELEASE(pRefTypeInfo);
8114  continue;
8115  }
8116  if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
8117  found = TRUE;
8118  }
8119  }
8120  if (!found) {
8121  OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
8122  OLE_RELEASE(pTypeInfo2);
8123  }
8124  }
8125  OLE_RELEASE(pTypeLib);
8126  if (found) {
8127  *pCOTypeInfo = pTypeInfo2;
8128  *pCOTypeAttr = pTypeAttr2;
8129  hr = S_OK;
8130  } else {
8131  hr = E_NOINTERFACE;
8132  }
8133  return hr;
8134 }
8135 
8136 static HRESULT
8138  ITypeInfo *pTypeInfo,
8139  TYPEATTR *pTypeAttr,
8140  ITypeInfo **ppTypeInfo)
8141 {
8142  int i = 0;
8143  HRESULT hr = E_NOINTERFACE;
8144  int flags;
8145  HREFTYPE hRefType;
8146  /* Enumerate all implemented types of the COCLASS */
8147  for (i = 0; i < pTypeAttr->cImplTypes; i++) {
8148  hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
8149  if (FAILED(hr))
8150  continue;
8151 
8152  /*
8153  looking for the [default] [source]
8154  we just hope that it is a dispinterface :-)
8155  */
8156  if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
8157  (flags & IMPLTYPEFLAG_FSOURCE)) {
8158 
8159  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
8160  i, &hRefType);
8161  if (FAILED(hr))
8162  continue;
8163  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
8164  hRefType, ppTypeInfo);
8165  if (SUCCEEDED(hr))
8166  break;
8167  }
8168  }
8169  return hr;
8170 }
8171 
8172 static HRESULT
8173 find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
8174 {
8175  HRESULT hr;
8176  IProvideClassInfo2 *pProvideClassInfo2;
8177  IProvideClassInfo *pProvideClassInfo;
8178  void *p;
8179 
8180  IDispatch *pDispatch;
8181  ITypeInfo *pTypeInfo;
8182  ITypeInfo *pTypeInfo2 = NULL;
8183  TYPEATTR *pTypeAttr;
8184  TYPEATTR *pTypeAttr2 = NULL;
8185 
8186  struct oledata *pole;
8187 
8188  OLEData_Get_Struct(ole, pole);
8189  pDispatch = pole->pDispatch;
8190  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
8191  &IID_IProvideClassInfo2,
8192  &p);
8193  if (SUCCEEDED(hr)) {
8194  pProvideClassInfo2 = p;
8195  hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
8196  GUIDKIND_DEFAULT_SOURCE_DISP_IID,
8197  piid);
8198  OLE_RELEASE(pProvideClassInfo2);
8199  if (SUCCEEDED(hr)) {
8200  hr = find_iid(ole, NULL, piid, ppTypeInfo);
8201  }
8202  }
8203  if (SUCCEEDED(hr)) {
8204  return hr;
8205  }
8206  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
8207  &IID_IProvideClassInfo,
8208  &p);
8209  if (SUCCEEDED(hr)) {
8210  pProvideClassInfo = p;
8211  hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
8212  &pTypeInfo);
8213  OLE_RELEASE(pProvideClassInfo);
8214  }
8215  if (FAILED(hr)) {
8216  hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
8217  }
8218  if (FAILED(hr))
8219  return hr;
8220  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
8221  if (FAILED(hr)) {
8222  OLE_RELEASE(pTypeInfo);
8223  return hr;
8224  }
8225 
8226  *ppTypeInfo = 0;
8227  hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
8228  if (!*ppTypeInfo) {
8229  hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
8230  if (SUCCEEDED(hr)) {
8231  hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
8232  OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
8233  OLE_RELEASE(pTypeInfo2);
8234  }
8235  }
8236  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
8237  OLE_RELEASE(pTypeInfo);
8238  /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
8239  if (!*ppTypeInfo) {
8240  if (SUCCEEDED(hr))
8241  hr = E_UNEXPECTED;
8242  return hr;
8243  }
8244 
8245  /* Determine IID of default source interface */
8246  hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr);
8247  if (SUCCEEDED(hr)) {
8248  *piid = pTypeAttr->guid;
8249  (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr);
8250  }
8251  else
8252  OLE_RELEASE(*ppTypeInfo);
8253 
8254  return hr;
8255 
8256 }
8257 
8258 static void
8260 {
8261  if (poleev->pConnectionPoint) {
8262  poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
8263  OLE_RELEASE(poleev->pConnectionPoint);
8264  poleev->pConnectionPoint = NULL;
8265  }
8266  free(poleev);
8267 }
8268 
8269 static VALUE
8271 {
8272  VALUE obj;
8273  struct oleeventdata *poleev;
8274  obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev);
8275  poleev->dwCookie = 0;
8276  poleev->pConnectionPoint = NULL;
8277  poleev->event_id = 0;
8278  return obj;
8279 }
8280 
8281 static VALUE
8283 {
8284 
8285  VALUE ole, itf;
8286  struct oledata *pole;
8287  char *pitf;
8288  HRESULT hr;
8289  IID iid;
8290  ITypeInfo *pTypeInfo = 0;
8291  IDispatch *pDispatch;
8292  IConnectionPointContainer *pContainer;
8293  IConnectionPoint *pConnectionPoint;
8294  IEVENTSINKOBJ *pIEV;
8295  DWORD dwCookie;
8296  struct oleeventdata *poleev;
8297  void *p;
8298 
8299  rb_secure(4);
8300  rb_scan_args(argc, argv, "11", &ole, &itf);
8301 
8302  if (!rb_obj_is_kind_of(ole, cWIN32OLE)) {
8303  rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object");
8304  }
8305 
8306  if(TYPE(itf) != T_NIL) {
8307  if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) {
8308  rb_raise(rb_eSecurityError, "Insecure Event Creation - %s",
8309  StringValuePtr(itf));
8310  }
8311  SafeStringValue(itf);
8312  pitf = StringValuePtr(itf);
8313  hr = find_iid(ole, pitf, &iid, &pTypeInfo);
8314  }
8315  else {
8316  hr = find_default_source(ole, &iid, &pTypeInfo);
8317  }
8318  if (FAILED(hr)) {
8319  ole_raise(hr, rb_eRuntimeError, "interface not found");
8320  }
8321 
8322  OLEData_Get_Struct(ole, pole);
8323  pDispatch = pole->pDispatch;
8324  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
8325  &IID_IConnectionPointContainer,
8326  &p);
8327  if (FAILED(hr)) {
8328  OLE_RELEASE(pTypeInfo);
8330  "failed to query IConnectionPointContainer");
8331  }
8332  pContainer = p;
8333 
8334  hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
8335  &iid,
8336  &pConnectionPoint);
8337  OLE_RELEASE(pContainer);
8338  if (FAILED(hr)) {
8339  OLE_RELEASE(pTypeInfo);
8340  ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint");
8341  }
8342  pIEV = EVENTSINK_Constructor();
8343  pIEV->m_iid = iid;
8344  hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
8345  (IUnknown*)pIEV,
8346  &dwCookie);
8347  if (FAILED(hr)) {
8348  ole_raise(hr, rb_eRuntimeError, "Advise Error");
8349  }
8350 
8351  Data_Get_Struct(self, struct oleeventdata, poleev);
8352  pIEV->m_event_id
8353  = NUM2INT(evs_length());
8354  pIEV->pTypeInfo = pTypeInfo;
8355  poleev->dwCookie = dwCookie;
8357  poleev->event_id = pIEV->m_event_id;
8358 
8359  return self;
8360 }
8361 
8362 /*
8363  * call-seq:
8364  * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
8365  *
8366  * Returns OLE event object.
8367  * The first argument specifies WIN32OLE object.
8368  * The second argument specifies OLE event name.
8369  * ie = WIN32OLE.new('InternetExplorer.Application')
8370  * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
8371  */
8372 static VALUE
8374 {
8375  ev_advise(argc, argv, self);
8376  evs_push(self);
8377  rb_ivar_set(self, id_events, rb_ary_new());
8378  fev_set_handler(self, Qnil);
8379  return self;
8380 }
8381 
8382 /*
8383  * call-seq:
8384  * WIN32OLE_EVENT.message_loop
8385  *
8386  * Translates and dispatches Windows message.
8387  */
8388 static VALUE
8390 {
8391  ole_msg_loop();
8392  return Qnil;
8393 }
8394 
8395 
8396 static void
8398 {
8399  VALUE events = rb_ivar_get(obj, id_events);
8400  if (NIL_P(events) || TYPE(events) != T_ARRAY) {
8401  events = rb_ary_new();
8402  rb_ivar_set(obj, id_events, events);
8403  }
8404  ole_delete_event(events, event);
8405  rb_ary_push(events, data);
8406 }
8407 
8408 static VALUE
8409 ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
8410 {
8411  struct oleeventdata *poleev;
8412  VALUE event, args, data;
8413  Data_Get_Struct(self, struct oleeventdata, poleev);
8414  if (poleev->pConnectionPoint == NULL) {
8415  rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
8416  }
8417  rb_scan_args(argc, argv, "01*", &event, &args);
8418  if(!NIL_P(event)) {
8419  if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) {
8420  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
8421  }
8422  if (TYPE(event) == T_SYMBOL) {
8423  event = rb_sym_to_s(event);
8424  }
8425  }
8426  data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
8427  add_event_call_back(self, event, data);
8428  return Qnil;
8429 }
8430 
8431 /*
8432  * call-seq:
8433  * WIN32OLE_EVENT#on_event([event]){...}
8434  *
8435  * Defines the callback event.
8436  * If argument is omitted, this method defines the callback of all events.
8437  * If you want to modify reference argument in callback, return hash in
8438  * callback. If you want to return value to OLE server as result of callback
8439  * use `return' or :return.
8440  *
8441  * ie = WIN32OLE.new('InternetExplorer.Application')
8442  * ev = WIN32OLE_EVENT.new(ie)
8443  * ev.on_event("NavigateComplete") {|url| puts url}
8444  * ev.on_event() {|ev, *args| puts "#{ev} fired"}
8445  *
8446  * ev.on_event("BeforeNavigate2") {|*args|
8447  * ...
8448  * # set true to BeforeNavigate reference argument `Cancel'.
8449  * # Cancel is 7-th argument of BeforeNavigate,
8450  * # so you can use 6 as key of hash instead of 'Cancel'.
8451  * # The argument is counted from 0.
8452  * # The hash key of 0 means first argument.)
8453  * {:Cancel => true} # or {'Cancel' => true} or {6 => true}
8454  * }
8455  *
8456  * ev.on_event(...) {|*args|
8457  * {:return => 1, :xxx => yyy}
8458  * }
8459  */
8460 static VALUE
8462 {
8463  return ev_on_event(argc, argv, self, Qfalse);
8464 }
8465 
8466 /*
8467  * call-seq:
8468  * WIN32OLE_EVENT#on_event_with_outargs([event]){...}
8469  *
8470  * Defines the callback of event.
8471  * If you want modify argument in callback,
8472  * you could use this method instead of WIN32OLE_EVENT#on_event.
8473  *
8474  * ie = WIN32OLE.new('InternetExplorer.Application')
8475  * ev = WIN32OLE_EVENT.new(ie)
8476  * ev.on_event_with_outargs('BeforeNavigate2') {|*args|
8477  * args.last[6] = true
8478  * }
8479  */
8480 static VALUE
8482 {
8483  return ev_on_event(argc, argv, self, Qtrue);
8484 }
8485 
8486 /*
8487  * call-seq:
8488  * WIN32OLE_EVENT#off_event([event])
8489  *
8490  * removes the callback of event.
8491  *
8492  * ie = WIN32OLE.new('InternetExplorer.Application')
8493  * ev = WIN32OLE_EVENT.new(ie)
8494  * ev.on_event('BeforeNavigate2') {|*args|
8495  * args.last[6] = true
8496  * }
8497  * ...
8498  * ev.off_event('BeforeNavigate2')
8499  * ...
8500  */
8501 static VALUE
8503 {
8504  VALUE event = Qnil;
8505  VALUE events;
8506 
8507  rb_secure(4);
8508  rb_scan_args(argc, argv, "01", &event);
8509  if(!NIL_P(event)) {
8510  if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) {
8511  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
8512  }
8513  if (TYPE(event) == T_SYMBOL) {
8514  event = rb_sym_to_s(event);
8515  }
8516  }
8517  events = rb_ivar_get(self, id_events);
8518  if (NIL_P(events)) {
8519  return Qnil;
8520  }
8521  ole_delete_event(events, event);
8522  return Qnil;
8523 }
8524 
8525 /*
8526  * call-seq:
8527  * WIN32OLE_EVENT#unadvise -> nil
8528  *
8529  * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
8530  * does not receive the OLE server event any more.
8531  * This method is trial implementation.
8532  *
8533  * ie = WIN32OLE.new('InternetExplorer.Application')
8534  * ev = WIN32OLE_EVENT.new(ie)
8535  * ev.on_event() {...}
8536  * ...
8537  * ev.unadvise
8538  *
8539  */
8540 static VALUE
8542 {
8543  struct oleeventdata *poleev;
8544  Data_Get_Struct(self, struct oleeventdata, poleev);
8545  if (poleev->pConnectionPoint) {
8546  ole_msg_loop();
8547  evs_delete(poleev->event_id);
8548  poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
8549  OLE_RELEASE(poleev->pConnectionPoint);
8550  poleev->pConnectionPoint = NULL;
8551  }
8552  return Qnil;
8553 }
8554 
8555 static VALUE
8557 {
8558  return rb_ary_push(ary_ole_event, ev);
8559 }
8560 
8561 static VALUE
8562 evs_delete(long i)
8563 {
8565  return Qnil;
8566 }
8567 
8568 static VALUE
8569 evs_entry(long i)
8570 {
8571  return rb_ary_entry(ary_ole_event, i);
8572 }
8573 
8574 static VALUE
8576 {
8577  return rb_funcall(ary_ole_event, rb_intern("length"), 0);
8578 }
8579 
8580 /*
8581  * call-seq:
8582  * WIN32OLE_EVENT#handler=
8583  *
8584  * sets event handler object. If handler object has onXXX
8585  * method according to XXX event, then onXXX method is called
8586  * when XXX event occurs.
8587  *
8588  * If handler object has method_missing and there is no
8589  * method according to the event, then method_missing
8590  * called and 1-st argument is event name.
8591  *
8592  * If handler object has onXXX method and there is block
8593  * defined by WIN32OLE_EVENT#on_event('XXX'){},
8594  * then block is executed but handler object method is not called
8595  * when XXX event occurs.
8596  *
8597  * class Handler
8598  * def onStatusTextChange(text)
8599  * puts "StatusTextChanged"
8600  * end
8601  * def onPropertyChange(prop)
8602  * puts "PropertyChanged"
8603  * end
8604  * def method_missing(ev, *arg)
8605  * puts "other event #{ev}"
8606  * end
8607  * end
8608  *
8609  * handler = Handler.new
8610  * ie = WIN32OLE.new('InternetExplorer.Application')
8611  * ev = WIN32OLE_EVENT.new(ie)
8612  * ev.on_event("StatusTextChange") {|*args|
8613  * puts "this block executed."
8614  * puts "handler.onStatusTextChange method is not called."
8615  * }
8616  * ev.handler = handler
8617  *
8618  */
8619 static VALUE
8621 {
8622  return rb_ivar_set(self, rb_intern("handler"), val);
8623 }
8624 
8625 /*
8626  * call-seq:
8627  * WIN32OLE_EVENT#handler
8628  *
8629  * returns handler object.
8630  *
8631  */
8632 static VALUE
8634 {
8635  return rb_ivar_get(self, rb_intern("handler"));
8636 }
8637 
8638 static void
8640 {
8641  VariantClear(&(pvar->realvar));
8642  VariantClear(&(pvar->var));
8643  free(pvar);
8644 }
8645 
8646 static VALUE
8648 {
8649  struct olevariantdata *pvar;
8650  VALUE obj;
8651  ole_initialize();
8652  obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar);
8653  VariantInit(&(pvar->var));
8654  VariantInit(&(pvar->realvar));
8655  return obj;
8656 }
8657 
8658 /*
8659  * call-seq:
8660  * WIN32OLE_VARIANT.array(ary, vt)
8661  *
8662  * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
8663  * The first argument should be Array object which specifies dimensions
8664  * and each size of dimensions of OLE array.
8665  * The second argument specifies variant type of the element of OLE array.
8666  *
8667  * The following create 2 dimensions OLE array. The first dimensions size
8668  * is 3, and the second is 4.
8669  *
8670  * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
8671  * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
8672  *
8673  */
8674 static VALUE
8676 {
8677  VALUE obj = Qnil;
8678  VARTYPE vt;
8679  struct olevariantdata *pvar;
8680  SAFEARRAYBOUND *psab = NULL;
8681  SAFEARRAY *psa = NULL;
8682  UINT dim = 0;
8683  UINT i = 0;
8684 
8685  ole_initialize();
8686 
8687  vt = NUM2UINT(vvt);
8688  vt = (vt | VT_ARRAY);
8689  Check_Type(elems, T_ARRAY);
8690  obj = folevariant_s_allocate(klass);
8691 
8692  Data_Get_Struct(obj, struct olevariantdata, pvar);
8693  dim = RARRAY_LEN(elems);
8694 
8695  psab = ALLOC_N(SAFEARRAYBOUND, dim);
8696 
8697  if(!psab) {
8698  rb_raise(rb_eRuntimeError, "memory allocation error");
8699  }
8700 
8701  for (i = 0; i < dim; i++) {
8702  psab[i].cElements = FIX2INT(rb_ary_entry(elems, i));
8703  psab[i].lLbound = 0;
8704  }
8705 
8706  psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
8707  if (psa == NULL) {
8708  if (psab) free(psab);
8709  rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
8710  }
8711 
8712  V_VT(&(pvar->var)) = vt;
8713  if (vt & VT_BYREF) {
8714  V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
8715  V_ARRAY(&(pvar->realvar)) = psa;
8716  V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
8717  } else {
8718  V_ARRAY(&(pvar->var)) = psa;
8719  }
8720  if (psab) free(psab);
8721  return obj;
8722 }
8723 
8724 /*
8725  * call-seq:
8726  * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object.
8727  *
8728  * Returns Ruby object wrapping OLE variant.
8729  * The first argument specifies Ruby object to convert OLE variant variable.
8730  * The second argument specifies VARIANT type.
8731  * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method
8732  *
8733  * shell = WIN32OLE.new("Shell.Application")
8734  * folder = shell.NameSpace("C:\\Windows")
8735  * item = folder.ParseName("tmp.txt")
8736  * # You can't use Ruby String object to call FolderItem.InvokeVerb.
8737  * # Instead, you have to use WIN32OLE_VARIANT object to call the method.
8738  * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
8739  * item.invokeVerb(shortcut)
8740  *
8741  */
8742 static VALUE
8744 {
8745  int len = 0;
8746  VARIANT var;
8747  VALUE val;
8748  VALUE vvt;
8749  VARTYPE vt;
8750  struct olevariantdata *pvar;
8751 
8752  len = RARRAY_LEN(args);
8753  if (len < 1 || len > 3) {
8754  rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
8755  }
8756  VariantInit(&var);
8757  val = rb_ary_entry(args, 0);
8758 
8759  if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
8761  !rb_obj_is_kind_of(val, rb_cTime)) {
8762  switch (TYPE(val)) {
8763  case T_ARRAY:
8764  case T_STRING:
8765  case T_FIXNUM:
8766  case T_BIGNUM:
8767  case T_FLOAT:
8768  case T_TRUE:
8769  case T_FALSE:
8770  case T_NIL:
8771  break;
8772  default:
8773  rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
8774  rb_obj_classname(val));
8775  }
8776  }
8777 
8778  Data_Get_Struct(self, struct olevariantdata, pvar);
8779  if (len == 1) {
8780  ole_val2variant(val, &(pvar->var));
8781  } else {
8782  vvt = rb_ary_entry(args, 1);
8783  vt = NUM2INT(vvt);
8784  ole_val2olevariantdata(val, vt, pvar);
8785  }
8786  vt = V_VT(&pvar->var);
8787  return self;
8788 }
8789 
8790 static SAFEARRAY *
8792 {
8793  struct olevariantdata *pvar;
8794  SAFEARRAY *psa = NULL;
8795  HRESULT hr;
8796  Data_Get_Struct(val, struct olevariantdata, pvar);
8797  if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
8798  rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
8799  }
8800  psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
8801  if (psa == NULL) {
8802  return psa;
8803  }
8804  hr = SafeArrayLock(psa);
8805  if (FAILED(hr)) {
8806  ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
8807  }
8808  return psa;
8809 }
8810 
8811 static long *
8812 ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
8813 {
8814  long dim;
8815  long *pid;
8816  long i;
8817  dim = SafeArrayGetDim(psa);
8818  if (dim != ary_size) {
8819  rb_raise(rb_eArgError, "unmatch number of indices");
8820  }
8821  pid = ALLOC_N(long, dim);
8822  if (pid == NULL) {
8823  rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
8824  }
8825  for (i = 0; i < dim; i++) {
8826  pid[i] = NUM2INT(ary[i]);
8827  }
8828  return pid;
8829 }
8830 
8831 static void
8832 unlock_safe_array(SAFEARRAY *psa)
8833 {
8834  HRESULT hr;
8835  hr = SafeArrayUnlock(psa);
8836  if (FAILED(hr)) {
8837  ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
8838  }
8839 }
8840 
8841 /*
8842  * call-seq:
8843  * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array.
8844  *
8845  * Returns the element of WIN32OLE_VARIANT object(OLE array).
8846  * This method is available only when the variant type of
8847  * WIN32OLE_VARIANT object is VT_ARRAY.
8848  *
8849  * REMARK:
8850  * The all indicies should be 0 or natural number and
8851  * lower than or equal to max indicies.
8852  * (This point is different with Ruby Array indicies.)
8853  *
8854  * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
8855  * p obj[0,0] # => 1
8856  * p obj[1,0] # => 4
8857  * p obj[2,0] # => WIN32OLERuntimeError
8858  * p obj[0, -1] # => WIN32OLERuntimeError
8859  *
8860  */
8861 static VALUE
8863 {
8864  struct olevariantdata *pvar;
8865  SAFEARRAY *psa;
8866  VALUE val = Qnil;
8867  VARIANT variant;
8868  long *pid;
8869  HRESULT hr;
8870 
8871  Data_Get_Struct(self, struct olevariantdata, pvar);
8872  if (!V_ISARRAY(&(pvar->var))) {
8874  "`[]' is not available for this variant type object");
8875  }
8876  psa = get_locked_safe_array(self);
8877  if (psa == NULL) {
8878  return val;
8879  }
8880 
8881  pid = ary2safe_array_index(argc, argv, psa);
8882 
8883  VariantInit(&variant);
8884  V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF;
8885  hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
8886  if (FAILED(hr)) {
8887  ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex");
8888  }
8889  val = ole_variant2val(&variant);
8890 
8891  unlock_safe_array(psa);
8892  if (pid) free(pid);
8893  return val;
8894 }
8895 
8896 static VOID *
8897 val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
8898 {
8899  VOID *p = NULL;
8900  HRESULT hr = S_OK;
8901  ole_val2variant_ex(val, var, vt);
8902  if ((vt & ~VT_BYREF) == VT_VARIANT) {
8903  p = var;
8904  } else {
8905  if ( (vt & ~VT_BYREF) != V_VT(var)) {
8906  hr = VariantChangeTypeEx(var, var,
8907  cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
8908  if (FAILED(hr)) {
8909  ole_raise(hr, rb_eRuntimeError, "failed to change type");
8910  }
8911  }
8912  p = get_ptr_of_variant(var);
8913  }
8914  if (p == NULL) {
8915  rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
8916  }
8917  return p;
8918 }
8919 
8920 /*
8921  * call-seq:
8922  * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array
8923  *
8924  * Set the element of WIN32OLE_VARIANT object(OLE array) to val.
8925  * This method is available only when the variant type of
8926  * WIN32OLE_VARIANT object is VT_ARRAY.
8927  *
8928  * REMARK:
8929  * The all indicies should be 0 or natural number and
8930  * lower than or equal to max indicies.
8931  * (This point is different with Ruby Array indicies.)
8932  *
8933  * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
8934  * obj[0,0] = 7
8935  * obj[1,0] = 8
8936  * p obj.value # => [[7,2,3], [8,5,6]]
8937  * obj[2,0] = 9 # => WIN32OLERuntimeError
8938  * obj[0, -1] = 9 # => WIN32OLERuntimeError
8939  *
8940  */
8941 static VALUE
8943 {
8944  struct olevariantdata *pvar;
8945  SAFEARRAY *psa;
8946  VARIANT var;
8947  VARTYPE vt;
8948  long *pid;
8949  HRESULT hr;
8950  VOID *p = NULL;
8951 
8952  Data_Get_Struct(self, struct olevariantdata, pvar);
8953  if (!V_ISARRAY(&(pvar->var))) {
8955  "`[]' is not available for this variant type object");
8956  }
8957  psa = get_locked_safe_array(self);
8958  if (psa == NULL) {
8959  rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
8960  }
8961 
8962  pid = ary2safe_array_index(argc-1, argv, psa);
8963 
8964  VariantInit(&var);
8965  vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
8966  p = val2variant_ptr(argv[argc-1], &var, vt);
8967  if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
8968  (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
8969  rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
8970  }
8971  hr = SafeArrayPutElement(psa, pid, p);
8972  if (FAILED(hr)) {
8973  ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
8974  }
8975 
8976  unlock_safe_array(psa);
8977  if (pid) free(pid);
8978  return argv[argc-1];
8979 }
8980 
8981 /*
8982  * call-seq:
8983  * WIN32OLE_VARIANT.value #=> Ruby object.
8984  *
8985  * Returns Ruby object value from OLE variant.
8986  * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR)
8987  * obj.value # => "1" (not Fixnum object, but String object "1")
8988  *
8989  */
8990 static VALUE
8992 {
8993  struct olevariantdata *pvar;
8994  VALUE val = Qnil;
8995  VARTYPE vt;
8996  int dim;
8997  SAFEARRAY *psa;
8998  Data_Get_Struct(self, struct olevariantdata, pvar);
8999 
9000  val = ole_variant2val(&(pvar->var));
9001  vt = V_VT(&(pvar->var));
9002 
9003  if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) {
9004  if (vt & VT_BYREF) {
9005  psa = *V_ARRAYREF(&(pvar->var));
9006  } else {
9007  psa = V_ARRAY(&(pvar->var));
9008  }
9009  if (!psa) {
9010  return val;
9011  }
9012  dim = SafeArrayGetDim(psa);
9013  if (dim == 1) {
9014  val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*"));
9015  }
9016  }
9017  return val;
9018 }
9019 
9020 /*
9021  * call-seq:
9022  * WIN32OLE_VARIANT.vartype #=> OLE variant type.
9023  *
9024  * Returns OLE variant type.
9025  * obj = WIN32OLE_VARIANT.new("string")
9026  * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
9027  *
9028  */
9029 static VALUE
9031 {
9032  struct olevariantdata *pvar;
9033  Data_Get_Struct(self, struct olevariantdata, pvar);
9034  return INT2FIX(V_VT(&pvar->var));
9035 }
9036 
9037 /*
9038  * call-seq:
9039  * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
9040  *
9041  * Sets variant value to val. If the val type does not match variant value
9042  * type(vartype), then val is changed to match variant value type(vartype)
9043  * before setting val.
9044  * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
9045  * If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
9046  *
9047  * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
9048  * obj.value = 3.2 # 3.2 is changed to 3 when setting value.
9049  * p obj.value # => 3
9050  */
9051 static VALUE
9053 {
9054  struct olevariantdata *pvar;
9055  VARTYPE vt;
9056  Data_Get_Struct(self, struct olevariantdata, pvar);
9057  vt = V_VT(&(pvar->var));
9058  if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) {
9060  "`value=' is not available for this variant type object");
9061  }
9062  ole_val2olevariantdata(val, vt, pvar);
9063  return Qnil;
9064 }
9065 
9066 static void
9068 {
9069  enc2cp_table = st_init_numtable();
9070 }
9071 
9072 static void
9074 {
9075  st_free_table(enc2cp_table);
9076 }
9077 
9078 void
9080 {
9084  id_events = rb_intern("events");
9085 
9086  com_vtbl.QueryInterface = QueryInterface;
9087  com_vtbl.AddRef = AddRef;
9088  com_vtbl.Release = Release;
9089  com_vtbl.GetTypeInfoCount = GetTypeInfoCount;
9090  com_vtbl.GetTypeInfo = GetTypeInfo;
9091  com_vtbl.GetIDsOfNames = GetIDsOfNames;
9092  com_vtbl.Invoke = Invoke;
9093 
9094  message_filter.QueryInterface = mf_QueryInterface;
9095  message_filter.AddRef = mf_AddRef;
9096  message_filter.Release = mf_Release;
9097  message_filter.HandleInComingCall = mf_HandleInComingCall;
9098  message_filter.RetryRejectedCall = mf_RetryRejectedCall;
9099  message_filter.MessagePending = mf_MessagePending;
9100 
9103 
9104  cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
9105 
9107 
9108  rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1);
9109 
9112 
9114  rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1);
9115  rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1);
9123 
9124  rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1);
9126  rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3);
9127  rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3);
9128  rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3);
9129 
9130  /* support propput method that takes an argument */
9132 
9133  rb_define_method(cWIN32OLE, "ole_free", fole_free, 0);
9134 
9135  rb_define_method(cWIN32OLE, "each", fole_each, 0);
9136  rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1);
9137 
9138  /* support setproperty method much like Perl ;-) */
9139  rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1);
9140 
9141  rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0);
9142  rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0);
9143  rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0);
9144  rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0);
9145 
9146  rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1);
9147  rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method");
9148  rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0);
9149  rb_define_method(cWIN32OLE, "ole_type", fole_type, 0);
9150  rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type");
9151  rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0);
9152  rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1);
9153  rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1);
9154 
9156  rb_define_const(cWIN32OLE, "ARGV", rb_ary_new());
9157 
9158  rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP));
9159  rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP));
9160  rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP));
9161  rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP));
9162  rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL));
9163  rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7));
9164  rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8));
9165 
9166  rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT));
9167  rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT));
9168 
9170  rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY));
9171  rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL));
9172  rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2));
9173  rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4));
9174  rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4));
9175  rb_define_const(mWIN32OLE_VARIANT, "VT_R8", INT2FIX(VT_R8));
9176  rb_define_const(mWIN32OLE_VARIANT, "VT_CY", INT2FIX(VT_CY));
9177  rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", INT2FIX(VT_DATE));
9178  rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", INT2FIX(VT_BSTR));
9179  rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", INT2FIX(VT_USERDEFINED));
9180  rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", INT2FIX(VT_PTR));
9181  rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", INT2FIX(VT_DISPATCH));
9182  rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", INT2FIX(VT_ERROR));
9183  rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", INT2FIX(VT_BOOL));
9184  rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", INT2FIX(VT_VARIANT));
9185  rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", INT2FIX(VT_UNKNOWN));
9186  rb_define_const(mWIN32OLE_VARIANT, "VT_I1", INT2FIX(VT_I1));
9187  rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1));
9188  rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2));
9189  rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4));
9190 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
9191  rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8));
9192  rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8));
9193 #endif
9194  rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT));
9195  rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT));
9196  rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY));
9197  rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF));
9198 
9199  cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject);
9210  rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types");
9213  rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name");
9215 
9216  cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject);
9227  rb_define_alias(cWIN32OLE_TYPE, "to_s", "name");
9236  rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0);
9238  rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0);
9240  rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0);
9243 
9244  cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject);
9253  rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name");
9254 
9255  cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject);
9275  rb_define_alias(cWIN32OLE_METHOD, "to_s", "name");
9277 
9278  cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject);
9289  rb_define_alias(cWIN32OLE_PARAM, "to_s", "name");
9291 
9292  cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
9295  rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
9296  rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
9297  rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
9298  rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
9302 
9303  cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
9314  rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH)));
9315 
9316  eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError);
9317 
9318  init_enc2cp();
9319  atexit((void (*)(void))free_enc2cp);
9320  ole_init_cp();
9321 }
static void olevariant_free(struct olevariantdata *pvar)
Definition: win32ole.c:8639
static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
Definition: win32ole.c:3790
static VALUE foletype_helpfile(VALUE self)
Definition: win32ole.c:5942
static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti)
Definition: win32ole.c:4233
static VALUE fole_s_set_locale(VALUE self, VALUE vlcid)
Definition: win32ole.c:3109
static DWORD HTASK DWORD LPINTERFACEINFO lpInterfaceInfo
Definition: win32ole.c:633
static VALUE method_name(VALUE obj)
Definition: proc.c:1153
static VALUE foletype_minor_version(VALUE self)
Definition: win32ole.c:5819
static BOOL lcid_installed(LCID lcid)
Definition: win32ole.c:3090
#define load_conv_function51932()
Definition: win32ole.c:955
#define ALLOC(type)
static VALUE foletype_visible(VALUE self)
Definition: win32ole.c:5759
static IDispatchVtbl com_vtbl
Definition: win32ole.c:234
IDispatch dispatch
Definition: win32ole.c:697
VALUE rb_ary_unshift(VALUE ary, VALUE item)
Definition: array.c:1084
#define RUBY_EVENT_THREAD_END
static VALUE foletypelib_ole_types(VALUE self)
Definition: win32ole.c:5516
static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8481
VALUE cWIN32OLE_PROPERTY
Definition: win32ole.c:213
static VALUE folemethod_return_type_detail(VALUE self)
Definition: win32ole.c:6699
static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
Definition: win32ole.c:6243
#define FIXNUM_FLAG
VALUE cWIN32OLE_PARAM
Definition: win32ole.c:208
STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK pEventSink, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
Definition: win32ole.c:7813
static VALUE foletype_impl_ole_types(VALUE self)
Definition: win32ole.c:6045
static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
Definition: win32ole.c:8409
static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask)
Definition: win32ole.c:4166
pure parser lex param
Definition: ripper.y:687
UINT CodePage
Definition: win32ole.c:1008
static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
Definition: win32ole.c:8173
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6673
static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
Definition: win32ole.c:3588
static VALUE foletype_guid(VALUE self)
Definition: win32ole.c:5689
UINT method_index
Definition: win32ole.c:279
static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:4566
#define FALSE
Definition: nkf.h:174
static VALUE folemethod_dispid(VALUE self)
Definition: win32ole.c:7061
static HWND ole_show_help(VALUE helpfile, VALUE helpcontext)
Definition: win32ole.c:2946
static VALUE foletype_s_allocate(VALUE klass)
Definition: win32ole.c:4877
static char g_lcid_to_check[8+1]
Definition: win32ole.c:239
size_t strlen(const char *)
static VALUE fev_unadvise(VALUE self)
Definition: win32ole.c:8541
static VALUE folemethod_size_opt_params(VALUE self)
Definition: win32ole.c:7155
int i
Definition: win32ole.c:784
static VALUE foleparam_input(VALUE self)
Definition: win32ole.c:7420
unsigned long VALUE
Definition: ripper.y:104
static VALUE evs_entry(long i)
Definition: win32ole.c:8569
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:3850
static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid)
Definition: win32ole.c:2577
int minor
Definition: tcltklib.c:110
static VALUE fole_s_ole_uninitialize(VALUE self)
Definition: win32ole.c:3168
void ruby_finalize(void)
Runs the VM finalization processes.
Definition: eval.c:138
int count
Definition: encoding.c:51
static DWORD HTASK threadIDCaller
Definition: win32ole.c:628
int st_lookup(st_table *, st_data_t, st_data_t *)
static VALUE foletypelib_minor_version(VALUE self)
Definition: win32ole.c:5348
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
PIEVENTSINKOBJ EVENTSINK_Constructor()
Definition: win32ole.c:7918
EVENTSINK_AddRef(PEVENTSINK pEV)
Definition: win32ole.c:7603
static VALUE ev_advise(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8282
static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
Definition: win32ole.c:3826
static VALUE folemethod_event_interface(VALUE self)
Definition: win32ole.c:6910
static long ole_search_event_at(VALUE ary, VALUE ev)
Definition: win32ole.c:7657
VALUE rb_sym_to_s(VALUE)
Definition: string.c:7907
STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK pEV, REFIID iid, LPVOID *ppv)
Definition: win32ole.c:7584
static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
Definition: win32ole.c:1885
#define va_init_list(a, b)
Definition: win32ole.c:49
static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
Definition: win32ole.c:4888
static VALUE foletype_default_event_sources(VALUE self)
Definition: win32ole.c:6080
st_table * st_init_numtable(void)
Definition: st.c:272
static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
Definition: win32ole.c:7682
#define Data_Make_Struct(klass, type, mark, free, sval)
static VALUE ole_methods(VALUE self, int mask)
Definition: win32ole.c:4274
static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:7163
STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK pEventSink, REFIID riid, OLECHAR **szNames, UINT cNames, LCID lcid, DISPID *pDispID)
Definition: win32ole.c:7639
static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
Definition: win32ole.c:7734
VALUE rb_ary_delete_at(VALUE ary, long pos)
Definition: array.c:2813
static REFIID LPOLESTR __RPC_FAR * rgszNames
Definition: win32ole.c:305
static VALUE reg_get_typelib_file_path(HKEY hkey)
Definition: win32ole.c:2402
static VALUE evs_delete(long i)
Definition: win32ole.c:8562
void rb_secure(int)
Definition: safe.c:79
static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
Definition: win32ole.c:7362
static VALUE foleparam_output(VALUE self)
Definition: win32ole.c:7447
static volatile DWORD g_ole_initialized_key
Definition: win32ole.c:222
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1876
static VALUE fole_func_methods(VALUE self)
Definition: win32ole.c:4353
#define UI8_2_NUM
Definition: win32ole.c:139
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:2309
VARIANT realvar
Definition: win32ole.c:295
static LCID cWIN32OLE_lcid
Definition: win32ole.c:236
#define g_ole_initialized_set(val)
Definition: win32ole.c:225
static DWORD HTASK DWORD dwTickCount
Definition: win32ole.c:628
static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5921
static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim)
Definition: win32ole.c:2042
RUBY_EXTERN VALUE rb_cTime
Definition: ripper.y:1460
static VALUE fev_on_event(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8461
static VALUE folevariable_varkind(VALUE self)
Definition: win32ole.c:6497
#define rb_enc_name(enc)
ITypeInfo * pTypeInfo
Definition: win32ole.c:268
const int id
Definition: nkf.c:209
VALUE cWIN32OLE
Definition: win32ole.c:203
long event_id
Definition: win32ole.c:286
static VALUE foletype_inspect(VALUE self)
Definition: win32ole.c:6115
static VALUE reg_enum_key(HKEY hkey, DWORD i)
Definition: win32ole.c:2342
static REFIID LPOLESTR __RPC_FAR UINT cNames
Definition: win32ole.c:305
#define strcasecmp
Definition: win32.h:200
static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6721
BOOL( FNENUMSYSEMCODEPAGES)(CODEPAGE_ENUMPROC, DWORD)
Definition: win32ole.c:153
static VALUE typelib_file_from_typelib(VALUE ole)
Definition: win32ole.c:2446
static VALUE foletype_s_progids(VALUE self)
Definition: win32ole.c:4846
static IEventSinkVtbl vtEventSink
Definition: win32ole.c:7578
static VALUE foletype_helpcontext(VALUE self)
Definition: win32ole.c:5970
VALUE rb_eTypeError
Definition: error.c:511
static DWORD dwCallType
Definition: win32ole.c:628
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
static VALUE fole_free(VALUE self)
Definition: win32ole.c:3963
#define OBJ_TAINTED(x)
static rb_encoding * cWIN32OLE_enc
Definition: win32ole.c:237
static UINT cWIN32OLE_cp
Definition: win32ole.c:235
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1373
#define NUM2I8
Definition: win32ole.c:140
static BOOL CALLBACK installed_lcid_proc(LPTSTR str)
Definition: win32ole.c:3080
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
Definition: win32ole.c:4415
static VALUE make_inspect(const char *class_name, VALUE detail)
Definition: win32ole.c:1990
static void init_enc2cp(void)
Definition: win32ole.c:9067
static VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:2075
static VALUE fole_type(VALUE self)
Definition: win32ole.c:4392
IEventSinkVtbl * lpVtbl
Definition: win32ole.c:196
static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self)
Definition: win32ole.c:2514
static VALUE folevariant_initialize(VALUE self, VALUE args)
Definition: win32ole.c:8743
static IDispatch * val2dispatch(VALUE val)
Definition: win32ole.c:804
#define TYPE(x)
static LPWSTR ole_mb2wc(char *pm, int len)
Definition: win32ole.c:1356
static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask)
Definition: win32ole.c:7396
static void olevariable_free(struct olevariabledata *polevar)
Definition: win32ole.c:1288
struct tagIEVENTSINKOBJ IEVENTSINKOBJ
static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:7069
#define RSTRING_PTR(str)
struct _Win32OLEIDispatch Win32OLEIDispatch
#define T_ARRAY
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:439
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:771
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:773
#define Qnil
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
static VALUE folemethod_helpfile(VALUE self)
Definition: win32ole.c:7000
static VALUE foleparam_inspect(VALUE self)
Definition: win32ole.c:7561
void EVENTSINK_Destructor(PIEVENTSINKOBJ)
Definition: win32ole.c:7940
#define MEMCMP(p1, p2, type, n)
#define T_HASH
#define V_UINTREF(X)
Definition: win32ole.c:97
static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:7038
#define RETURN_ENUMERATOR(obj, argc, argv)
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3220
void rb_backtrace(void)
Definition: vm_backtrace.c:766
static VALUE fole_methods(VALUE self)
Definition: win32ole.c:4304
#define OLEData_Get_Struct(obj, pole)
Definition: win32ole.c:125
static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6778
static DISPID REFIID LCID WORD wFlags
Definition: win32ole.c:306
static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1695
static VALUE is_all_index_under(long *pid, long *pub, long dim)
Definition: win32ole.c:1479
#define SafeStringValue(v)
static VALUE foletype_major_version(VALUE self)
Definition: win32ole.c:5789
VALUE rb_ary_new3(long n,...)
Definition: array.c:432
static ITypeLib * oletypelib_get_typelib(VALUE self)
Definition: win32ole.c:4946
VALUE rb_eSecurityError
Definition: error.c:520
#define T_NIL
char CodePageName[MAX_PATH]
Definition: win32ole.c:1009
const char * alias
Definition: nkf.c:1151
static HINSTANCE ghhctrl
Definition: win32ole.c:230
static VALUE fole_s_reference_count(VALUE self, VALUE obj)
Definition: win32ole.c:2915
double rb_big2dbl(VALUE x)
Definition: bignum.c:1429
VALUE eWIN32OLERuntimeError
Definition: win32ole.c:211
#define rb_str_new2
#define OLE_GET_TYPEATTR(X, Y)
Definition: win32ole.c:113
IConnectionPoint * pConnectionPoint
Definition: win32ole.c:285
static VALUE fole_method_help(VALUE self, VALUE cmdname)
Definition: win32ole.c:4730
static VALUE folemethod_inspect(VALUE self)
Definition: win32ole.c:7231
static VALUE ole_set_member(VALUE self, IDispatch *dispatch)
Definition: win32ole.c:2009
static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
Definition: win32ole.c:6815
IUnknown COSERVERINFO MULTI_QI *typedef LPCSTR UINT DWORD dwData
Definition: win32ole.c:151
ITypeInfo * pTypeInfo
Definition: win32ole.c:273
static VALUE folemethod_return_type(VALUE self)
Definition: win32ole.c:6631
static HTASK threadIDCallee
Definition: win32ole.c:662
static VALUE foletype_s_typelibs(VALUE self)
Definition: win32ole.c:4829
#define T_FLOAT
static void * get_ptr_of_variant(VARIANT *pvar)
Definition: win32ole.c:1410
BYTE LeadByte[12]
Definition: win32ole.c:1006
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2122
static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
Definition: win32ole.c:4899
static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val)
Definition: win32ole.c:2068
static VALUE fole_s_get_code_page(VALUE self)
Definition: win32ole.c:3017
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1116
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2163
static void olemethod_free(struct olemethoddata *polemethod)
Definition: win32ole.c:1280
static void ole_delete_event(VALUE ary, VALUE ev)
Definition: win32ole.c:7724
UINT MaxCharSize
Definition: win32ole.c:1004
static void ole_val2ptr_variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1730
VALUE cWIN32OLE_TYPE
Definition: win32ole.c:205
static VALUE ole_ary_m_entry(VALUE val, long *pid)
Definition: win32ole.c:1397
static VALUE ole_type_visible(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5733
static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
Definition: win32ole.c:5995
unsigned long rb_event_flag_t
Definition: ripper.y:1603
static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo)
Definition: win32ole.c:8137
static VALUE set_argv(VARIANTARG *realargs, unsigned int beg, unsigned int end)
Definition: win32ole.c:3322
static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8862
NORETURN(static void failed_load_conv51932(void))
#define WC2VSTR(x)
Definition: win32ole.c:144
static VALUE ole_ole_type(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5600
static VALUE foleparam_ole_type_detail(VALUE self)
Definition: win32ole.c:7387
static void oleparam_free(struct oleparamdata *pole)
Definition: win32ole.c:1295
static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6978
Win32OLEIDispatch * p
Definition: win32ole.c:786
static VALUE folemethod_invkind(VALUE self)
Definition: win32ole.c:6751
static void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1629
void rb_exc_raise(VALUE mesg)
Definition: eval.c:527
static VALUE foletypelib_guid(VALUE self)
Definition: win32ole.c:5245
IUnknown COSERVERINFO MULTI_QI *typedef LPCSTR UINT uCommand
Definition: win32ole.c:151
static BOOL g_uninitialize_hooked
Definition: win32ole.c:227
int args
Definition: win32ole.c:785
static VALUE foletype_ole_type(VALUE self)
Definition: win32ole.c:5654
static UINT g_cp_to_check
Definition: win32ole.c:238
unsigned long st_data_t
Definition: ripper.y:35
#define g_ole_initialized_init()
Definition: win32ole.c:224
int st_delete(st_table *, st_data_t *, st_data_t *)
int rb_is_const_id(ID id)
Definition: ripper.c:17099
static VALUE folevariable_ole_type_detail(VALUE self)
Definition: win32ole.c:6311
static VALUE foletype_default_ole_types(VALUE self)
Definition: win32ole.c:6098
struct tagIEVENTSINKOBJ * PIEVENTSINKOBJ
STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK pEV, UINT *pct)
Definition: win32ole.c:7621
static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
Definition: win32ole.c:4543
struct IEventSink * PEVENTSINK
static VALUE folevariable_value(VALUE self)
Definition: win32ole.c:6355
static VALUE rb_float_new(double d)
Definition: ripper.y:790
OLECHAR ** pNamedArgs
Definition: win32ole.c:291
static VALUE folemethod_invoke_kind(VALUE self)
Definition: win32ole.c:6770
static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
Definition: win32ole.c:7706
static VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:4604
static VALUE fev_initialize(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8373
static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n)
Definition: win32ole.c:7294
static void ole_val2variant2(VALUE val, VARIANT *var)
Definition: win32ole.c:1982
static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv)
Definition: win32ole.c:2034
ITypeInfo * pTypeInfo
Definition: win32ole.c:278
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR * pExcepInfo
Definition: win32ole.c:306
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1288
static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes)
Definition: win32ole.c:2864
static void unlock_safe_array(SAFEARRAY *psa)
Definition: win32ole.c:8832
VALUE rb_block_proc(void)
Definition: proc.c:479
static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree)
Definition: win32ole.c:1386
#define OLE_FREE(x)
Definition: win32ole.c:116
static VALUE folemethod_event(VALUE self)
Definition: win32ole.c:6889
static VALUE ole_hresult2msg(HRESULT hr)
Definition: win32ole.c:1103
static VALUE foleparam_default(VALUE self)
Definition: win32ole.c:7544
static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
Definition: win32ole.c:6465
static VALUE com_hash
Definition: win32ole.c:233
static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6639
static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
Definition: win32ole.c:6409
static UINT ole_encoding2cp(rb_encoding *enc)
Definition: win32ole.c:863
ITypeInfo * pTypeInfo
Definition: win32ole.c:200
ITypeInfo * pOwnerTypeInfo
Definition: win32ole.c:267
static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name)
Definition: win32ole.c:6527
VALUE rb_Float(VALUE)
Definition: object.c:2654
static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
Definition: win32ole.c:6363
static void ole_initialize(void)
Definition: win32ole.c:1225
VALUE mWIN32OLE_VARIANT
Definition: win32ole.c:212
static BOOL g_lcid_installed
Definition: win32ole.c:229
#define RARRAY_LEN(a)
STDMETHOD() QueryInterface(PEVENTSINK, REFIID, LPVOID *)
#define NUM2DBL(x)
#define StringValuePtr(v)
static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
Definition: win32ole.c:6319
#define val
static VALUE foletype_src_type(VALUE self)
Definition: win32ole.c:5913
static LPWSTR ole_vstr2wc(VALUE vstr)
Definition: win32ole.c:1303
static double rbtime2vtdate(VALUE tmobj)
Definition: win32ole.c:825
static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5950
VALUE rb_eRuntimeError
Definition: error.c:510
#define Qtrue
IUnknown DWORD
Definition: win32ole.c:149
static void ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
Definition: win32ole.c:1219
static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:4591
static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib)
Definition: win32ole.c:4807
static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1798
static VALUE typelib_file(VALUE ole)
Definition: win32ole.c:2504
#define g_ole_initialized
Definition: win32ole.c:223
static VALUE oletypelib_search_registry(VALUE self, VALUE typelib)
Definition: win32ole.c:5108
VALUE rb_ary_new(void)
Definition: array.c:424
#define Check_Type(v, t)
#define StringValueCStr(v)
static VALUE folemethod_helpcontext(VALUE self)
Definition: win32ole.c:7030
unsigned long ID
Definition: ripper.y:105
static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr)
Definition: win32ole.c:4954
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2202
static UINT __RPC_FAR * pctinfo
Definition: win32ole.c:303
static VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo)
Definition: win32ole.c:4359
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1983
static VALUE enc_name(VALUE self)
Definition: encoding.c:1003
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
static char msg[50]
Definition: strerror.c:8
VALUE cWIN32OLE_EVENT
Definition: win32ole.c:209
static IMessageFilter imessage_filter
Definition: win32ole.c:243
VALUE rb_eNoMethodError
Definition: error.c:519
#define RSTRING_LEN(str)
#define FIX2INT(x)
#define INT2FIX(i)
#define Qfalse
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:719
static IMessageFilterVtbl message_filter
Definition: win32ole.c:242
static VALUE reg_get_val(HKEY hkey, const char *subkey)
Definition: win32ole.c:2357
#define T_STRING
VARIANT var
Definition: win32ole.c:296
static VALUE fole_s_allocate(VALUE klass)
Definition: win32ole.c:2023
static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
Definition: win32ole.c:3808
static void oletypelib_free(struct oletypelibdata *poletypelib)
Definition: win32ole.c:1266
static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6707
static VALUE fole_invoke(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:3582
static SAFEARRAY * get_locked_safe_array(VALUE val)
Definition: win32ole.c:8791
static VALUE ole_type_progid(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5697
static BOOL code_page_installed(UINT cp)
Definition: win32ole.c:3032
static VALUE foletypelib_path(VALUE self)
Definition: win32ole.c:5419
int argc
Definition: ruby.c:130
#define NIL_P(v)
static VALUE fole_typelib(VALUE self)
Definition: win32ole.c:4443
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:273
static void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt)
Definition: win32ole.c:1491
static VALUE foletype_name(VALUE self)
Definition: win32ole.c:5594
static VALUE folevariant_set_value(VALUE self, VALUE val)
Definition: win32ole.c:9052
static char * ole_wc2mb(LPWSTR pw)
Definition: win32ole.c:1067
static VALUE foletypelib_name(VALUE self)
Definition: win32ole.c:5273
static VALUE foletypelib_visible(VALUE self)
Definition: win32ole.c:5459
static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
Definition: win32ole.c:6568
static VALUE hash2named_arg(VALUE pair, struct oleparam *pOp)
Definition: win32ole.c:3284
static VALUE folevariable_inspect(VALUE self)
Definition: win32ole.c:6512
static VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
Definition: win32ole.c:4204
static UINT iTInfo
Definition: win32ole.c:304
int err
Definition: win32.c:87
#define I8_2_NUM
Definition: win32ole.c:138
arg
Definition: ripper.y:1316
static VALUE ole_type_guid(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5662
#define ALLOCA_N(type, n)
VALUE rb_eIndexError
Definition: error.c:513
static VALUE fole_activex_initialize(VALUE self)
Definition: win32ole.c:4772
UINT index
Definition: win32ole.c:280
static REFIID LPOLESTR __RPC_FAR UINT LCID DISPID __RPC_FAR * rgDispId
Definition: win32ole.c:305
#define V_INTREF(X)
Definition: win32ole.c:89
static void add_event_call_back(VALUE obj, VALUE event, VALUE data)
Definition: win32ole.c:8397
STDMETHODIMP_(ULONG)
Definition: win32ole.c:7610
static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8942
static VALUE folemethod_name(VALUE self)
Definition: win32ole.c:6599
static void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
Definition: win32ole.c:1193
VALUE rb_eval_string(const char *)
Evaluates the given string in an isolated binding.
Definition: vm_eval.c:1386
static void set_ole_codepage(UINT cp)
Definition: win32ole.c:961
static long dimension(VALUE val)
Definition: win32ole.c:1523
static VALUE folevariable_variable_kind(VALUE self)
Definition: win32ole.c:6457
static rb_encoding * ole_cp2encoding(UINT cp)
Definition: win32ole.c:1013
static VALUE fole_put_methods(VALUE self)
Definition: win32ole.c:4336
static VALUE fole_s_set_code_page(VALUE self, VALUE vcp)
Definition: win32ole.c:3054
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
static VALUE fev_set_handler(VALUE self, VALUE val)
Definition: win32ole.c:8620
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1539
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
static VALUE ole_create_dcom(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:2615
BYTE DefaultChar[2]
Definition: win32ole.c:1005
static long ary_len_of_dim(VALUE ary, long dim)
Definition: win32ole.c:1542
static VALUE folevariant_value(VALUE self)
Definition: win32ole.c:8991
static VALUE fev_s_msg_loop(VALUE klass)
Definition: win32ole.c:8389
static VALUE folevariant_s_allocate(VALUE klass)
Definition: win32ole.c:8647
static VALUE foletypelib_major_version(VALUE self)
Definition: win32ole.c:5325
#define TRUE
Definition: nkf.h:175
static VALUE foletype_helpstring(VALUE self)
Definition: win32ole.c:5878
#define DATA_PTR(dta)
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1270
static VALUE evs_length(void)
Definition: win32ole.c:8575
static st_table * enc2cp_table
Definition: win32ole.c:241
static VALUE foleparam_retval(VALUE self)
Definition: win32ole.c:7484
static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1568
static VALUE foletype_progid(VALUE self)
Definition: win32ole.c:5724
static VALUE reg_get_val2(HKEY hkey, const char *subkey)
Definition: win32ole.c:2385
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:2982
static VALUE ole_type_major_version(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5767
VALUE rb_String(VALUE)
Definition: object.c:2745
ITypeLib * pTypeLib
Definition: win32ole.c:259
#define OLE_RELEASE_TYPEATTR(X, Y)
Definition: win32ole.c:114
static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value)
Definition: win32ole.c:3897
static VALUE fole_get_methods(VALUE self)
Definition: win32ole.c:4320
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
static VALUE typelib_file_from_clsid(VALUE ole)
Definition: win32ole.c:2418
#define NUM2UINT(x)
VALUE rb_block_call(VALUE, ID, int, VALUE *, VALUE(*)(ANYARGS), VALUE)
Definition: vm_eval.c:1130
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n)
Definition: win32ole.c:7301
static VALUE oletypelib_search_registry2(VALUE self, VALUE args)
Definition: win32ole.c:5036
static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
Definition: win32ole.c:3336
static HINSTANCE gole32
Definition: win32ole.c:231
static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:7100
VALUE cWIN32OLE_TYPELIB
Definition: win32ole.c:204
int type
Definition: tcltklib.c:111
int rb_define_dummy_encoding(const char *name)
Definition: encoding.c:400
#define T_FIXNUM
static HTASK DWORD DWORD dwPendingType
Definition: win32ole.c:682
static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:7132
static void failed_load_conv51932(void)
Definition: win32ole.c:929
static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name)
Definition: win32ole.c:4098
static UINT LCID lcid
Definition: win32ole.c:304
static VALUE result
Definition: nkf.c:40
struct IEventSinkVtbl * lpVtbl
Definition: win32ole.c:155
static VALUE vtdate2rbtime(double date)
Definition: win32ole.c:842
static void free_enc2cp(void)
Definition: win32ole.c:9073
static VALUE folemethod_size_params(VALUE self)
Definition: win32ole.c:7124
void ole_uninitialize(void)
Definition: win32ole.c:1211
#define ENC_MACHING_CP(enc, encname, cp)
Definition: win32ole.c:861
static VARTYPE g_nil_to
Definition: win32ole.c:240
static VALUE fev_get_handler(VALUE self)
Definition: win32ole.c:8633
static VALUE foletypelib_s_allocate(VALUE klass)
Definition: win32ole.c:5159
static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib)
Definition: win32ole.c:4937
static HTASK DWORD DWORD dwRejectType
Definition: win32ole.c:666
#define conv_51932(cp)
Definition: win32ole.c:958
static VALUE fole_s_get_locale(VALUE self)
Definition: win32ole.c:3074
static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
Definition: win32ole.c:7493
static VALUE folemethod_return_vtype(VALUE self)
Definition: win32ole.c:6665
WCHAR UnicodeDefaultChar
Definition: win32ole.c:1007
static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
Definition: win32ole.c:6285
static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:3869
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
static VALUE foleparam_name(VALUE self)
Definition: win32ole.c:7322
static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:7009
static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5858
static VALUE ole_variables(ITypeInfo *pTypeInfo)
Definition: win32ole.c:6121
#define OLE_ADDREF(X)
Definition: win32ole.c:111
static VALUE ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
Definition: win32ole.c:6925
static VALUE foletypelib_s_typelibs(VALUE self)
Definition: win32ole.c:4975
static VALUE fev_s_allocate(VALUE klass)
Definition: win32ole.c:8270
static BOOL g_IsEventSinkVtblInitialized
Definition: win32ole.c:7579
static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index)
Definition: win32ole.c:7256
static VALUE foletypelib_initialize(VALUE self, VALUE args)
Definition: win32ole.c:5196
static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:3891
static VALUE foletypelib_library_name(VALUE self)
Definition: win32ole.c:5488
VALUE rb_vsprintf(const char *, va_list)
Definition: sprintf.c:1264
#define T_BIGNUM
static void oletype_free(struct oletypedata *poletype)
Definition: win32ole.c:1273
static VALUE ole_each_sub(VALUE pEnumV)
Definition: win32ole.c:3974
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:637
static VALUE folemethod_offset_vtbl(VALUE self)
Definition: win32ole.c:7092
#define T_TRUE
ID rb_to_id(VALUE)
Definition: string.c:8155
static VALUE folemethod_s_allocate(VALUE klass)
Definition: win32ole.c:6541
#define V_UNION1(X, Y)
Definition: win32ole.c:62
ITypeInfo * pTypeInfo
Definition: win32ole.c:263
DISPPARAMS dp
Definition: win32ole.c:290
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1128
#define V_INT(X)
Definition: win32ole.c:85
static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2)
Definition: win32ole.c:8062
static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
Definition: win32ole.c:5558
#define T_SYMBOL
static VALUE fole_each(VALUE self)
Definition: win32ole.c:4012
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1964
static VALUE ary_ole_event
Definition: win32ole.c:215
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:772
int size
Definition: encoding.c:52
DWORD dwCookie
Definition: win32ole.c:284
static REFIID void __RPC_FAR *__RPC_FAR * ppvObject
Definition: win32ole.c:300
#define pIMultiLanguage
Definition: win32ole.c:251
static VALUE folemethod_params(VALUE self)
Definition: win32ole.c:7216
static VALUE fole_respond_to(VALUE self, VALUE method)
Definition: win32ole.c:4521
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:582
VALUE rb_exc_new3(VALUE etype, VALUE str)
Definition: error.c:548
IUnknown COSERVERINFO MULTI_QI *typedef HWND(WINAPI FNHTMLHELP)(HWND hwndCaller
Definition: win32ole.c:151
#define T_CLASS
static VALUE fole_s_free(VALUE self, VALUE obj)
Definition: win32ole.c:2932
IDispatch * pDispatch
Definition: win32ole.c:255
#define OLE_RELEASE(X)
Definition: win32ole.c:109
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR * pDispParams
Definition: win32ole.c:306
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
static FNCOCREATEINSTANCEEX * gCoCreateInstanceEx
Definition: win32ole.c:232
static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt)
Definition: win32ole.c:8675
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
#define ALLOC_N(type, n)
uint8_t key[16]
Definition: random.c:1370
STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK pEV, UINT info, LCID lcid, ITypeInfo **pInfo)
Definition: win32ole.c:7629
static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
Definition: win32ole.c:7773
static const unsigned char ev[]
Definition: nkf.c:607
static VALUE exec_callback(VALUE arg)
Definition: win32ole.c:7786
#define INT2NUM(x)
static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
Definition: win32ole.c:7951
static VALUE folevariable_name(VALUE self)
Definition: win32ole.c:6237
static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:2665
#define Data_Get_Struct(obj, type, sval)
static VALUE foletypelib_inspect(VALUE self)
Definition: win32ole.c:5535
v
Definition: win32ole.c:798
static VALUE fole_query_interface(VALUE self, VALUE str_iid)
Definition: win32ole.c:4476
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1583
static ULONG reference_count(struct oledata *pole)
Definition: win32ole.c:2896
static void ole_event_free(struct oleeventdata *poleev)
Definition: win32ole.c:8259
static VALUE foletype_ole_typelib(VALUE self)
Definition: win32ole.c:5987
static VALUE hash2result(VALUE hash)
Definition: win32ole.c:7763
static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6947
static VALUE rescue_callback(VALUE arg)
Definition: win32ole.c:7796
static VALUE folemethod_helpstring(VALUE self)
Definition: win32ole.c:6970
int st_insert(st_table *, st_data_t, st_data_t)
VALUE rb_apply(VALUE, ID, VALUE)
Calls a method.
Definition: vm_eval.c:744
static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
Definition: win32ole.c:6605
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3382
VALUE cWIN32OLE_METHOD
Definition: win32ole.c:207
static VALUE ole_type_src_type(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5886
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
#define WIN32OLE_VERSION
Definition: win32ole.c:146
#define RSTRING_LENINT(str)
static VALUE ole_ienum_free(VALUE pEnumV)
Definition: win32ole.c:3990
#define rb_safe_level()
Definition: tcltklib.c:94
void rb_write_error(const char *)
Definition: io.c:7065
#define T_MODULE
static VALUE foletypelib_version(VALUE self)
Definition: win32ole.c:5300
static void ole_freeexceptinfo(EXCEPINFO *pExInfo)
Definition: win32ole.c:1143
const char * name
Definition: nkf.c:208
#define NUM2INT(x)
static ID id_events
Definition: win32ole.c:216
VALUE rb_hash_new(void)
Definition: hash.c:234
const char * rb_id2name(ID id)
Definition: ripper.c:17058
#define rb_errinfo()
Definition: tcltklib.c:89
VALUE rb_str_intern(VALUE)
Definition: string.c:7212
static BOOL g_cp_installed
Definition: win32ole.c:228
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR UINT __RPC_FAR * puArgErr
Definition: win32ole.c:306
static VALUE folevariable_visible(VALUE self)
Definition: win32ole.c:6401
IUnknown COSERVERINFO MULTI_QI *typedef LPCSTR pszFile
Definition: win32ole.c:151
static VALUE make_version_str(VALUE major, VALUE minor)
Definition: win32ole.c:5019
#define V_I1REF(X)
Definition: win32ole.c:77
static UINT LCID ITypeInfo __RPC_FAR *__RPC_FAR * ppTInfo
Definition: win32ole.c:304
VALUE cWIN32OLE_VARIANT
Definition: win32ole.c:210
static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5797
static VALUE fole_initialize(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:3228
static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib)
Definition: win32ole.c:5394
void rb_mark_hash(struct st_table *)
Definition: gc.c:2413
VALUE cWIN32OLE_VARIABLE
Definition: win32ole.c:206
static VALUE foletype_typekind(VALUE self)
Definition: win32ole.c:5850
#define V_UINT(X)
Definition: win32ole.c:93
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:570
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:804
#define NUM2CHR(x)
VALUE rb_fix2str(VALUE, int)
Definition: numeric.c:2552
int rb_enc_find_index(const char *name)
Definition: encoding.c:635
static void ole_free(struct oledata *pole)
Definition: win32ole.c:1259
static VALUE folevariant_vartype(VALUE self)
Definition: win32ole.c:9030
static VALUE fole_s_create_guid(VALUE self)
Definition: win32ole.c:3135
static VALUE foletype_variables(VALUE self)
Definition: win32ole.c:6183
static void version(void)
Definition: nkf.c:898
static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
Definition: win32ole.c:7328
int major
Definition: tcltklib.c:109
#define Data_Wrap_Struct(klass, mark, free, sval)
static UINT ole_init_cp(void)
Definition: win32ole.c:990
#define snprintf
static VALUE foleparam_optional(VALUE self)
Definition: win32ole.c:7465
static long * ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
Definition: win32ole.c:8812
static VALUE folemethod_visible(VALUE self)
Definition: win32ole.c:6807
return S_OK
Definition: win32ole.c:769
static DISPID dispIdMember
Definition: win32ole.c:306
static IMessageFilter * previous_filter
Definition: win32ole.c:244
#define rb_intern(str)
static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:8897
static VALUE oletypelib_path(VALUE guid, VALUE version)
Definition: win32ole.c:5361
RUBY_EXTERN VALUE rb_cData
Definition: ripper.y:1433
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
Definition: vm_trace.c:135
static void ole_msg_loop(void)
Definition: win32ole.c:1250
#define NULL
Definition: _sdbm.c:103
static VALUE foleparam_s_allocate(VALUE klass)
Definition: win32ole.c:7242
static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:2978
static VALUE ole_type_typekind(ITypeInfo *pTypeInfo)
Definition: win32ole.c:5827
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
static ULONG(STDMETHODCALLTYPE AddRef)(IDispatch __RPC_FAR *This)
Definition: win32ole.c:614
static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
Definition: win32ole.c:4135
static BOOL CALLBACK installed_code_page_proc(LPTSTR str)
Definition: win32ole.c:3023
static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo)
Definition: win32ole.c:1151
free(psz)
static VALUE default_inspect(VALUE self, const char *class_name)
Definition: win32ole.c:2002
static VALUE fev_off_event(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:8502
static REFIID riid
Definition: win32ole.c:300
static VALUE folevariable_ole_type(VALUE self)
Definition: win32ole.c:6277
VALUE rb_eArgError
Definition: error.c:512
int rb_during_gc(void)
Definition: gc.c:3119
static VALUE foleparam_ole_type(VALUE self)
Definition: win32ole.c:7353
static VALUE foletype_source_ole_types(VALUE self)
Definition: win32ole.c:6063
void st_free_table(st_table *)
Definition: st.c:334
#define V_UI2REF(X)
Definition: win32ole.c:81
#define T_FALSE
static VALUE fole_s_ole_initialize(VALUE self)
Definition: win32ole.c:3160
static VALUE fole_missing(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:4075
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR * pVarResult
Definition: win32ole.c:306
char ** argv
Definition: ruby.c:131
static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
Definition: win32ole.c:2336
VALUE * parg
Definition: win32ole.c:787
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:548
#define NUM2UI8
Definition: win32ole.c:141
static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:2798
void Init_win32ole(void)
Definition: win32ole.c:9079
static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
Definition: win32ole.c:2330
static VALUE foletype_methods(VALUE self)
Definition: win32ole.c:6203
static VALUE evs_push(VALUE ev)
Definition: win32ole.c:8556
static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self)
Definition: win32ole.c:2716