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