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