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