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