* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / ext / win32ole / win32ole.c
blobbded54f7b6ebf6a38778c2e45318ad8f727141c4
1 /*
2 * (c) 1995 Microsoft Corporation. All rights reserved.
3 * Developed by ActiveWare Internet Corp., http://www.ActiveWare.com
5 * Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy
6 * <gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net>
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.
15 modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@nifty.ne.jp>
18 #include "ruby/ruby.h"
19 #include "ruby/st.h"
20 #include "ruby/encoding.h"
21 #include <ctype.h>
22 #include <windows.h>
23 #include <ocidl.h>
24 #include <olectl.h>
25 #include <ole2.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #ifdef HAVE_STDARG_PROTOTYPES
29 #include <stdarg.h>
30 #define va_init_list(a,b) va_start(a,b)
31 #else
32 #include <varargs.h>
33 #define va_init_list(a,b) va_start(a)
34 #endif
35 #include <objidl.h>
37 #define DOUT fprintf(stderr,"[%d]\n",__LINE__)
38 #define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x)
39 #define DOUTMSG(x) fprintf(stderr, "[%d]:" #x "\n",__LINE__)
40 #define DOUTI(x) fprintf(stderr, "[%ld]:" #x "=%d\n",__LINE__,x)
41 #define DOUTD(x) fprintf(stderr, "[%d]:" #x "=%f\n",__LINE__,x)
43 #if defined NONAMELESSUNION && __GNUC__
44 #define V_UNION1(X, Y) ((X)->u.Y)
45 #else
46 #define V_UNION1(X, Y) ((X)->Y)
47 #endif
49 #if defined NONAMELESSUNION && __GNUC__
50 #undef V_UNION
51 #define V_UNION(X,Y) ((X)->n1.n2.n3.Y)
53 #undef V_VT
54 #define V_VT(X) ((X)->n1.n2.vt)
56 #undef V_BOOL
57 #define V_BOOL(X) V_UNION(X,boolVal)
58 #endif
60 #ifndef V_I1REF
61 #define V_I1REF(X) V_UNION(X, pcVal)
62 #endif
64 #ifndef U_UI2REF
65 #define V_UI2REF(X) V_UNION(X, puiVal)
66 #endif
68 #ifndef V_INT
69 #define V_INT(X) V_UNION(X, intVal)
70 #endif
72 #ifndef V_INTREF
73 #define V_INTREF(X) V_UNION(X, pintVal)
74 #endif
76 #ifndef V_UINT
77 #define V_UINT(X) V_UNION(X, uintVal)
78 #endif
80 #ifndef V_UINTREF
81 #define V_UINTREF(X) V_UNION(X, puintVal)
82 #endif
84 #define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
86 #define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
88 #define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y)))
89 #define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y)))
91 #define OLE_FREE(x) {\
92 if(g_ole_initialized == TRUE) {\
93 if(x) {\
94 OLE_RELEASE(x);\
95 (x) = 0;\
100 #define OLEData_Get_Struct(obj, pole) {\
101 Data_Get_Struct(obj, struct oledata, pole);\
102 if(!pole->pDispatch) {\
103 rb_raise(rb_eRuntimeError, "failed to get Dispatch Interface");\
107 #ifdef HAVE_LONG_LONG
108 #define I8_2_NUM LL2NUM
109 #define UI8_2_NUM ULL2NUM
110 #define NUM2I8 NUM2LL
111 #define NUM2UI8 NUM2ULL
112 #else
113 #define I8_2_NUM INT2NUM
114 #define UI8_2_NUM UINT2NUM
115 #define NUM2I8 NUM2INT
116 #define NUM2UI8 NUM2UINT
117 #endif
119 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
121 #define WIN32OLE_VERSION "1.3.1"
123 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
124 (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
126 typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile,
127 UINT uCommand, DWORD dwData);
128 typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD);
129 typedef struct {
130 struct IEventSinkVtbl * lpVtbl;
131 } IEventSink, *PEVENTSINK;
133 typedef struct IEventSinkVtbl IEventSinkVtbl;
135 struct IEventSinkVtbl {
136 STDMETHOD(QueryInterface)(
137 PEVENTSINK,
138 REFIID,
139 LPVOID *);
140 STDMETHOD_(ULONG, AddRef)(PEVENTSINK);
141 STDMETHOD_(ULONG, Release)(PEVENTSINK);
143 STDMETHOD(GetTypeInfoCount)(
144 PEVENTSINK,
145 UINT *);
146 STDMETHOD(GetTypeInfo)(
147 PEVENTSINK,
148 UINT,
149 LCID,
150 ITypeInfo **);
151 STDMETHOD(GetIDsOfNames)(
152 PEVENTSINK,
153 REFIID,
154 OLECHAR **,
155 UINT,
156 LCID,
157 DISPID *);
158 STDMETHOD(Invoke)(
159 PEVENTSINK,
160 DISPID,
161 REFIID,
162 LCID,
163 WORD,
164 DISPPARAMS *,
165 VARIANT *,
166 EXCEPINFO *,
167 UINT *);
170 typedef struct tagIEVENTSINKOBJ {
171 IEventSinkVtbl *lpVtbl;
172 DWORD m_cRef;
173 IID m_iid;
174 int m_event_id;
175 ITypeInfo *pTypeInfo;
176 }IEVENTSINKOBJ, *PIEVENTSINKOBJ;
178 VALUE cWIN32OLE;
179 VALUE cWIN32OLE_TYPELIB;
180 VALUE cWIN32OLE_TYPE;
181 VALUE cWIN32OLE_VARIABLE;
182 VALUE cWIN32OLE_METHOD;
183 VALUE cWIN32OLE_PARAM;
184 VALUE cWIN32OLE_EVENT;
185 VALUE cWIN32OLE_VARIANT;
186 VALUE eWIN32OLERuntimeError;
187 VALUE mWIN32OLE_VARIANT;
188 VALUE cWIN32OLE_PROPERTY;
190 static VALUE ary_ole_event;
191 static ID id_events;
192 static BOOL g_ole_initialized = FALSE;
193 static BOOL g_cp_installed = FALSE;
194 static BOOL g_lcid_installed = FALSE;
195 static HINSTANCE ghhctrl = NULL;
196 static HINSTANCE gole32 = NULL;
197 static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL;
198 static VALUE com_hash;
199 static IDispatchVtbl com_vtbl;
200 static UINT cWIN32OLE_cp = CP_ACP;
201 static LCID cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT;
202 static rb_encoding *cWIN32OLE_enc;
203 static UINT g_cp_to_check = CP_ACP;
204 static char g_lcid_to_check[8 + 1];
205 static VARTYPE g_nil_to = VT_ERROR;
206 static st_table *enc2cp_table;
207 static IMessageFilterVtbl message_filter;
208 static IMessageFilter imessage_filter = { &message_filter };
209 static IMessageFilter* previous_filter;
211 struct oledata {
212 IDispatch *pDispatch;
215 struct oletypedata {
216 ITypeInfo *pTypeInfo;
219 struct olemethoddata {
220 ITypeInfo *pOwnerTypeInfo;
221 ITypeInfo *pTypeInfo;
222 UINT index;
225 struct olevariabledata {
226 ITypeInfo *pTypeInfo;
227 UINT index;
230 struct oleparamdata {
231 ITypeInfo *pTypeInfo;
232 UINT method_index;
233 UINT index;
236 struct oleeventdata {
237 DWORD dwCookie;
238 IConnectionPoint *pConnectionPoint;
239 long event_id;
242 struct oleparam {
243 DISPPARAMS dp;
244 OLECHAR** pNamedArgs;
247 struct olevariantdata {
248 VARIANT realvar;
249 VARIANT var;
253 static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
254 static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This);
255 static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This);
256 static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo);
257 static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
258 static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId);
259 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);
260 static IDispatch* val2dispatch(VALUE val);
261 static void time2d(int hh, int mm, int ss, double *pv);
262 static void d2time(double v, int *hh, int *mm, int *ss);
263 static void civil2jd(int y, int m, int d, long *jd);
264 static void jd2civil(long day, int *yy, int *mm, int *dd);
265 static void double2time(double v, int *y, int *m, int *d, int *hh, int *mm, int *ss);
266 static double time_object2date(VALUE tmobj);
267 static VALUE date2time_str(double date);
268 static rb_encoding *ole_cp2encoding(UINT cp);
269 static UINT ole_encoding2cp(rb_encoding *enc);
270 static UINT ole_init_cp();
271 static char *ole_wc2mb(LPWSTR pw);
272 static VALUE ole_hresult2msg(HRESULT hr);
273 static void ole_freeexceptinfo(EXCEPINFO *pExInfo);
274 static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo);
275 static void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...);
276 static void ole_initialize();
277 static void ole_msg_loop();
278 static void ole_free(struct oledata *pole);
279 static void oletype_free(struct oletypedata *poletype);
280 static void olemethod_free(struct olemethoddata *polemethod);
281 static void olevariable_free(struct olevariabledata *polevar);
282 static void oleparam_free(struct oleparamdata *pole);
283 static LPWSTR ole_vstr2wc(VALUE vstr);
284 static LPWSTR ole_mb2wc(char *pm, int len);
285 static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree);
286 static VALUE ole_ary_m_entry(VALUE val, long *pid);
287 static void * get_ptr_of_variant(VARIANT *pvar);
288 static VALUE is_all_index_under(long *pid, long *pub, long dim);
289 static void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt);
290 static long dimension(VALUE val);
291 static long ary_len_of_dim(VALUE ary, long dim);
292 static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
293 static void ole_val2variant(VALUE val, VARIANT *var);
294 static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
295 static void ole_val2ptr_variant(VALUE val, VARIANT *var);
296 static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
297 static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
298 static void ole_val2variant2(VALUE val, VARIANT *var);
299 static VALUE make_inspect(const char *class_name, VALUE detail);
300 static VALUE default_inspect(VALUE self, const char *class_name);
301 static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
302 static VALUE fole_s_allocate(VALUE klass);
303 static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
304 static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim);
305 static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val);
306 static VALUE ole_variant2val(VARIANT *pvar);
307 static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey);
308 static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey);
309 static VALUE reg_enum_key(HKEY hkey, DWORD i);
310 static VALUE reg_get_val(HKEY hkey, const char *subkey);
311 static VALUE reg_get_typelib_file_path(HKEY hkey);
312 static VALUE typelib_file_from_clsid(VALUE ole);
313 static VALUE typelib_file_from_typelib(VALUE ole);
314 static VALUE typelib_file(VALUE ole);
315 static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self);
316 static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid);
317 static VALUE ole_create_dcom(int argc, VALUE *argv, VALUE self);
318 static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self);
319 static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self);
320 static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self);
321 static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes);
322 static ULONG reference_count(struct oledata * pole);
323 static VALUE fole_s_reference_count(VALUE self, VALUE obj);
324 static VALUE fole_s_free(VALUE self, VALUE obj);
325 static HWND ole_show_help(VALUE helpfile, VALUE helpcontext);
326 static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self);
327 static VALUE fole_s_get_code_page(VALUE self);
328 static BOOL CALLBACK installed_code_page_proc(LPTSTR str);
329 static BOOL code_page_installed(UINT cp);
330 static VALUE fole_s_set_code_page(VALUE self, VALUE vcp);
331 static VALUE fole_s_get_locale(VALUE self);
332 static BOOL CALLBACK installed_lcid_proc(LPTSTR str);
333 static BOOL lcid_installed(LCID lcid);
334 static VALUE fole_s_set_locale(VALUE self, VALUE vlcid);
335 static VALUE fole_s_create_guid(VALUE self);
336 static VALUE fole_initialize(int argc, VALUE *argv, VALUE self);
337 static VALUE hash2named_arg(VALUE pair, struct oleparam* pOp);
338 static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end);
339 static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket);
340 static VALUE fole_invoke(int argc, VALUE *argv, VALUE self);
341 static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind);
342 static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types);
343 static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
344 static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
345 static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self);
346 static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self);
347 static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self);
348 static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value);
349 static VALUE fole_free(VALUE self);
350 static VALUE ole_each_sub(VALUE pEnumV);
351 static VALUE ole_ienum_free(VALUE pEnumV);
352 static VALUE fole_each(VALUE self);
353 static VALUE fole_missing(int argc, VALUE *argv, VALUE self);
354 static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name);
355 static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
356 static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask);
357 static VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask);
358 static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti);
359 static VALUE ole_methods(VALUE self, int mask);
360 static VALUE fole_methods(VALUE self);
361 static VALUE fole_get_methods(VALUE self);
362 static VALUE fole_put_methods(VALUE self);
363 static VALUE fole_func_methods(VALUE self);
364 static VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo);
365 static VALUE fole_type(VALUE self);
366 static VALUE make_oletypelib_obj(VALUE guid, VALUE major_version, VALUE minor_version);
367 static VALUE ole_typelib_from_itypelib(ITypeLib *pTypeLib);
368 static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo);
369 static VALUE fole_typelib(VALUE self);
370 static VALUE fole_query_interface(VALUE self, VALUE str_iid);
371 static VALUE fole_respond_to(VALUE self, VALUE method);
372 static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
373 static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
374 static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
375 static VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
376 static VALUE fole_method_help(VALUE self, VALUE cmdname);
377 static VALUE fole_activex_initialize(VALUE self);
378 static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib);
379 static VALUE foletype_s_typelibs(VALUE self);
380 static VALUE foletype_s_progids(VALUE self);
381 static VALUE foletype_s_allocate(VALUE klass);
382 static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
383 static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass);
384 static VALUE oletypelib_set_member(VALUE self, VALUE typelib, VALUE guid, VALUE version);
385 static VALUE foletypelib_s_typelibs(VALUE self);
386 static VALUE make_version_str(VALUE major, VALUE minor);
387 static VALUE oletypelib_search_registry2(VALUE self, VALUE args);
388 static VALUE oletypelib_search_registry(VALUE self, VALUE typelib);
389 static VALUE foletypelib_initialize(VALUE self, VALUE args);
390 static VALUE foletypelib_guid(VALUE self);
391 static VALUE foletypelib_name(VALUE self);
392 static VALUE foletypelib_version(VALUE self);
393 static VALUE foletypelib_major_version(VALUE self);
394 static VALUE foletypelib_minor_version(VALUE self);
395 static VALUE oletypelib_path(VALUE guid, VALUE version);
396 static VALUE foletypelib_path(VALUE self);
397 static void oletypelib2itypelib(VALUE self, ITypeLib **ppTypeLib);
398 static VALUE foletypelib_visible(VALUE self);
399 static VALUE foletypelib_library_name(VALUE self);
400 static VALUE foletypelib_ole_types(VALUE self);
401 static VALUE foletypelib_inspect(VALUE self);
402 static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass);
403 static VALUE foletype_name(VALUE self);
404 static VALUE ole_ole_type(ITypeInfo *pTypeInfo);
405 static VALUE foletype_ole_type(VALUE self);
406 static VALUE ole_type_guid(ITypeInfo *pTypeInfo);
407 static VALUE foletype_guid(VALUE self);
408 static VALUE ole_type_progid(ITypeInfo *pTypeInfo);
409 static VALUE foletype_progid(VALUE self);
410 static VALUE ole_type_visible(ITypeInfo *pTypeInfo);
411 static VALUE foletype_visible(VALUE self);
412 static VALUE ole_type_major_version(ITypeInfo *pTypeInfo);
413 static VALUE foletype_major_version(VALUE self);
414 static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo);
415 static VALUE foletype_minor_version(VALUE self);
416 static VALUE ole_type_typekind(ITypeInfo *pTypeInfo);
417 static VALUE foletype_typekind(VALUE self);
418 static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo);
419 static VALUE foletype_helpstring(VALUE self);
420 static VALUE ole_type_src_type(ITypeInfo *pTypeInfo);
421 static VALUE foletype_src_type(VALUE self);
422 static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo);
423 static VALUE foletype_helpfile(VALUE self);
424 static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo);
425 static VALUE foletype_helpcontext(VALUE self);
426 static VALUE foletype_ole_typelib(VALUE self);
427 static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags);
428 static VALUE foletype_impl_ole_types(VALUE self);
429 static VALUE foletype_source_ole_types(VALUE self);
430 static VALUE foletype_default_event_sources(VALUE self);
431 static VALUE foletype_default_ole_types(VALUE self);
432 static VALUE foletype_inspect(VALUE self);
433 static VALUE ole_variables(ITypeInfo *pTypeInfo);
434 static VALUE foletype_variables(VALUE self);
435 static VALUE foletype_methods(VALUE self);
436 static VALUE folevariable_name(VALUE self);
437 static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index);
438 static VALUE folevariable_ole_type(VALUE self);
439 static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index);
440 static VALUE folevariable_ole_type_detail(VALUE self);
441 static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index);
442 static VALUE folevariable_value(VALUE self);
443 static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index);
444 static VALUE folevariable_visible(VALUE self);
445 static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index);
446 static VALUE folevariable_variable_kind(VALUE self);
447 static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index);
448 static VALUE folevariable_varkind(VALUE self);
449 static VALUE folevariable_inspect(VALUE self);
450 static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name);
451 static VALUE folemethod_s_allocate(VALUE klass);
452 static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method);
453 static VALUE folemethod_name(VALUE self);
454 static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index);
455 static VALUE folemethod_return_type(VALUE self);
456 static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index);
457 static VALUE folemethod_return_vtype(VALUE self);
458 static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index);
459 static VALUE folemethod_return_type_detail(VALUE self);
460 static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index);
461 static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index);
462 static VALUE folemethod_invkind(VALUE self);
463 static VALUE folemethod_invoke_kind(VALUE self);
464 static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index);
465 static VALUE folemethod_visible(VALUE self);
466 static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name);
467 static VALUE folemethod_event(VALUE self);
468 static VALUE folemethod_event_interface(VALUE self);
469 static VALUE ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
470 static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index);
471 static VALUE folemethod_helpstring(VALUE self);
472 static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index);
473 static VALUE folemethod_helpfile(VALUE self);
474 static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index);
475 static VALUE folemethod_helpcontext(VALUE self);
476 static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index);
477 static VALUE folemethod_dispid(VALUE self);
478 static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index);
479 static VALUE folemethod_offset_vtbl(VALUE self);
480 static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index);
481 static VALUE folemethod_size_params(VALUE self);
482 static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index);
483 static VALUE folemethod_size_opt_params(VALUE self);
484 static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index);
485 static VALUE folemethod_params(VALUE self);
486 static VALUE folemethod_inspect(VALUE self);
487 static VALUE foleparam_name(VALUE self);
488 static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
489 static VALUE foleparam_ole_type(VALUE self);
490 static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
491 static VALUE foleparam_ole_type_detail(VALUE self);
492 static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask);
493 static VALUE foleparam_input(VALUE self);
494 static VALUE foleparam_output(VALUE self);
495 static VALUE foleparam_optional(VALUE self);
496 static VALUE foleparam_retval(VALUE self);
497 static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
498 static VALUE foleparam_default(VALUE self);
499 static VALUE foleparam_inspect(VALUE self);
500 static long ole_search_event_at(VALUE ary, VALUE ev);
501 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
502 static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
503 static void ole_delete_event(VALUE ary, VALUE ev);
504 static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
505 static VALUE hash2result(VALUE hash);
506 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
507 static VALUE exec_callback(VALUE arg);
508 static VALUE rescue_callback(VALUE arg);
509 static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
510 static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
511 static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
512 static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
513 static void ole_event_free(struct oleeventdata *poleev);
514 static VALUE fev_s_allocate(VALUE klass);
515 static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
516 static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
517 static VALUE fev_s_msg_loop(VALUE klass);
518 static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
519 static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
520 static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
521 static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
522 static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
523 static VALUE fev_unadvise(VALUE self);
524 static VALUE fev_set_handler(VALUE self, VALUE val);
525 static VALUE fev_get_handler(VALUE self);
526 static VALUE evs_push(VALUE ev);
527 static VALUE evs_delete(long i);
528 static VALUE evs_entry(long i);
529 static VALUE evs_length();
530 static void olevariant_free(struct olevariantdata *pvar);
531 static VALUE folevariant_s_allocate(VALUE klass);
532 static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
533 static VALUE folevariant_initialize(VALUE self, VALUE args);
534 static long *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
535 static void unlock_safe_array(SAFEARRAY *psa);
536 static SAFEARRAY *get_locked_safe_array(VALUE val);
537 static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
538 static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
539 static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
540 static VALUE folevariant_value(VALUE self);
541 static VALUE folevariant_vartype(VALUE self);
542 static VALUE folevariant_set_value(VALUE self, VALUE val);
543 static void init_enc2cp();
544 static void free_enc2cp();
546 static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
547 IMessageFilter __RPC_FAR * This,
548 /* [in] */ REFIID riid,
549 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
551 if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
552 || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0)
554 *ppvObject = &message_filter;
555 return S_OK;
557 return E_NOINTERFACE;
560 static ULONG (STDMETHODCALLTYPE mf_AddRef)(
561 IMessageFilter __RPC_FAR * This)
563 return 1;
566 static ULONG (STDMETHODCALLTYPE mf_Release)(
567 IMessageFilter __RPC_FAR * This)
569 return 1;
572 static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)(
573 IMessageFilter __RPC_FAR * pThis,
574 DWORD dwCallType, //Type of incoming call
575 HTASK threadIDCaller, //Task handle calling this task
576 DWORD dwTickCount, //Elapsed tick count
577 LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure
580 #ifdef DEBUG_MESSAGEFILTER
581 printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount);
582 fflush(stdout);
583 #endif
584 switch (dwCallType)
586 case CALLTYPE_ASYNC:
587 case CALLTYPE_TOPLEVEL_CALLPENDING:
588 case CALLTYPE_ASYNC_CALLPENDING:
589 if (rb_during_gc()) {
590 return SERVERCALL_RETRYLATER;
592 break;
593 default:
594 break;
596 if (previous_filter) {
597 return previous_filter->lpVtbl->HandleInComingCall(previous_filter,
598 dwCallType,
599 threadIDCaller,
600 dwTickCount,
601 lpInterfaceInfo);
603 return SERVERCALL_ISHANDLED;
606 static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)(
607 IMessageFilter* pThis,
608 HTASK threadIDCallee, //Server task handle
609 DWORD dwTickCount, //Elapsed tick count
610 DWORD dwRejectType //Returned rejection message
613 if (previous_filter) {
614 return previous_filter->lpVtbl->RetryRejectedCall(previous_filter,
615 threadIDCallee,
616 dwTickCount,
617 dwRejectType);
619 return 1000;
622 static DWORD (STDMETHODCALLTYPE mf_MessagePending)(
623 IMessageFilter* pThis,
624 HTASK threadIDCallee, //Called applications task handle
625 DWORD dwTickCount, //Elapsed tick count
626 DWORD dwPendingType //Call type
629 if (rb_during_gc()) {
630 return PENDINGMSG_WAITNOPROCESS;
632 if (previous_filter) {
633 return previous_filter->lpVtbl->MessagePending(previous_filter,
634 threadIDCallee,
635 dwTickCount,
636 dwPendingType);
638 return PENDINGMSG_WAITNOPROCESS;
641 typedef struct _Win32OLEIDispatch
643 IDispatch dispatch;
644 ULONG refcount;
645 VALUE obj;
646 } Win32OLEIDispatch;
648 static HRESULT ( STDMETHODCALLTYPE QueryInterface )(
649 IDispatch __RPC_FAR * This,
650 /* [in] */ REFIID riid,
651 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
653 if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
654 || MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0)
656 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
657 p->refcount++;
658 *ppvObject = This;
659 return S_OK;
661 return E_NOINTERFACE;
664 static ULONG ( STDMETHODCALLTYPE AddRef )(
665 IDispatch __RPC_FAR * This)
667 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
668 return ++(p->refcount);
671 static ULONG ( STDMETHODCALLTYPE Release )(
672 IDispatch __RPC_FAR * This)
674 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
675 ULONG u = --(p->refcount);
676 if (u == 0) {
677 st_data_t key = p->obj;
678 st_delete(DATA_PTR(com_hash), &key, 0);
679 free(p);
681 return u;
684 static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(
685 IDispatch __RPC_FAR * This,
686 /* [out] */ UINT __RPC_FAR *pctinfo)
688 return E_NOTIMPL;
691 static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(
692 IDispatch __RPC_FAR * This,
693 /* [in] */ UINT iTInfo,
694 /* [in] */ LCID lcid,
695 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
697 return E_NOTIMPL;
701 static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(
702 IDispatch __RPC_FAR * This,
703 /* [in] */ REFIID riid,
704 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
705 /* [in] */ UINT cNames,
706 /* [in] */ LCID lcid,
707 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
710 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
712 char* psz = ole_wc2mb(*rgszNames); // support only one method
713 *rgDispId = rb_intern(psz);
714 free(psz);
715 return S_OK;
718 static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )(
719 IDispatch __RPC_FAR * This,
720 /* [in] */ DISPID dispIdMember,
721 /* [in] */ REFIID riid,
722 /* [in] */ LCID lcid,
723 /* [in] */ WORD wFlags,
724 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
725 /* [out] */ VARIANT __RPC_FAR *pVarResult,
726 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
727 /* [out] */ UINT __RPC_FAR *puArgErr)
729 VALUE v;
730 int i;
731 int args = pDispParams->cArgs;
732 Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
733 VALUE* parg = ALLOCA_N(VALUE, args);
734 for (i = 0; i < args; i++) {
735 *(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]);
737 if (dispIdMember == DISPID_VALUE) {
738 if (wFlags == DISPATCH_METHOD) {
739 dispIdMember = rb_intern("call");
740 } else if (wFlags & DISPATCH_PROPERTYGET) {
741 dispIdMember = rb_intern("value");
744 v = rb_funcall2(p->obj, dispIdMember, args, parg);
745 ole_val2variant(v, pVarResult);
746 return S_OK;
749 static IDispatch*
750 val2dispatch(VALUE val)
752 struct st_table *tbl = DATA_PTR(com_hash);
753 Win32OLEIDispatch* pdisp;
754 st_data_t data;
756 if (st_lookup(tbl, val, &data)) {
757 pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG);
758 pdisp->refcount++;
760 else {
761 pdisp = ALLOC(Win32OLEIDispatch);
762 pdisp->dispatch.lpVtbl = &com_vtbl;
763 pdisp->refcount = 1;
764 pdisp->obj = val;
765 st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG);
767 return &pdisp->dispatch;
770 static void
771 time2d(int hh, int mm, int ss, double *pv)
773 *pv = (hh * 60.0 * 60.0 + mm * 60.0 + ss) / 86400.0;
776 static void
777 d2time(double v, int *hh, int *mm, int *ss)
779 double d_hh, d_mm, d_ss;
780 int i_hh, i_mm, i_ss;
782 double d = fabs(v * 86400.0);
784 d_hh = d / 3600.0;
785 i_hh = (int)d_hh;
787 d = d - i_hh * 3600.0;
789 d_mm = d / 60.0;
790 i_mm = (int)d_mm;
792 d = d - i_mm * 60.0;
794 d_ss = d * 10.0 + 5;
796 i_ss = (int)d_ss / 10;
798 if(i_ss == 60) {
799 i_mm += 1;
800 i_ss = 0;
803 if (i_mm == 60) {
804 i_hh += 1;
805 i_mm = 0;
807 if (i_hh == 24) {
808 i_hh = 0;
811 *hh = i_hh;
812 *mm = i_mm;
813 *ss = i_ss;
816 static void
817 civil2jd(int y, int m, int d, long *jd)
819 long a, b;
820 if (m <= 2) {
821 y -= 1;
822 m += 12;
824 a = (long)(y / 100.0);
825 b = 2 - a + (long)(a / 4.0);
826 *jd = (long)(365.25 * (double)(y + 4716))
827 + (long)(30.6001 * (m + 1))
828 + d + b - 1524;
831 static void
832 jd2civil(long day, int *yy, int *mm, int *dd)
834 long x, a, b, c, d, e;
835 x = (long)(((double)day - 1867216.25) / 36524.25);
836 a = day + 1 + x - (long)(x / 4.0);
837 b = a + 1524;
838 c = (long)(((double)b -122.1) /365.25);
839 d = (long)(365.25 * c);
840 e = (long)((double)(b - d) / 30.6001);
841 *dd = b - d - (long)(30.6001 * e);
842 if (e <= 13) {
843 *mm = e - 1;
844 *yy = c - 4716;
846 else {
847 *mm = e - 13;
848 *yy = c - 4715;
852 static void
853 double2time(double v, int *y, int *m, int *d, int *hh, int *mm, int *ss)
855 long day;
856 double t;
858 day = (long)v;
859 t = v - day;
860 jd2civil(2415019 + day, y, m, d);
862 d2time(t, hh, mm, ss);
865 static double
866 time_object2date(VALUE tmobj)
868 long y, m, d, hh, mm, ss;
869 long day;
870 double t;
871 y = FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0));
872 m = FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0));
873 d = FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0));
874 hh = FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0));
875 mm = FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0));
876 ss = FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0));
877 civil2jd(y, m, d, &day);
878 time2d(hh, mm, ss, &t);
879 return t + day - 2415019;
882 static VALUE
883 date2time_str(double date)
885 int y, m, d, hh, mm, ss;
886 double2time(date, &y, &m, &d, &hh, &mm, &ss);
887 return rb_sprintf(
888 "%04d/%02d/%02d %02d:%02d:%02d",
889 y, m, d, hh, mm, ss);
892 #define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp
894 static UINT ole_encoding2cp(rb_encoding *enc)
897 * Is there any better solution to convert
898 * Ruby encoding to Windows codepage???
900 ENC_MACHING_CP(enc, "Big5", 950);
901 ENC_MACHING_CP(enc, "CP51932", 51932);
902 ENC_MACHING_CP(enc, "CP850", 850);
903 ENC_MACHING_CP(enc, "CP852", 852);
904 ENC_MACHING_CP(enc, "CP855", 855);
905 ENC_MACHING_CP(enc, "CP949", 949);
906 ENC_MACHING_CP(enc, "EUC-JP", 20932);
907 ENC_MACHING_CP(enc, "EUC-KR", 51949);
908 ENC_MACHING_CP(enc, "EUC-TW", 51950);
909 ENC_MACHING_CP(enc, "GB18030", 54936);
910 ENC_MACHING_CP(enc, "GB2312", 51936);
911 ENC_MACHING_CP(enc, "GBK", 936);
912 ENC_MACHING_CP(enc, "IBM437", 437);
913 ENC_MACHING_CP(enc, "IBM737", 737);
914 ENC_MACHING_CP(enc, "IBM775", 775);
915 ENC_MACHING_CP(enc, "IBM852", 852);
916 ENC_MACHING_CP(enc, "IBM855", 855);
917 ENC_MACHING_CP(enc, "IBM857", 857);
918 ENC_MACHING_CP(enc, "IBM860", 860);
919 ENC_MACHING_CP(enc, "IBM861", 861);
920 ENC_MACHING_CP(enc, "IBM862", 862);
921 ENC_MACHING_CP(enc, "IBM863", 863);
922 ENC_MACHING_CP(enc, "IBM864", 864);
923 ENC_MACHING_CP(enc, "IBM865", 865);
924 ENC_MACHING_CP(enc, "IBM866", 866);
925 ENC_MACHING_CP(enc, "IBM869", 869);
926 ENC_MACHING_CP(enc, "ISO-2022-JP", 50220);
927 ENC_MACHING_CP(enc, "ISO-8859-1", 28591);
928 ENC_MACHING_CP(enc, "ISO-8859-15", 28605);
929 ENC_MACHING_CP(enc, "ISO-8859-2", 28592);
930 ENC_MACHING_CP(enc, "ISO-8859-3", 28593);
931 ENC_MACHING_CP(enc, "ISO-8859-4", 28594);
932 ENC_MACHING_CP(enc, "ISO-8859-5", 28595);
933 ENC_MACHING_CP(enc, "ISO-8859-6", 28596);
934 ENC_MACHING_CP(enc, "ISO-8859-7", 28597);
935 ENC_MACHING_CP(enc, "ISO-8859-8", 28598);
936 ENC_MACHING_CP(enc, "ISO-8859-9", 28599);
937 ENC_MACHING_CP(enc, "KOI8-R", 20866);
938 ENC_MACHING_CP(enc, "KOI8-U", 21866);
939 ENC_MACHING_CP(enc, "Shift_JIS", 932);
940 ENC_MACHING_CP(enc, "UTF-16BE", 1201);
941 ENC_MACHING_CP(enc, "UTF-16LE", 1200);
942 ENC_MACHING_CP(enc, "UTF-7", 65000);
943 ENC_MACHING_CP(enc, "UTF-8", 65001);
944 ENC_MACHING_CP(enc, "Windows-1250", 1250);
945 ENC_MACHING_CP(enc, "Windows-1251", 1251);
946 ENC_MACHING_CP(enc, "Windows-1252", 1252);
947 ENC_MACHING_CP(enc, "Windows-1253", 1253);
948 ENC_MACHING_CP(enc, "Windows-1254", 1254);
949 ENC_MACHING_CP(enc, "Windows-1255", 1255);
950 ENC_MACHING_CP(enc, "Windows-1256", 1256);
951 ENC_MACHING_CP(enc, "Windows-1257", 1257);
952 ENC_MACHING_CP(enc, "Windows-1258", 1258);
953 ENC_MACHING_CP(enc, "Windows-31J", 932);
954 ENC_MACHING_CP(enc, "Windows-874", 874);
955 ENC_MACHING_CP(enc, "eucJP-ms", 20932);
956 return CP_ACP;
959 static UINT
960 ole_init_cp()
962 UINT cp;
963 rb_encoding *encdef;
964 encdef = rb_default_external_encoding();
965 cp = ole_encoding2cp(encdef);
966 if (code_page_installed(cp)) {
967 cWIN32OLE_cp = cp;
969 return cp;
972 struct myCPINFOEX {
973 UINT MaxCharSize;
974 BYTE DefaultChar[2];
975 BYTE LeadByte[12];
976 WCHAR UnicodeDefaultChar;
977 UINT CodePage;
978 char CodePageName[MAX_PATH];
981 static rb_encoding *
982 ole_cp2encoding(UINT cp)
984 static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL;
985 struct myCPINFOEX* buf;
986 VALUE enc_name;
987 char *enc_cstr;
988 int idx;
990 if (!code_page_installed(cp)) {
991 switch(cp) {
992 case CP_ACP:
993 cp = GetACP();
994 break;
995 case CP_OEMCP:
996 cp = GetOEMCP();
997 break;
998 case CP_MACCP:
999 case CP_THREAD_ACP:
1000 if (!pGetCPInfoEx) {
1001 pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
1002 GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
1003 if (!pGetCPInfoEx) {
1004 pGetCPInfoEx = (void*)-1;
1007 buf = ALLOCA_N(struct myCPINFOEX, 1);
1008 ZeroMemory(buf, sizeof(struct myCPINFOEX));
1009 if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
1010 rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
1011 break; /* never reach here */
1013 cp = buf->CodePage;
1014 break;
1015 case CP_SYMBOL:
1016 case CP_UTF7:
1017 case CP_UTF8:
1018 // nothing ToDo
1019 break;
1020 default:
1021 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.");
1022 break;
1026 enc_name = rb_sprintf("CP%d", cp);
1027 idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name));
1028 if (idx < 0)
1029 idx = rb_define_dummy_encoding(enc_cstr);
1030 return rb_enc_from_index(idx);
1033 static char *
1034 ole_wc2mb(LPWSTR pw)
1036 int size;
1037 LPSTR pm;
1038 size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL);
1039 if (size) {
1040 pm = ALLOC_N(char, size + 1);
1041 WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, pm, size, NULL, NULL);
1042 pm[size] = '\0';
1044 else {
1045 pm = ALLOC_N(char, 1);
1046 *pm = '\0';
1048 return pm;
1051 static VALUE
1052 ole_hresult2msg(HRESULT hr)
1054 VALUE msg = Qnil;
1055 char *p_msg = NULL;
1056 char *term = NULL;
1057 DWORD dwCount;
1059 char strhr[100];
1060 sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr);
1061 msg = rb_str_new2(strhr);
1063 dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1064 FORMAT_MESSAGE_FROM_SYSTEM |
1065 FORMAT_MESSAGE_IGNORE_INSERTS,
1066 NULL, hr, cWIN32OLE_lcid,
1067 (LPTSTR)&p_msg, 0, NULL);
1068 if (dwCount > 0) {
1069 term = p_msg + strlen(p_msg);
1070 while (p_msg < term) {
1071 term--;
1072 if (*term == '\r' || *term == '\n')
1073 *term = '\0';
1074 else break;
1076 if (p_msg[0] != '\0') {
1077 rb_str_cat2(msg, p_msg);
1080 LocalFree(p_msg);
1081 return msg;
1084 static void
1085 ole_freeexceptinfo(EXCEPINFO *pExInfo)
1087 SysFreeString(pExInfo->bstrDescription);
1088 SysFreeString(pExInfo->bstrSource);
1089 SysFreeString(pExInfo->bstrHelpFile);
1092 static VALUE
1093 ole_excepinfo2msg(EXCEPINFO *pExInfo)
1095 char error_code[40];
1096 char *pSource = NULL;
1097 char *pDescription = NULL;
1098 VALUE error_msg;
1099 if(pExInfo->pfnDeferredFillIn != NULL) {
1100 (*pExInfo->pfnDeferredFillIn)(pExInfo);
1102 if (pExInfo->bstrSource != NULL) {
1103 pSource = ole_wc2mb(pExInfo->bstrSource);
1105 if (pExInfo->bstrDescription != NULL) {
1106 pDescription = ole_wc2mb(pExInfo->bstrDescription);
1108 if(pExInfo->wCode == 0) {
1109 sprintf(error_code, "\n OLE error code:%lX in ", pExInfo->scode);
1111 else{
1112 sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode);
1114 error_msg = rb_str_new2(error_code);
1115 if(pSource != NULL) {
1116 rb_str_cat(error_msg, pSource, strlen(pSource));
1118 else {
1119 rb_str_cat(error_msg, "<Unknown>", 9);
1121 rb_str_cat2(error_msg, "\n ");
1122 if(pDescription != NULL) {
1123 rb_str_cat2(error_msg, pDescription);
1125 else {
1126 rb_str_cat2(error_msg, "<No Description>");
1128 if(pSource) free(pSource);
1129 if(pDescription) free(pDescription);
1130 ole_freeexceptinfo(pExInfo);
1131 return error_msg;
1134 static void
1135 ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...)
1137 va_list args;
1138 char buf[BUFSIZ];
1139 VALUE err_msg;
1140 va_init_list(args, fmt);
1141 vsnprintf(buf, BUFSIZ, fmt, args);
1142 va_end(args);
1144 err_msg = ole_hresult2msg(hr);
1145 if(err_msg != Qnil) {
1146 rb_raise(ecs, "%s\n%s", buf, StringValuePtr(err_msg));
1148 else {
1149 rb_raise(ecs, "%s", buf);
1153 void
1154 ole_uninitialize()
1156 OleUninitialize();
1157 g_ole_initialized = FALSE;
1160 static void
1161 ole_initialize()
1163 HRESULT hr;
1165 if(g_ole_initialized == FALSE) {
1166 hr = OleInitialize(NULL);
1167 if(FAILED(hr)) {
1168 ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize");
1170 g_ole_initialized = TRUE;
1172 * In some situation, OleUninitialize does not work fine. ;-<
1175 atexit((void (*)(void))ole_uninitialize);
1177 hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter);
1178 if(FAILED(hr)) {
1179 previous_filter = NULL;
1180 ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter");
1185 static void
1186 ole_msg_loop() {
1187 MSG msg;
1188 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
1189 TranslateMessage(&msg);
1190 DispatchMessage(&msg);
1194 static void
1195 ole_free(struct oledata *pole)
1197 OLE_FREE(pole->pDispatch);
1198 free(pole);
1201 static void
1202 oletype_free(struct oletypedata *poletype)
1204 OLE_FREE(poletype->pTypeInfo);
1205 free(poletype);
1208 static void
1209 olemethod_free(struct olemethoddata *polemethod)
1211 OLE_FREE(polemethod->pTypeInfo);
1212 OLE_FREE(polemethod->pOwnerTypeInfo);
1213 free(polemethod);
1216 static void
1217 olevariable_free(struct olevariabledata *polevar)
1219 OLE_FREE(polevar->pTypeInfo);
1220 free(polevar);
1223 static void
1224 oleparam_free(struct oleparamdata *pole)
1226 OLE_FREE(pole->pTypeInfo);
1227 free(pole);
1230 static LPWSTR
1231 ole_vstr2wc(VALUE vstr)
1233 rb_encoding *enc;
1234 int cp;
1235 int size;
1236 LPWSTR pw;
1237 st_data_t data;
1238 enc = rb_enc_get(vstr);
1239 if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) {
1240 cp = data;
1241 } else {
1242 cp = ole_encoding2cp(enc);
1243 if (code_page_installed(cp) ||
1244 cp == CP_ACP ||
1245 cp == CP_OEMCP ||
1246 cp == CP_MACCP ||
1247 cp == CP_THREAD_ACP ||
1248 cp == CP_SYMBOL ||
1249 cp == CP_UTF7 ||
1250 cp == CP_UTF8 ) {
1251 st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp);
1252 } else {
1253 rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
1256 size = MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, NULL, 0);
1257 pw = SysAllocStringLen(NULL, size - 1);
1258 MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, pw, size);
1259 return pw;
1262 static LPWSTR
1263 ole_mb2wc(char *pm, int len)
1265 int size;
1266 LPWSTR pw;
1267 size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0);
1268 pw = SysAllocStringLen(NULL, size - 1);
1269 MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size);
1270 return pw;
1273 static VALUE
1274 ole_wc2vstr(LPWSTR pw, BOOL isfree)
1276 char *p = ole_wc2mb(pw);
1277 VALUE vstr = rb_enc_str_new(p, strlen(p), cWIN32OLE_enc);
1278 if(isfree)
1279 SysFreeString(pw);
1280 free(p);
1281 return vstr;
1284 static VALUE
1285 ole_ary_m_entry(VALUE val, long *pid)
1287 VALUE obj = Qnil;
1288 int i = 0;
1289 obj = val;
1290 while(TYPE(obj) == T_ARRAY) {
1291 obj = rb_ary_entry(obj, pid[i]);
1292 i++;
1294 return obj;
1297 static void *
1298 get_ptr_of_variant(VARIANT *pvar)
1300 switch(V_VT(pvar)) {
1301 case VT_UI1:
1302 return &V_UI1(pvar);
1303 break;
1304 case VT_I2:
1305 return &V_I2(pvar);
1306 break;
1307 case VT_UI2:
1308 return &V_UI2(pvar);
1309 break;
1310 case VT_I4:
1311 return &V_I4(pvar);
1312 break;
1313 case VT_UI4:
1314 return &V_UI4(pvar);
1315 break;
1316 case VT_R4:
1317 return &V_R4(pvar);
1318 break;
1319 case VT_R8:
1320 return &V_R8(pvar);
1321 break;
1322 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1323 case VT_I8:
1324 return &V_I8(pvar);
1325 break;
1326 case VT_UI8:
1327 return &V_UI8(pvar);
1328 break;
1329 #endif
1330 case VT_INT:
1331 return &V_INT(pvar);
1332 break;
1333 case VT_UINT:
1334 return &V_UINT(pvar);
1335 break;
1336 case VT_CY:
1337 return &V_CY(pvar);
1338 break;
1339 case VT_DATE:
1340 return &V_DATE(pvar);
1341 break;
1342 case VT_BSTR:
1343 return V_BSTR(pvar);
1344 break;
1345 case VT_DISPATCH:
1346 return V_DISPATCH(pvar);
1347 break;
1348 case VT_ERROR:
1349 return &V_ERROR(pvar);
1350 break;
1351 case VT_BOOL:
1352 return &V_BOOL(pvar);
1353 break;
1354 case VT_UNKNOWN:
1355 return V_UNKNOWN(pvar);
1356 break;
1357 case VT_ARRAY:
1358 return &V_ARRAY(pvar);
1359 break;
1360 default:
1361 return NULL;
1362 break;
1366 static VALUE
1367 is_all_index_under(long *pid, long *pub, long dim)
1369 long i = 0;
1370 for (i = 0; i < dim; i++) {
1371 if (pid[i] > pub[i]) {
1372 return Qfalse;
1375 return Qtrue;
1378 static void
1379 ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vt)
1381 VALUE val1;
1382 HRESULT hr = S_OK;
1383 VARIANT var;
1384 VOID *p = NULL;
1385 long i = n;
1386 while(i >= 0) {
1387 val1 = ole_ary_m_entry(val, pid);
1388 VariantInit(&var);
1389 p = val2variant_ptr(val1, &var, vt);
1390 if (is_all_index_under(pid, pub, dim) == Qtrue) {
1391 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
1392 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
1393 rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface");
1395 hr = SafeArrayPutElement(psa, pid, p);
1397 if (FAILED(hr)) {
1398 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement");
1400 pid[i] += 1;
1401 if (pid[i] > pub[i]) {
1402 pid[i] = 0;
1403 i -= 1;
1404 } else {
1405 i = dim - 1;
1410 static long
1411 dimension(VALUE val) {
1412 long dim = 0;
1413 long dim1 = 0;
1414 long len = 0;
1415 long i = 0;
1416 if (TYPE(val) == T_ARRAY) {
1417 len = RARRAY_LEN(val);
1418 for (i = 0; i < len; i++) {
1419 dim1 = dimension(rb_ary_entry(val, i));
1420 if (dim < dim1) {
1421 dim = dim1;
1424 dim += 1;
1426 return dim;
1429 static long
1430 ary_len_of_dim(VALUE ary, long dim) {
1431 long ary_len = 0;
1432 long ary_len1 = 0;
1433 long len = 0;
1434 long i = 0;
1435 VALUE val;
1436 if (dim == 0) {
1437 if (TYPE(ary) == T_ARRAY) {
1438 ary_len = RARRAY_LEN(ary);
1440 } else {
1441 if (TYPE(ary) == T_ARRAY) {
1442 len = RARRAY_LEN(ary);
1443 for (i = 0; i < len; i++) {
1444 val = rb_ary_entry(ary, i);
1445 ary_len1 = ary_len_of_dim(val, dim-1);
1446 if (ary_len < ary_len1) {
1447 ary_len = ary_len1;
1452 return ary_len;
1455 static HRESULT
1456 ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
1458 long dim = 0;
1459 int i = 0;
1460 HRESULT hr = S_OK;
1462 SAFEARRAYBOUND *psab = NULL;
1463 SAFEARRAY *psa = NULL;
1464 long *pub, *pid;
1466 Check_Type(val, T_ARRAY);
1468 dim = dimension(val);
1470 psab = ALLOC_N(SAFEARRAYBOUND, dim);
1471 pub = ALLOC_N(long, dim);
1472 pid = ALLOC_N(long, dim);
1474 if(!psab || !pub || !pid) {
1475 if(pub) free(pub);
1476 if(psab) free(psab);
1477 if(pid) free(pid);
1478 rb_raise(rb_eRuntimeError, "memory allocation error");
1481 for (i = 0; i < dim; i++) {
1482 psab[i].cElements = ary_len_of_dim(val, i);
1483 psab[i].lLbound = 0;
1484 pub[i] = psab[i].cElements - 1;
1485 pid[i] = 0;
1487 /* Create and fill VARIANT array */
1488 if ((vt & ~VT_BYREF) == VT_ARRAY) {
1489 vt = (vt | VT_VARIANT);
1491 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
1492 if (psa == NULL)
1493 hr = E_OUTOFMEMORY;
1494 else
1495 hr = SafeArrayLock(psa);
1496 if (SUCCEEDED(hr)) {
1497 ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK));
1498 hr = SafeArrayUnlock(psa);
1501 if(pub) free(pub);
1502 if(psab) free(psab);
1503 if(pid) free(pid);
1505 if (SUCCEEDED(hr)) {
1506 V_VT(var) = vt;
1507 V_ARRAY(var) = psa;
1509 else {
1510 if (psa != NULL)
1511 SafeArrayDestroy(psa);
1513 return hr;
1516 static void
1517 ole_val2variant(VALUE val, VARIANT *var)
1519 struct oledata *pole;
1520 struct olevariantdata *pvar;
1521 if(rb_obj_is_kind_of(val, cWIN32OLE)) {
1522 Data_Get_Struct(val, struct oledata, pole);
1523 OLE_ADDREF(pole->pDispatch);
1524 V_VT(var) = VT_DISPATCH;
1525 V_DISPATCH(var) = pole->pDispatch;
1526 return;
1528 if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) {
1529 Data_Get_Struct(val, struct olevariantdata, pvar);
1530 VariantCopy(var, &(pvar->var));
1531 return;
1534 if (rb_obj_is_kind_of(val, rb_cTime)) {
1535 V_VT(var) = VT_DATE;
1536 V_DATE(var) = time_object2date(val);
1537 return;
1539 switch (TYPE(val)) {
1540 case T_ARRAY:
1541 ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY);
1542 break;
1543 case T_STRING:
1544 V_VT(var) = VT_BSTR;
1545 V_BSTR(var) = ole_vstr2wc(val);
1546 break;
1547 case T_FIXNUM:
1548 V_VT(var) = VT_I4;
1549 V_I4(var) = NUM2INT(val);
1550 break;
1551 case T_BIGNUM:
1552 V_VT(var) = VT_R8;
1553 V_R8(var) = rb_big2dbl(val);
1554 break;
1555 case T_FLOAT:
1556 V_VT(var) = VT_R8;
1557 V_R8(var) = NUM2DBL(val);
1558 break;
1559 case T_TRUE:
1560 V_VT(var) = VT_BOOL;
1561 V_BOOL(var) = VARIANT_TRUE;
1562 break;
1563 case T_FALSE:
1564 V_VT(var) = VT_BOOL;
1565 V_BOOL(var) = VARIANT_FALSE;
1566 break;
1567 case T_NIL:
1568 if (g_nil_to == VT_ERROR) {
1569 V_VT(var) = VT_ERROR;
1570 V_ERROR(var) = DISP_E_PARAMNOTFOUND;
1571 }else {
1572 V_VT(var) = VT_EMPTY;
1574 break;
1575 default:
1576 V_VT(var) = VT_DISPATCH;
1577 V_DISPATCH(var) = val2dispatch(val);
1578 break;
1582 static void
1583 ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
1585 if (val == Qnil) {
1586 if (vt == VT_VARIANT) {
1587 ole_val2variant2(val, var);
1588 } else {
1589 V_VT(var) = (vt & ~VT_BYREF);
1590 if (V_VT(var) == VT_DISPATCH) {
1591 V_DISPATCH(var) = NULL;
1592 } else if (V_VT(var) == VT_UNKNOWN) {
1593 V_UNKNOWN(var) = NULL;
1596 return;
1598 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1599 switch(vt & ~VT_BYREF) {
1600 case VT_I8:
1601 V_VT(var) = VT_I8;
1602 V_I8(var) = NUM2I8 (val);
1603 break;
1604 case VT_UI8:
1605 V_VT(var) = VT_UI8;
1606 V_UI8(var) = NUM2UI8(val);
1607 break;
1608 default:
1609 ole_val2variant2(val, var);
1610 break;
1612 #else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
1613 ole_val2variant2(val, var);
1614 #endif
1617 static void
1618 ole_val2ptr_variant(VALUE val, VARIANT *var)
1620 switch (TYPE(val)) {
1621 case T_STRING:
1622 if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
1623 *V_BSTRREF(var) = ole_vstr2wc(val);
1625 break;
1626 case T_FIXNUM:
1627 switch(V_VT(var)) {
1628 case (VT_UI1 | VT_BYREF) :
1629 *V_UI1REF(var) = NUM2CHR(val);
1630 break;
1631 case (VT_I2 | VT_BYREF) :
1632 *V_I2REF(var) = (short)NUM2INT(val);
1633 break;
1634 case (VT_I4 | VT_BYREF) :
1635 *V_I4REF(var) = NUM2INT(val);
1636 break;
1637 case (VT_R4 | VT_BYREF) :
1638 *V_R4REF(var) = (float)NUM2INT(val);
1639 break;
1640 case (VT_R8 | VT_BYREF) :
1641 *V_R8REF(var) = NUM2INT(val);
1642 break;
1643 default:
1644 break;
1646 break;
1647 case T_FLOAT:
1648 switch(V_VT(var)) {
1649 case (VT_I2 | VT_BYREF) :
1650 *V_I2REF(var) = (short)NUM2INT(val);
1651 break;
1652 case (VT_I4 | VT_BYREF) :
1653 *V_I4REF(var) = NUM2INT(val);
1654 break;
1655 case (VT_R4 | VT_BYREF) :
1656 *V_R4REF(var) = (float)NUM2DBL(val);
1657 break;
1658 case (VT_R8 | VT_BYREF) :
1659 *V_R8REF(var) = NUM2DBL(val);
1660 break;
1661 default:
1662 break;
1664 break;
1665 case T_BIGNUM:
1666 if (V_VT(var) == (VT_R8 | VT_BYREF)) {
1667 *V_R8REF(var) = rb_big2dbl(val);
1669 break;
1670 case T_TRUE:
1671 if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
1672 *V_BOOLREF(var) = VARIANT_TRUE;
1674 break;
1675 case T_FALSE:
1676 if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
1677 *V_BOOLREF(var) = VARIANT_FALSE;
1679 break;
1680 default:
1681 break;
1685 static void
1686 ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
1688 V_VT(var) = vt;
1689 if (vt == (VT_VARIANT|VT_BYREF)) {
1690 V_VARIANTREF(var) = realvar;
1691 } else {
1692 if (V_VT(realvar) != (vt & ~VT_BYREF)) {
1693 rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
1695 switch(vt & ~VT_BYREF) {
1696 case VT_I1:
1697 V_I1REF(var) = &V_I1(realvar);
1698 break;
1699 case VT_UI1:
1700 V_UI1REF(var) = &V_UI1(realvar);
1701 break;
1702 case VT_I2:
1703 V_I2REF(var) = &V_I2(realvar);
1704 break;
1705 case VT_UI2:
1706 V_UI2REF(var) = &V_UI2(realvar);
1707 break;
1708 case VT_I4:
1709 V_I4REF(var) = &V_I4(realvar);
1710 break;
1711 case VT_UI4:
1712 V_UI4REF(var) = &V_UI4(realvar);
1713 break;
1714 case VT_R4:
1715 V_R4REF(var) = &V_R4(realvar);
1716 break;
1717 case VT_R8:
1718 V_R8REF(var) = &V_R8(realvar);
1719 break;
1721 #if (_MSC_VER >= 1300)
1722 case VT_I8:
1723 V_I8REF(var) = &V_I8(realvar);
1724 break;
1725 case VT_UI8:
1726 V_UI8REF(var) = &V_UI8(realvar);
1727 break;
1728 #endif
1729 case VT_INT:
1730 V_INTREF(var) = &V_INT(realvar);
1731 break;
1733 case VT_UINT:
1734 V_UINTREF(var) = &V_UINT(realvar);
1735 break;
1737 case VT_CY:
1738 V_CYREF(var) = &V_CY(realvar);
1739 break;
1740 case VT_DATE:
1741 V_DATEREF(var) = &V_DATE(realvar);
1742 break;
1743 case VT_BSTR:
1744 V_BSTRREF(var) = &V_BSTR(realvar);
1745 break;
1746 case VT_DISPATCH:
1747 V_DISPATCHREF(var) = &V_DISPATCH(realvar);
1748 break;
1749 case VT_ERROR:
1750 V_ERRORREF(var) = &V_ERROR(realvar);
1751 break;
1752 case VT_BOOL:
1753 V_BOOLREF(var) = &V_BOOL(realvar);
1754 break;
1755 case VT_UNKNOWN:
1756 V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
1757 break;
1758 case VT_ARRAY:
1759 V_ARRAYREF(var) = &V_ARRAY(realvar);
1760 break;
1761 default:
1762 rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
1763 break;
1768 static void
1769 ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
1771 HRESULT hr = S_OK;
1773 if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && TYPE(val) == T_STRING) {
1774 long len = RSTRING_LEN(val);
1775 void *pdest = NULL;
1776 SAFEARRAY *p = NULL;
1777 SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
1778 if (!psa) {
1779 rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
1781 hr = SafeArrayAccessData(psa, &pdest);
1782 if (SUCCEEDED(hr)) {
1783 memcpy(pdest, RSTRING_PTR(val), len);
1784 SafeArrayUnaccessData(psa);
1785 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
1786 p = V_ARRAY(&(pvar->realvar));
1787 if (p != NULL) {
1788 SafeArrayDestroy(p);
1790 V_ARRAY(&(pvar->realvar)) = psa;
1791 if (vt & VT_BYREF) {
1792 V_VT(&(pvar->var)) = vt;
1793 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
1794 } else {
1795 hr = VariantCopy(&(pvar->var), &(pvar->realvar));
1797 } else {
1798 if (psa)
1799 SafeArrayDestroy(psa);
1801 } else if (vt & VT_ARRAY) {
1802 if (val == Qnil) {
1803 V_VT(&(pvar->var)) = vt;
1804 if (vt & VT_BYREF) {
1805 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
1807 } else {
1808 hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
1809 if (SUCCEEDED(hr)) {
1810 if (vt & VT_BYREF) {
1811 V_VT(&(pvar->var)) = vt;
1812 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
1813 } else {
1814 hr = VariantCopy(&(pvar->var), &(pvar->realvar));
1818 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
1819 } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) {
1820 ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF));
1821 ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF));
1822 V_VT(&(pvar->var)) = vt;
1823 if (vt & VT_BYREF) {
1824 ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1826 #endif
1827 } else {
1828 if (val == Qnil) {
1829 V_VT(&(pvar->var)) = vt;
1830 if (vt == (VT_BYREF | VT_VARIANT)) {
1831 ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1832 } else {
1833 V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
1834 if (vt & VT_BYREF) {
1835 ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1838 } else {
1839 ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
1840 if (vt == (VT_BYREF | VT_VARIANT)) {
1841 ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1842 } else if (vt & VT_BYREF) {
1843 if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
1844 hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
1845 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
1847 if (SUCCEEDED(hr)) {
1848 ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
1850 } else {
1851 if (vt == V_VT(&(pvar->realvar))) {
1852 hr = VariantCopy(&(pvar->var), &(pvar->realvar));
1853 } else {
1854 hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
1855 cWIN32OLE_lcid, 0, vt);
1860 if (FAILED(hr)) {
1861 ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
1865 static void
1866 ole_val2variant2(VALUE val, VARIANT *var)
1868 g_nil_to = VT_EMPTY;
1869 ole_val2variant(val, var);
1870 g_nil_to = VT_ERROR;
1873 static VALUE
1874 make_inspect(const char *class_name, VALUE detail)
1876 VALUE str;
1877 str = rb_str_new2("#<");
1878 rb_str_cat2(str, class_name);
1879 rb_str_cat2(str, ":");
1880 rb_str_concat(str, detail);
1881 rb_str_cat2(str, ">");
1882 return str;
1885 static VALUE
1886 default_inspect(VALUE self, const char *class_name)
1888 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
1889 return make_inspect(class_name, detail);
1892 static VALUE
1893 ole_set_member(VALUE self, IDispatch *dispatch)
1895 struct oledata *pole;
1896 Data_Get_Struct(self, struct oledata, pole);
1897 if (pole->pDispatch) {
1898 OLE_RELEASE(pole->pDispatch);
1899 pole->pDispatch = NULL;
1901 pole->pDispatch = dispatch;
1902 return self;
1906 static VALUE
1907 fole_s_allocate(VALUE klass)
1909 struct oledata *pole;
1910 VALUE obj;
1911 ole_initialize();
1912 obj = Data_Make_Struct(klass,struct oledata,0,ole_free,pole);
1913 pole->pDispatch = NULL;
1914 return obj;
1917 static VALUE
1918 create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv)
1920 VALUE obj = fole_s_allocate(klass);
1921 ole_set_member(obj, pDispatch);
1922 return obj;
1925 static VALUE
1926 ary_new_dim(VALUE myary, long *pid, long *plb, long dim) {
1927 long i;
1928 VALUE obj = Qnil;
1929 VALUE pobj = Qnil;
1930 long *ids = ALLOC_N(long, dim);
1931 if (!ids) {
1932 rb_raise(rb_eRuntimeError, "memory allocation error");
1934 for(i = 0; i < dim; i++) {
1935 ids[i] = pid[i] - plb[i];
1937 obj = myary;
1938 pobj = myary;
1939 for(i = 0; i < dim-1; i++) {
1940 obj = rb_ary_entry(pobj, ids[i]);
1941 if (obj == Qnil) {
1942 rb_ary_store(pobj, ids[i], rb_ary_new());
1944 obj = rb_ary_entry(pobj, ids[i]);
1945 pobj = obj;
1947 if (ids) free(ids);
1948 return obj;
1951 static void
1952 ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val) {
1953 long id = pid[dim - 1] - plb[dim - 1];
1954 VALUE obj = ary_new_dim(myary, pid, plb, dim);
1955 rb_ary_store(obj, id, val);
1958 static VALUE
1959 ole_variant2val(VARIANT *pvar)
1961 VALUE obj = Qnil;
1962 HRESULT hr;
1963 while ( V_VT(pvar) == (VT_BYREF | VT_VARIANT) )
1964 pvar = V_VARIANTREF(pvar);
1966 if(V_ISARRAY(pvar)) {
1967 SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar);
1968 UINT i = 0;
1969 long *pid, *plb, *pub;
1970 VARIANT variant;
1971 VALUE val;
1972 UINT dim = 0;
1973 if (!psa) {
1974 return obj;
1976 dim = SafeArrayGetDim(psa);
1977 VariantInit(&variant);
1978 V_VT(&variant) = (V_VT(pvar) & ~VT_ARRAY) | VT_BYREF;
1980 pid = ALLOC_N(long, dim);
1981 plb = ALLOC_N(long, dim);
1982 pub = ALLOC_N(long, dim);
1984 if(!pid || !plb || !pub) {
1985 if(pid) free(pid);
1986 if(plb) free(plb);
1987 if(pub) free(pub);
1988 rb_raise(rb_eRuntimeError, "memory allocation error");
1991 for(i = 0; i < dim; ++i) {
1992 SafeArrayGetLBound(psa, i+1, &plb[i]);
1993 SafeArrayGetLBound(psa, i+1, &pid[i]);
1994 SafeArrayGetUBound(psa, i+1, &pub[i]);
1996 hr = SafeArrayLock(psa);
1997 if (SUCCEEDED(hr)) {
1998 obj = rb_ary_new();
1999 i = 0;
2000 while (i < dim) {
2001 ary_new_dim(obj, pid, plb, dim);
2002 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
2003 if (SUCCEEDED(hr)) {
2004 val = ole_variant2val(&variant);
2005 ary_store_dim(obj, pid, plb, dim, val);
2007 for (i = 0; i < dim; ++i) {
2008 if (++pid[i] <= pub[i])
2009 break;
2010 pid[i] = plb[i];
2013 SafeArrayUnlock(psa);
2015 if(pid) free(pid);
2016 if(plb) free(plb);
2017 if(pub) free(pub);
2018 return obj;
2020 switch(V_VT(pvar) & ~VT_BYREF){
2021 case VT_EMPTY:
2022 break;
2023 case VT_NULL:
2024 break;
2025 case VT_I1:
2026 if(V_ISBYREF(pvar))
2027 obj = INT2NUM((long)*V_I1REF(pvar));
2028 else
2029 obj = INT2NUM((long)V_I1(pvar));
2030 break;
2032 case VT_UI1:
2033 if(V_ISBYREF(pvar))
2034 obj = INT2NUM((long)*V_UI1REF(pvar));
2035 else
2036 obj = INT2NUM((long)V_UI1(pvar));
2037 break;
2039 case VT_I2:
2040 if(V_ISBYREF(pvar))
2041 obj = INT2NUM((long)*V_I2REF(pvar));
2042 else
2043 obj = INT2NUM((long)V_I2(pvar));
2044 break;
2046 case VT_UI2:
2047 if(V_ISBYREF(pvar))
2048 obj = INT2NUM((long)*V_UI2REF(pvar));
2049 else
2050 obj = INT2NUM((long)V_UI2(pvar));
2051 break;
2053 case VT_I4:
2054 if(V_ISBYREF(pvar))
2055 obj = INT2NUM((long)*V_I4REF(pvar));
2056 else
2057 obj = INT2NUM((long)V_I4(pvar));
2058 break;
2060 case VT_UI4:
2061 if(V_ISBYREF(pvar))
2062 obj = INT2NUM((long)*V_UI4REF(pvar));
2063 else
2064 obj = INT2NUM((long)V_UI4(pvar));
2065 break;
2067 case VT_INT:
2068 if(V_ISBYREF(pvar))
2069 obj = INT2NUM((long)*V_INTREF(pvar));
2070 else
2071 obj = INT2NUM((long)V_INT(pvar));
2072 break;
2074 case VT_UINT:
2075 if(V_ISBYREF(pvar))
2076 obj = INT2NUM((long)*V_UINTREF(pvar));
2077 else
2078 obj = INT2NUM((long)V_UINT(pvar));
2079 break;
2081 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
2082 case VT_I8:
2083 if(V_ISBYREF(pvar))
2084 #if (_MSC_VER >= 1300)
2085 obj = I8_2_NUM(*V_I8REF(pvar));
2086 #else
2087 obj = Qnil;
2088 #endif
2089 else
2090 obj = I8_2_NUM(V_I8(pvar));
2091 break;
2092 case VT_UI8:
2093 if(V_ISBYREF(pvar))
2094 #if (_MSC_VER >= 1300)
2095 obj = UI8_2_NUM(*V_UI8REF(pvar));
2096 #else
2097 obj = Qnil;
2098 #endif
2099 else
2100 obj = UI8_2_NUM(V_UI8(pvar));
2101 break;
2102 #endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
2104 case VT_R4:
2105 if(V_ISBYREF(pvar))
2106 obj = rb_float_new(*V_R4REF(pvar));
2107 else
2108 obj = rb_float_new(V_R4(pvar));
2109 break;
2111 case VT_R8:
2112 if(V_ISBYREF(pvar))
2113 obj = rb_float_new(*V_R8REF(pvar));
2114 else
2115 obj = rb_float_new(V_R8(pvar));
2116 break;
2118 case VT_BSTR:
2120 if(V_ISBYREF(pvar))
2121 obj = ole_wc2vstr(*V_BSTRREF(pvar), FALSE);
2122 else
2123 obj = ole_wc2vstr(V_BSTR(pvar), FALSE);
2124 break;
2127 case VT_ERROR:
2128 if(V_ISBYREF(pvar))
2129 obj = INT2NUM(*V_ERRORREF(pvar));
2130 else
2131 obj = INT2NUM(V_ERROR(pvar));
2132 break;
2134 case VT_BOOL:
2135 if (V_ISBYREF(pvar))
2136 obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse);
2137 else
2138 obj = (V_BOOL(pvar) ? Qtrue : Qfalse);
2139 break;
2141 case VT_DISPATCH:
2143 IDispatch *pDispatch;
2145 if (V_ISBYREF(pvar))
2146 pDispatch = *V_DISPATCHREF(pvar);
2147 else
2148 pDispatch = V_DISPATCH(pvar);
2150 if (pDispatch != NULL ) {
2151 OLE_ADDREF(pDispatch);
2152 obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
2154 break;
2157 case VT_UNKNOWN:
2159 /* get IDispatch interface from IUnknown interface */
2160 IUnknown *punk;
2161 IDispatch *pDispatch;
2162 void *p;
2163 HRESULT hr;
2165 if (V_ISBYREF(pvar))
2166 punk = *V_UNKNOWNREF(pvar);
2167 else
2168 punk = V_UNKNOWN(pvar);
2170 if(punk != NULL) {
2171 hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p);
2172 if(SUCCEEDED(hr)) {
2173 pDispatch = p;
2174 obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
2177 break;
2180 case VT_DATE:
2182 DATE date;
2183 if(V_ISBYREF(pvar))
2184 date = *V_DATEREF(pvar);
2185 else
2186 date = V_DATE(pvar);
2188 obj = date2time_str(date);
2189 break;
2191 case VT_CY:
2192 default:
2194 HRESULT hr;
2195 VARIANT variant;
2196 VariantInit(&variant);
2197 hr = VariantChangeTypeEx(&variant, pvar,
2198 cWIN32OLE_lcid, 0, VT_BSTR);
2199 if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) {
2200 obj = ole_wc2vstr(V_BSTR(&variant), FALSE);
2202 VariantClear(&variant);
2203 break;
2206 return obj;
2209 static LONG
2210 reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
2212 return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey);
2215 static LONG
2216 reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
2218 return reg_open_key(hkey, StringValuePtr(key), phkey);
2221 static VALUE
2222 reg_enum_key(HKEY hkey, DWORD i)
2224 char buf[BUFSIZ + 1];
2225 DWORD size_buf = sizeof(buf);
2226 FILETIME ft;
2227 LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf,
2228 NULL, NULL, NULL, &ft);
2229 if(err == ERROR_SUCCESS) {
2230 buf[BUFSIZ] = '\0';
2231 return rb_str_new2(buf);
2233 return Qnil;
2236 static VALUE
2237 reg_get_val(HKEY hkey, const char *subkey)
2239 char *pbuf;
2240 DWORD dwtype = 0;
2241 LONG size = 0;
2242 VALUE val = Qnil;
2243 LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size);
2245 if (err == ERROR_SUCCESS) {
2246 pbuf = ALLOC_N(char, size + 1);
2247 err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, pbuf, &size);
2248 if (err == ERROR_SUCCESS) {
2249 pbuf[size] = '\0';
2250 val = rb_str_new2(pbuf);
2252 free(pbuf);
2254 return val;
2257 static VALUE
2258 reg_get_val2(HKEY hkey, const char *subkey)
2260 HKEY hsubkey;
2261 LONG err;
2262 VALUE val = Qnil;
2263 err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey);
2264 if (err == ERROR_SUCCESS) {
2265 val = reg_get_val(hsubkey, NULL);
2266 RegCloseKey(hsubkey);
2268 if (val == Qnil) {
2269 val = reg_get_val(hkey, subkey);
2271 return val;
2274 static VALUE
2275 reg_get_typelib_file_path(HKEY hkey)
2277 VALUE path = Qnil;
2278 path = reg_get_val2(hkey, "win32");
2279 if (path == Qnil) {
2280 path = reg_get_val2(hkey, "win16");
2282 return path;
2285 static VALUE
2286 typelib_file_from_clsid(VALUE ole)
2288 HKEY hroot, hclsid;
2289 LONG err;
2290 VALUE typelib;
2291 char path[MAX_PATH + 1];
2293 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot);
2294 if (err != ERROR_SUCCESS) {
2295 return Qnil;
2297 err = reg_open_key(hroot, StringValuePtr(ole), &hclsid);
2298 if (err != ERROR_SUCCESS) {
2299 RegCloseKey(hroot);
2300 return Qnil;
2302 typelib = reg_get_val2(hclsid, "InprocServer32");
2303 RegCloseKey(hroot);
2304 RegCloseKey(hclsid);
2305 if (typelib != Qnil) {
2306 ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path));
2307 path[MAX_PATH] = '\0';
2308 typelib = rb_str_new2(path);
2310 return typelib;
2313 static VALUE
2314 typelib_file_from_typelib(VALUE ole)
2316 HKEY htypelib, hclsid, hversion, hlang;
2317 double fver;
2318 DWORD i, j, k;
2319 LONG err;
2320 BOOL found = FALSE;
2321 VALUE typelib;
2322 VALUE file = Qnil;
2323 VALUE clsid;
2324 VALUE ver;
2325 VALUE lang;
2327 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
2328 if(err != ERROR_SUCCESS) {
2329 return Qnil;
2331 for(i = 0; !found; i++) {
2332 clsid = reg_enum_key(htypelib, i);
2333 if (clsid == Qnil)
2334 break;
2335 err = reg_open_vkey(htypelib, clsid, &hclsid);
2336 if (err != ERROR_SUCCESS)
2337 continue;
2338 fver = 0;
2339 for(j = 0; !found; j++) {
2340 ver = reg_enum_key(hclsid, j);
2341 if (ver == Qnil)
2342 break;
2343 err = reg_open_vkey(hclsid, ver, &hversion);
2344 if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
2345 continue;
2346 fver = atof(StringValuePtr(ver));
2347 typelib = reg_get_val(hversion, NULL);
2348 if (typelib == Qnil)
2349 continue;
2350 if (rb_str_cmp(typelib, ole) == 0) {
2351 for(k = 0; !found; k++) {
2352 lang = reg_enum_key(hversion, k);
2353 if (lang == Qnil)
2354 break;
2355 err = reg_open_vkey(hversion, lang, &hlang);
2356 if (err == ERROR_SUCCESS) {
2357 if ((file = reg_get_typelib_file_path(hlang)) != Qnil)
2358 found = TRUE;
2359 RegCloseKey(hlang);
2363 RegCloseKey(hversion);
2365 RegCloseKey(hclsid);
2367 RegCloseKey(htypelib);
2368 return file;
2371 static VALUE
2372 typelib_file(VALUE ole)
2374 VALUE file = typelib_file_from_clsid(ole);
2375 if (file != Qnil) {
2376 return file;
2378 return typelib_file_from_typelib(ole);
2381 static void
2382 ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self)
2384 unsigned int count;
2385 unsigned int index;
2386 int iVar;
2387 ITypeInfo *pTypeInfo;
2388 TYPEATTR *pTypeAttr;
2389 VARDESC *pVarDesc;
2390 HRESULT hr;
2391 unsigned int len;
2392 BSTR bstr;
2393 char *pName = NULL;
2394 VALUE val;
2395 VALUE constant;
2396 ID id;
2397 constant = rb_hash_new();
2398 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
2399 for (index = 0; index < count; index++) {
2400 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo);
2401 if (FAILED(hr))
2402 continue;
2403 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
2404 if(FAILED(hr)) {
2405 OLE_RELEASE(pTypeInfo);
2406 continue;
2408 for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) {
2409 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc);
2410 if(FAILED(hr))
2411 continue;
2412 if(pVarDesc->varkind == VAR_CONST &&
2413 !(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
2414 VARFLAG_FRESTRICTED |
2415 VARFLAG_FNONBROWSABLE))) {
2416 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
2417 1, &len);
2418 if(FAILED(hr) || len == 0 || !bstr)
2419 continue;
2420 pName = ole_wc2mb(bstr);
2421 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
2422 *pName = toupper(*pName);
2423 id = rb_intern(pName);
2424 if (rb_is_const_id(id)) {
2425 rb_define_const(klass, pName, val);
2427 else {
2428 rb_hash_aset(constant, rb_str_new2(pName), val);
2430 SysFreeString(bstr);
2431 if(pName) {
2432 free(pName);
2433 pName = NULL;
2436 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
2438 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
2439 OLE_RELEASE(pTypeInfo);
2441 rb_define_const(klass, "CONSTANTS", constant);
2444 static HRESULT
2445 clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid)
2447 HKEY hlm;
2448 HKEY hpid;
2449 VALUE subkey;
2450 LONG err;
2451 char clsid[100];
2452 OLECHAR *pbuf;
2453 DWORD len;
2454 DWORD dwtype;
2455 HRESULT hr = S_OK;
2456 err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm);
2457 if (err != ERROR_SUCCESS)
2458 return HRESULT_FROM_WIN32(err);
2459 subkey = rb_str_new2("SOFTWARE\\Classes\\");
2460 rb_str_concat(subkey, com);
2461 rb_str_cat2(subkey, "\\CLSID");
2462 err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid);
2463 if (err != ERROR_SUCCESS)
2464 hr = HRESULT_FROM_WIN32(err);
2465 else {
2466 len = sizeof(clsid);
2467 err = RegQueryValueEx(hpid, (LPBYTE)"", NULL, &dwtype, clsid, &len);
2468 if (err == ERROR_SUCCESS && dwtype == REG_SZ) {
2469 pbuf = ole_mb2wc(clsid, -1);
2470 hr = CLSIDFromString(pbuf, pclsid);
2471 SysFreeString(pbuf);
2473 else {
2474 hr = HRESULT_FROM_WIN32(err);
2476 RegCloseKey(hpid);
2478 RegCloseKey(hlm);
2479 return hr;
2482 static VALUE
2483 ole_create_dcom(int argc, VALUE *argv, VALUE self)
2485 VALUE ole, host, others;
2486 HRESULT hr;
2487 CLSID clsid;
2488 OLECHAR *pbuf;
2490 COSERVERINFO serverinfo;
2491 MULTI_QI multi_qi;
2492 DWORD clsctx = CLSCTX_REMOTE_SERVER;
2494 if (!gole32)
2495 gole32 = LoadLibrary("OLE32");
2496 if (!gole32)
2497 rb_raise(rb_eRuntimeError, "failed to load OLE32");
2498 if (!gCoCreateInstanceEx)
2499 gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*)
2500 GetProcAddress(gole32, "CoCreateInstanceEx");
2501 if (!gCoCreateInstanceEx)
2502 rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment");
2503 rb_scan_args(argc, argv, "2*", &ole, &host, &others);
2505 pbuf = ole_vstr2wc(ole);
2506 hr = CLSIDFromProgID(pbuf, &clsid);
2507 if (FAILED(hr))
2508 hr = clsid_from_remote(host, ole, &clsid);
2509 if (FAILED(hr))
2510 hr = CLSIDFromString(pbuf, &clsid);
2511 SysFreeString(pbuf);
2512 if (FAILED(hr))
2513 ole_raise(hr, eWIN32OLERuntimeError,
2514 "unknown OLE server: `%s'",
2515 StringValuePtr(ole));
2516 memset(&serverinfo, 0, sizeof(COSERVERINFO));
2517 serverinfo.pwszName = ole_vstr2wc(host);
2518 memset(&multi_qi, 0, sizeof(MULTI_QI));
2519 multi_qi.pIID = &IID_IDispatch;
2520 hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi);
2521 SysFreeString(serverinfo.pwszName);
2522 if (FAILED(hr))
2523 ole_raise(hr, eWIN32OLERuntimeError,
2524 "failed to create DCOM server `%s' in `%s'",
2525 StringValuePtr(ole),
2526 StringValuePtr(host));
2528 ole_set_member(self, (IDispatch*)multi_qi.pItf);
2529 return self;
2532 static VALUE
2533 ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
2535 IBindCtx *pBindCtx;
2536 IMoniker *pMoniker;
2537 IDispatch *pDispatch;
2538 void *p;
2539 HRESULT hr;
2540 OLECHAR *pbuf;
2541 ULONG eaten = 0;
2543 ole_initialize();
2545 hr = CreateBindCtx(0, &pBindCtx);
2546 if(FAILED(hr)) {
2547 ole_raise(hr, eWIN32OLERuntimeError,
2548 "failed to create bind context");
2551 pbuf = ole_vstr2wc(moniker);
2552 hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker);
2553 SysFreeString(pbuf);
2554 if(FAILED(hr)) {
2555 OLE_RELEASE(pBindCtx);
2556 ole_raise(hr, eWIN32OLERuntimeError,
2557 "failed to parse display name of moniker `%s'",
2558 StringValuePtr(moniker));
2560 hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL,
2561 &IID_IDispatch, &p);
2562 pDispatch = p;
2563 OLE_RELEASE(pMoniker);
2564 OLE_RELEASE(pBindCtx);
2566 if(FAILED(hr)) {
2567 ole_raise(hr, eWIN32OLERuntimeError,
2568 "failed to bind moniker `%s'",
2569 StringValuePtr(moniker));
2571 return create_win32ole_object(self, pDispatch, argc, argv);
2575 * call-seq:
2576 * WIN32OLE.connect( ole ) --> aWIN32OLE
2578 * Returns running OLE Automation object or WIN32OLE object from moniker.
2579 * 1st argument should be OLE program id or class id or moniker.
2581 * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel.
2583 static VALUE
2584 fole_s_connect(int argc, VALUE *argv, VALUE self)
2586 VALUE svr_name;
2587 VALUE others;
2588 HRESULT hr;
2589 CLSID clsid;
2590 OLECHAR *pBuf;
2591 IDispatch *pDispatch;
2592 void *p;
2593 IUnknown *pUnknown;
2595 rb_secure(4);
2596 /* initialize to use OLE */
2597 ole_initialize();
2599 rb_scan_args(argc, argv, "1*", &svr_name, &others);
2600 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
2601 rb_raise(rb_eSecurityError, "Insecure Object Connection - %s",
2602 StringValuePtr(svr_name));
2605 /* get CLSID from OLE server name */
2606 pBuf = ole_vstr2wc(svr_name);
2607 hr = CLSIDFromProgID(pBuf, &clsid);
2608 if(FAILED(hr)) {
2609 hr = CLSIDFromString(pBuf, &clsid);
2611 SysFreeString(pBuf);
2612 if(FAILED(hr)) {
2613 return ole_bind_obj(svr_name, argc, argv, self);
2616 hr = GetActiveObject(&clsid, 0, &pUnknown);
2617 if (FAILED(hr)) {
2618 ole_raise(hr, eWIN32OLERuntimeError,
2619 "OLE server `%s' not running", StringValuePtr(svr_name));
2621 hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p);
2622 pDispatch = p;
2623 if(FAILED(hr)) {
2624 OLE_RELEASE(pUnknown);
2625 ole_raise(hr, eWIN32OLERuntimeError,
2626 "failed to create WIN32OLE server `%s'",
2627 StringValuePtr(svr_name));
2630 OLE_RELEASE(pUnknown);
2632 return create_win32ole_object(self, pDispatch, argc, argv);
2636 * call-seq:
2637 * WIN32OLE.const_load( ole, mod = WIN32OLE)
2639 * Defines the constants of OLE Automation server as mod's constants.
2640 * The first argument is WIN32OLE object or type library name.
2641 * If 2nd argument is omitted, the default is WIN32OLE.
2642 * The first letter of Ruby's constant variable name is upper case,
2643 * so constant variable name of WIN32OLE object is capitalized.
2644 * For example, the 'xlTop' constant of Excel is changed to 'XlTop'
2645 * in WIN32OLE.
2646 * If the first letter of constant variabl is not [A-Z], then
2647 * the constant is defined as CONSTANTS hash element.
2649 * module EXCEL_CONST
2650 * end
2651 * excel = WIN32OLE.new('Excel.Application')
2652 * WIN32OLE.const_load(excel, EXCEL_CONST)
2653 * puts EXCEL_CONST::XlTop # => -4160
2654 * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541
2656 * WIN32OLE.const_load(excel)
2657 * puts WIN32OLE::XlTop # => -4160
2659 * module MSO
2660 * end
2661 * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO)
2662 * puts MSO::MsoLineSingle # => 1
2664 static VALUE
2665 fole_s_const_load(int argc, VALUE *argv, VALUE self)
2667 VALUE ole;
2668 VALUE klass;
2669 struct oledata *pole;
2670 ITypeInfo *pTypeInfo;
2671 ITypeLib *pTypeLib;
2672 unsigned int index;
2673 HRESULT hr;
2674 OLECHAR *pBuf;
2675 VALUE file;
2676 LCID lcid = cWIN32OLE_lcid;
2678 rb_secure(4);
2679 rb_scan_args(argc, argv, "11", &ole, &klass);
2680 if (TYPE(klass) != T_CLASS &&
2681 TYPE(klass) != T_MODULE &&
2682 TYPE(klass) != T_NIL) {
2683 rb_raise(rb_eTypeError, "2nd parameter must be Class or Module");
2685 if (rb_obj_is_kind_of(ole, cWIN32OLE)) {
2686 OLEData_Get_Struct(ole, pole);
2687 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
2688 0, lcid, &pTypeInfo);
2689 if(FAILED(hr)) {
2690 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
2692 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
2693 if(FAILED(hr)) {
2694 OLE_RELEASE(pTypeInfo);
2695 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib");
2697 OLE_RELEASE(pTypeInfo);
2698 if(TYPE(klass) != T_NIL) {
2699 ole_const_load(pTypeLib, klass, self);
2701 else {
2702 ole_const_load(pTypeLib, cWIN32OLE, self);
2704 OLE_RELEASE(pTypeLib);
2706 else if(TYPE(ole) == T_STRING) {
2707 file = typelib_file(ole);
2708 if (file == Qnil) {
2709 file = ole;
2711 pBuf = ole_vstr2wc(file);
2712 hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib);
2713 SysFreeString(pBuf);
2714 if (FAILED(hr))
2715 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
2716 if(TYPE(klass) != T_NIL) {
2717 ole_const_load(pTypeLib, klass, self);
2719 else {
2720 ole_const_load(pTypeLib, cWIN32OLE, self);
2722 OLE_RELEASE(pTypeLib);
2724 else {
2725 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance");
2727 return Qnil;
2730 static VALUE
2731 ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes)
2734 long count;
2735 int i;
2736 HRESULT hr;
2737 BSTR bstr;
2738 ITypeInfo *pTypeInfo;
2739 VALUE type;
2741 rb_secure(4);
2742 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
2743 for (i = 0; i < count; i++) {
2744 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
2745 &bstr, NULL, NULL, NULL);
2746 if (FAILED(hr))
2747 continue;
2749 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
2750 if (FAILED(hr))
2751 continue;
2753 type = foletype_s_allocate(cWIN32OLE_TYPE);
2754 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr));
2756 rb_ary_push(classes, type);
2757 OLE_RELEASE(pTypeInfo);
2759 return classes;
2762 static ULONG
2763 reference_count(struct oledata * pole)
2765 ULONG n = 0;
2766 if(pole->pDispatch) {
2767 OLE_ADDREF(pole->pDispatch);
2768 n = OLE_RELEASE(pole->pDispatch);
2770 return n;
2774 * call-seq:
2775 * WIN32OLE.ole_reference_count(aWIN32OLE) --> number
2777 * Returns reference counter of Dispatch interface of WIN32OLE object.
2778 * You should not use this method because this method
2779 * exists only for debugging WIN32OLE.
2781 static VALUE
2782 fole_s_reference_count(VALUE self, VALUE obj)
2784 struct oledata * pole;
2785 OLEData_Get_Struct(obj, pole);
2786 return INT2NUM(reference_count(pole));
2790 * call-seq:
2791 * WIN32OLE.ole_free(aWIN32OLE) --> number
2793 * Invokes Release method of Dispatch interface of WIN32OLE object.
2794 * You should not use this method because this method
2795 * exists only for debugging WIN32OLE.
2796 * The return value is reference counter of OLE object.
2798 static VALUE
2799 fole_s_free(VALUE self, VALUE obj)
2801 ULONG n = 0;
2802 struct oledata * pole;
2803 OLEData_Get_Struct(obj, pole);
2804 if(pole->pDispatch) {
2805 if (reference_count(pole) > 0) {
2806 n = OLE_RELEASE(pole->pDispatch);
2809 return INT2NUM(n);
2812 static HWND
2813 ole_show_help(VALUE helpfile, VALUE helpcontext)
2815 FNHTMLHELP *pfnHtmlHelp;
2816 HWND hwnd = 0;
2818 if(!ghhctrl)
2819 ghhctrl = LoadLibrary("HHCTRL.OCX");
2820 if (!ghhctrl)
2821 return hwnd;
2822 pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA");
2823 if (!pfnHtmlHelp)
2824 return hwnd;
2825 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
2826 0x0f, NUM2INT(helpcontext));
2827 if (hwnd == 0)
2828 hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
2829 0, NUM2INT(helpcontext));
2830 return hwnd;
2834 * call-seq:
2835 * WIN32OLE.ole_show_help(obj [,helpcontext])
2837 * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE
2838 * object or WIN32OLE_METHOD object or helpfile.
2840 * excel = WIN32OLE.new('Excel.Application')
2841 * typeobj = excel.ole_type
2842 * WIN32OLE.ole_show_help(typeobj)
2844 static VALUE
2845 fole_s_show_help(int argc, VALUE *argv, VALUE self)
2847 VALUE target;
2848 VALUE helpcontext;
2849 VALUE helpfile;
2850 VALUE name;
2851 HWND hwnd;
2852 rb_scan_args(argc, argv, "11", &target, &helpcontext);
2853 if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) ||
2854 rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) {
2855 helpfile = rb_funcall(target, rb_intern("helpfile"), 0);
2856 if(strlen(StringValuePtr(helpfile)) == 0) {
2857 name = rb_ivar_get(target, rb_intern("name"));
2858 rb_raise(rb_eRuntimeError, "no helpfile of `%s'",
2859 StringValuePtr(name));
2861 helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0);
2862 } else {
2863 helpfile = target;
2865 if (TYPE(helpfile) != T_STRING) {
2866 rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)");
2868 hwnd = ole_show_help(helpfile, helpcontext);
2869 if(hwnd == 0) {
2870 rb_raise(rb_eRuntimeError, "failed to open help file `%s'",
2871 StringValuePtr(helpfile));
2873 return Qnil;
2877 * call-seq:
2878 * WIN32OLE.codepage
2880 * Returns current codepage.
2881 * WIN32OLE.codepage # => WIN32OLE::CP_ACP
2883 static VALUE
2884 fole_s_get_code_page(VALUE self)
2886 return INT2FIX(cWIN32OLE_cp);
2889 static BOOL CALLBACK
2890 installed_code_page_proc(LPTSTR str) {
2891 if (strtoul(str, NULL, 10) == g_cp_to_check) {
2892 g_cp_installed = TRUE;
2893 return FALSE;
2895 return TRUE;
2898 static BOOL
2899 code_page_installed(UINT cp)
2901 g_cp_installed = FALSE;
2902 g_cp_to_check = cp;
2903 EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED);
2904 return g_cp_installed;
2908 * call-seq:
2909 * WIN32OLE.codepage = CP
2911 * Sets current codepage.
2912 * WIN32OLE.codepage = WIN32OLE::CP_UTF8
2913 * WIN32OLE.codepage = 20932
2915 static VALUE
2916 fole_s_set_code_page(VALUE self, VALUE vcp)
2918 UINT cp = FIX2INT(vcp);
2920 if (code_page_installed(cp)) {
2921 cWIN32OLE_cp = cp;
2922 } else {
2923 switch(cp) {
2924 case CP_ACP:
2925 case CP_OEMCP:
2926 case CP_MACCP:
2927 case CP_THREAD_ACP:
2928 case CP_SYMBOL:
2929 case CP_UTF7:
2930 case CP_UTF8:
2931 cWIN32OLE_cp = cp;
2932 break;
2933 default:
2934 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.");
2935 break;
2938 cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
2940 * Should this method return old codepage?
2942 return Qnil;
2946 * call-seq:
2947 * WIN32OLE.locale -> locale id.
2949 * Returns current locale id (lcid). The default locale is
2950 * LOCALE_SYSTEM_DEFAULT.
2952 * lcid = WIN32OLE.locale
2954 static VALUE
2955 fole_s_get_locale(VALUE self)
2957 return INT2FIX(cWIN32OLE_lcid);
2960 static BOOL
2961 CALLBACK installed_lcid_proc(LPTSTR str)
2963 if (strcmp(str, g_lcid_to_check) == 0) {
2964 g_lcid_installed = TRUE;
2965 return FALSE;
2967 return TRUE;
2970 static BOOL
2971 lcid_installed(LCID lcid)
2973 g_lcid_installed = FALSE;
2974 snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", lcid);
2975 EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED);
2976 return g_lcid_installed;
2980 * call-seq:
2981 * WIN32OLE.locale = lcid
2983 * Sets current locale id (lcid).
2985 * WIN32OLE.locale = 1033 # set locale English(U.S)
2986 * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
2989 static VALUE
2990 fole_s_set_locale(VALUE self, VALUE vlcid)
2992 LCID lcid = FIX2INT(vlcid);
2993 if (lcid_installed(lcid)) {
2994 cWIN32OLE_lcid = lcid;
2995 } else {
2996 switch (lcid) {
2997 case LOCALE_SYSTEM_DEFAULT:
2998 case LOCALE_USER_DEFAULT:
2999 cWIN32OLE_lcid = lcid;
3000 break;
3001 default:
3002 rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid);
3005 return Qnil;
3009 * call-seq:
3010 * WIN32OLE.create_guid
3012 * Creates GUID.
3013 * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
3015 static VALUE
3016 fole_s_create_guid(VALUE self)
3018 GUID guid;
3019 HRESULT hr;
3020 OLECHAR bstr[80];
3021 int len = 0;
3022 hr = CoCreateGuid(&guid);
3023 if (FAILED(hr)) {
3024 ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID");
3026 len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
3027 if (len == 0) {
3028 rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)");
3030 return ole_wc2vstr(bstr, FALSE);
3034 * Document-class: WIN32OLE
3036 * <code>WIN32OLE</code> objects represent OLE Automation object in Ruby.
3038 * By using WIN32OLE, you can access OLE server like VBScript.
3040 * Here is sample script.
3042 * require 'win32ole'
3044 * excel = WIN32OLE.new('Excel.Application')
3045 * excel.visible = true
3046 * workbook = excel.Workbooks.Add();
3047 * worksheet = workbook.Worksheets(1);
3048 * worksheet.Range("A1:D1").value = ["North","South","East","West"];
3049 * worksheet.Range("A2:B2").value = [5.2, 10];
3050 * worksheet.Range("C2").value = 8;
3051 * worksheet.Range("D2").value = 20;
3053 * range = worksheet.Range("A1:D2");
3054 * range.select
3055 * chart = workbook.Charts.Add;
3057 * workbook.saved = true;
3059 * excel.ActiveWorkbook.Close(0);
3060 * excel.Quit();
3062 * Unfortunately, Win32OLE doesn't support the argument passed by
3063 * reference directly.
3064 * Instead, Win32OLE provides WIN32OLE::ARGV.
3065 * If you want to get the result value of argument passed by reference,
3066 * you can use WIN32OLE::ARGV.
3068 * oleobj.method(arg1, arg2, refargv3)
3069 * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
3074 * call-seq:
3075 * WIN32OLE.new(server, [host]) -> WIN32OLE object
3077 * Returns a new WIN32OLE object(OLE Automation object).
3078 * The first argument server specifies OLE Automation server.
3079 * The first argument should be CLSID or PROGID.
3080 * If second argument host specified, then returns OLE Automation
3081 * object on host.
3083 * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object.
3084 * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
3086 static VALUE
3087 fole_initialize(int argc, VALUE *argv, VALUE self)
3089 VALUE svr_name;
3090 VALUE host;
3091 VALUE others;
3092 HRESULT hr;
3093 CLSID clsid;
3094 OLECHAR *pBuf;
3095 IDispatch *pDispatch;
3096 void *p;
3098 rb_secure(4);
3099 rb_call_super(0, 0);
3100 rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
3102 if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
3103 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
3104 StringValuePtr(svr_name));
3106 if (!NIL_P(host)) {
3107 if (rb_safe_level() > 0 && OBJ_TAINTED(host)) {
3108 rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
3109 StringValuePtr(svr_name));
3111 return ole_create_dcom(argc, argv, self);
3114 /* get CLSID from OLE server name */
3115 pBuf = ole_vstr2wc(svr_name);
3116 hr = CLSIDFromProgID(pBuf, &clsid);
3117 if(FAILED(hr)) {
3118 hr = CLSIDFromString(pBuf, &clsid);
3120 SysFreeString(pBuf);
3121 if(FAILED(hr)) {
3122 ole_raise(hr, eWIN32OLERuntimeError,
3123 "unknown OLE server: `%s'",
3124 StringValuePtr(svr_name));
3127 /* get IDispatch interface */
3128 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
3129 &IID_IDispatch, &p);
3130 pDispatch = p;
3131 if(FAILED(hr)) {
3132 ole_raise(hr, eWIN32OLERuntimeError,
3133 "failed to create WIN32OLE object from `%s'",
3134 StringValuePtr(svr_name));
3137 ole_set_member(self, pDispatch);
3138 return self;
3141 static VALUE
3142 hash2named_arg(VALUE pair, struct oleparam* pOp)
3144 unsigned int index, i;
3145 VALUE key, value;
3146 index = pOp->dp.cNamedArgs;
3148 /*---------------------------------------------
3149 the data-type of key must be String or Symbol
3150 -----------------------------------------------*/
3151 key = rb_ary_entry(pair, 0);
3152 if(TYPE(key) != T_STRING && TYPE(key) != T_SYMBOL) {
3153 /* clear name of dispatch parameters */
3154 for(i = 1; i < index + 1; i++) {
3155 SysFreeString(pOp->pNamedArgs[i]);
3157 /* clear dispatch parameters */
3158 for(i = 0; i < index; i++ ) {
3159 VariantClear(&(pOp->dp.rgvarg[i]));
3161 /* raise an exception */
3162 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
3164 if (TYPE(key) == T_SYMBOL) {
3165 key = rb_sym_to_s(key);
3168 /* pNamedArgs[0] is <method name>, so "index + 1" */
3169 pOp->pNamedArgs[index + 1] = ole_vstr2wc(key);
3171 value = rb_ary_entry(pair, 1);
3172 VariantInit(&(pOp->dp.rgvarg[index]));
3173 ole_val2variant(value, &(pOp->dp.rgvarg[index]));
3175 pOp->dp.cNamedArgs += 1;
3176 return Qnil;
3179 static VALUE
3180 set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
3182 VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV"));
3184 Check_Type(argv, T_ARRAY);
3185 rb_ary_clear(argv);
3186 while (end-- > beg) {
3187 rb_ary_push(argv, ole_variant2val(&realargs[end]));
3188 VariantClear(&realargs[end]);
3190 return argv;
3193 static VALUE
3194 ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
3196 LCID lcid = cWIN32OLE_lcid;
3197 struct oledata *pole;
3198 HRESULT hr;
3199 VALUE cmd;
3200 VALUE paramS;
3201 VALUE param;
3202 VALUE obj;
3203 VALUE v;
3205 BSTR wcmdname;
3207 DISPID DispID;
3208 DISPID* pDispID;
3209 EXCEPINFO excepinfo;
3210 VARIANT result;
3211 VARIANTARG* realargs = NULL;
3212 unsigned int argErr = 0;
3213 unsigned int i;
3214 unsigned int cNamedArgs;
3215 int n;
3216 struct oleparam op;
3217 struct olevariantdata *pvar;
3218 memset(&excepinfo, 0, sizeof(EXCEPINFO));
3220 VariantInit(&result);
3222 op.dp.rgvarg = NULL;
3223 op.dp.rgdispidNamedArgs = NULL;
3224 op.dp.cNamedArgs = 0;
3225 op.dp.cArgs = 0;
3227 rb_scan_args(argc, argv, "1*", &cmd, &paramS);
3228 if(TYPE(cmd) != T_STRING && TYPE(cmd) != T_SYMBOL) {
3229 rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
3231 if (TYPE(cmd) == T_SYMBOL) {
3232 cmd = rb_sym_to_s(cmd);
3234 OLEData_Get_Struct(self, pole);
3235 if(!pole->pDispatch) {
3236 rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
3238 if (is_bracket) {
3239 DispID = DISPID_VALUE;
3240 argc += 1;
3241 rb_ary_unshift(paramS, cmd);
3242 } else {
3243 wcmdname = ole_vstr2wc(cmd);
3244 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
3245 &wcmdname, 1, lcid, &DispID);
3246 SysFreeString(wcmdname);
3247 if(FAILED(hr)) {
3248 ole_raise(hr, eWIN32OLERuntimeError,
3249 "unknown property or method: `%s'",
3250 StringValuePtr(cmd));
3254 /* pick up last argument of method */
3255 param = rb_ary_entry(paramS, argc-2);
3257 op.dp.cNamedArgs = 0;
3259 /* if last arg is hash object */
3260 if(TYPE(param) == T_HASH) {
3261 /*------------------------------------------
3262 hash object ==> named dispatch parameters
3263 --------------------------------------------*/
3264 cNamedArgs = NUM2INT(rb_funcall(param, rb_intern("length"), 0));
3265 op.dp.cArgs = cNamedArgs + argc - 2;
3266 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
3267 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
3268 rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op);
3270 pDispID = ALLOCA_N(DISPID, cNamedArgs + 1);
3271 op.pNamedArgs[0] = ole_vstr2wc(cmd);
3272 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch,
3273 &IID_NULL,
3274 op.pNamedArgs,
3275 op.dp.cNamedArgs + 1,
3276 lcid, pDispID);
3277 for(i = 0; i < op.dp.cNamedArgs + 1; i++) {
3278 SysFreeString(op.pNamedArgs[i]);
3279 op.pNamedArgs[i] = NULL;
3281 if(FAILED(hr)) {
3282 /* clear dispatch parameters */
3283 for(i = 0; i < op.dp.cArgs; i++ ) {
3284 VariantClear(&op.dp.rgvarg[i]);
3286 ole_raise(hr, eWIN32OLERuntimeError,
3287 "failed to get named argument info: `%s'",
3288 StringValuePtr(cmd));
3290 op.dp.rgdispidNamedArgs = &(pDispID[1]);
3292 else {
3293 cNamedArgs = 0;
3294 op.dp.cArgs = argc - 1;
3295 op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
3296 if (op.dp.cArgs > 0) {
3297 op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
3300 /*--------------------------------------
3301 non hash args ==> dispatch parameters
3302 ----------------------------------------*/
3303 if(op.dp.cArgs > cNamedArgs) {
3304 realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1);
3305 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3306 n = op.dp.cArgs - i + cNamedArgs - 1;
3307 VariantInit(&realargs[n]);
3308 VariantInit(&op.dp.rgvarg[n]);
3309 param = rb_ary_entry(paramS, i-cNamedArgs);
3310 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
3311 Data_Get_Struct(param, struct olevariantdata, pvar);
3312 VariantCopy(&op.dp.rgvarg[n], &(pvar->var));
3313 } else {
3314 ole_val2variant(param, &realargs[n]);
3315 V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF;
3316 V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n];
3320 /* apparent you need to call propput, you need this */
3321 if (wFlags & DISPATCH_PROPERTYPUT) {
3322 if (op.dp.cArgs == 0)
3323 ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error");
3325 op.dp.cNamedArgs = 1;
3326 op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
3327 op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
3330 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3331 &IID_NULL, lcid, wFlags, &op.dp,
3332 &result, &excepinfo, &argErr);
3334 if (FAILED(hr)) {
3335 /* retry to call args by value */
3336 if(op.dp.cArgs >= cNamedArgs) {
3337 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3338 n = op.dp.cArgs - i + cNamedArgs - 1;
3339 param = rb_ary_entry(paramS, i-cNamedArgs);
3340 ole_val2variant(param, &op.dp.rgvarg[n]);
3342 if (hr == DISP_E_EXCEPTION) {
3343 ole_freeexceptinfo(&excepinfo);
3345 memset(&excepinfo, 0, sizeof(EXCEPINFO));
3346 VariantInit(&result);
3347 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3348 &IID_NULL, lcid, wFlags,
3349 &op.dp, &result,
3350 &excepinfo, &argErr);
3352 /* mega kludge. if a method in WORD is called and we ask
3353 * for a result when one is not returned then
3354 * hResult == DISP_E_EXCEPTION. this only happens on
3355 * functions whose DISPID > 0x8000 */
3356 if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) {
3357 if (hr == DISP_E_EXCEPTION) {
3358 ole_freeexceptinfo(&excepinfo);
3360 memset(&excepinfo, 0, sizeof(EXCEPINFO));
3361 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3362 &IID_NULL, lcid, wFlags,
3363 &op.dp, NULL,
3364 &excepinfo, &argErr);
3367 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3368 n = op.dp.cArgs - i + cNamedArgs - 1;
3369 VariantClear(&op.dp.rgvarg[n]);
3373 if (FAILED(hr)) {
3374 /* retry after converting nil to VT_EMPTY */
3375 if (op.dp.cArgs > cNamedArgs) {
3376 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3377 n = op.dp.cArgs - i + cNamedArgs - 1;
3378 param = rb_ary_entry(paramS, i-cNamedArgs);
3379 ole_val2variant2(param, &op.dp.rgvarg[n]);
3381 if (hr == DISP_E_EXCEPTION) {
3382 ole_freeexceptinfo(&excepinfo);
3384 memset(&excepinfo, 0, sizeof(EXCEPINFO));
3385 VariantInit(&result);
3386 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
3387 &IID_NULL, lcid, wFlags,
3388 &op.dp, &result,
3389 &excepinfo, &argErr);
3390 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3391 n = op.dp.cArgs - i + cNamedArgs - 1;
3392 VariantClear(&op.dp.rgvarg[n]);
3398 /* clear dispatch parameter */
3399 if(op.dp.cArgs > cNamedArgs) {
3400 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
3401 n = op.dp.cArgs - i + cNamedArgs - 1;
3402 param = rb_ary_entry(paramS, i-cNamedArgs);
3403 if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
3404 ole_val2variant(param, &realargs[n]);
3407 set_argv(realargs, cNamedArgs, op.dp.cArgs);
3409 else {
3410 for(i = 0; i < op.dp.cArgs; i++) {
3411 VariantClear(&op.dp.rgvarg[i]);
3415 if (FAILED(hr)) {
3416 v = ole_excepinfo2msg(&excepinfo);
3417 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s",
3418 StringValuePtr(cmd),
3419 StringValuePtr(v));
3421 obj = ole_variant2val(&result);
3422 VariantClear(&result);
3423 return obj;
3427 * call-seq:
3428 * WIN32OLE#invoke(method, [arg1,...]) => return value of method.
3430 * Runs OLE method.
3431 * The first argument specifies the method name of OLE Automation object.
3432 * The others specify argument of the <i>method</i>.
3433 * If you can not execute <i>method</i> directly, then use this method instead.
3435 * excel = WIN32OLE.new('Excel.Application')
3436 * excel.invoke('Quit') # => same as excel.Quit
3439 static VALUE
3440 fole_invoke(int argc, VALUE *argv, VALUE self)
3442 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
3445 static VALUE
3446 ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
3448 HRESULT hr;
3449 struct oledata *pole;
3450 unsigned int argErr = 0;
3451 EXCEPINFO excepinfo;
3452 VARIANT result;
3453 DISPPARAMS dispParams;
3454 VARIANTARG* realargs = NULL;
3455 int i, j;
3456 VALUE obj = Qnil;
3457 VALUE tp, param;
3458 VALUE v;
3459 VARTYPE vt;
3461 Check_Type(args, T_ARRAY);
3462 Check_Type(types, T_ARRAY);
3464 memset(&excepinfo, 0, sizeof(EXCEPINFO));
3465 memset(&dispParams, 0, sizeof(DISPPARAMS));
3466 VariantInit(&result);
3467 OLEData_Get_Struct(self, pole);
3469 dispParams.cArgs = RARRAY_LEN(args);
3470 dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs);
3471 realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs);
3472 for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--)
3474 VariantInit(&realargs[i]);
3475 VariantInit(&dispParams.rgvarg[i]);
3476 tp = rb_ary_entry(types, j);
3477 vt = (VARTYPE)FIX2INT(tp);
3478 V_VT(&dispParams.rgvarg[i]) = vt;
3479 param = rb_ary_entry(args, j);
3480 if (param == Qnil)
3483 V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR;
3484 V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND;
3486 else
3488 if (vt & VT_ARRAY)
3490 int ent;
3491 LPBYTE pb;
3492 short* ps;
3493 LPLONG pl;
3494 VARIANT* pv;
3495 CY *py;
3496 VARTYPE v;
3497 SAFEARRAYBOUND rgsabound[1];
3498 Check_Type(param, T_ARRAY);
3499 rgsabound[0].lLbound = 0;
3500 rgsabound[0].cElements = RARRAY_LEN(param);
3501 v = vt & ~(VT_ARRAY | VT_BYREF);
3502 V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound);
3503 V_VT(&realargs[i]) = VT_ARRAY | v;
3504 SafeArrayLock(V_ARRAY(&realargs[i]));
3505 pb = V_ARRAY(&realargs[i])->pvData;
3506 ps = V_ARRAY(&realargs[i])->pvData;
3507 pl = V_ARRAY(&realargs[i])->pvData;
3508 py = V_ARRAY(&realargs[i])->pvData;
3509 pv = V_ARRAY(&realargs[i])->pvData;
3510 for (ent = 0; ent < (int)rgsabound[0].cElements; ent++)
3512 VARIANT velem;
3513 VALUE elem = rb_ary_entry(param, ent);
3514 ole_val2variant(elem, &velem);
3515 if (v != VT_VARIANT)
3517 VariantChangeTypeEx(&velem, &velem,
3518 cWIN32OLE_lcid, 0, v);
3520 switch (v)
3522 /* 128 bits */
3523 case VT_VARIANT:
3524 *pv++ = velem;
3525 break;
3526 /* 64 bits */
3527 case VT_R8:
3528 case VT_CY:
3529 case VT_DATE:
3530 *py++ = V_CY(&velem);
3531 break;
3532 /* 16 bits */
3533 case VT_BOOL:
3534 case VT_I2:
3535 case VT_UI2:
3536 *ps++ = V_I2(&velem);
3537 break;
3538 /* 8 bites */
3539 case VT_UI1:
3540 case VT_I1:
3541 *pb++ = V_UI1(&velem);
3542 break;
3543 /* 32 bits */
3544 default:
3545 *pl++ = V_I4(&velem);
3546 break;
3549 SafeArrayUnlock(V_ARRAY(&realargs[i]));
3551 else
3553 ole_val2variant(param, &realargs[i]);
3554 if ((vt & (~VT_BYREF)) != VT_VARIANT)
3556 hr = VariantChangeTypeEx(&realargs[i], &realargs[i],
3557 cWIN32OLE_lcid, 0,
3558 (VARTYPE)(vt & (~VT_BYREF)));
3559 if (hr != S_OK)
3561 rb_raise(rb_eTypeError, "not valid value");
3565 if ((vt & VT_BYREF) || vt == VT_VARIANT)
3567 if (vt == VT_VARIANT)
3568 V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF;
3569 switch (vt & (~VT_BYREF))
3571 /* 128 bits */
3572 case VT_VARIANT:
3573 V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i];
3574 break;
3575 /* 64 bits */
3576 case VT_R8:
3577 case VT_CY:
3578 case VT_DATE:
3579 V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]);
3580 break;
3581 /* 16 bits */
3582 case VT_BOOL:
3583 case VT_I2:
3584 case VT_UI2:
3585 V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]);
3586 break;
3587 /* 8 bites */
3588 case VT_UI1:
3589 case VT_I1:
3590 V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]);
3591 break;
3592 /* 32 bits */
3593 default:
3594 V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]);
3595 break;
3598 else
3600 /* copy 64 bits of data */
3601 V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]);
3606 if (dispkind & DISPATCH_PROPERTYPUT) {
3607 dispParams.cNamedArgs = 1;
3608 dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
3609 dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
3612 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid),
3613 &IID_NULL, cWIN32OLE_lcid,
3614 dispkind,
3615 &dispParams, &result,
3616 &excepinfo, &argErr);
3618 if (FAILED(hr)) {
3619 v = ole_excepinfo2msg(&excepinfo);
3620 ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s",
3621 NUM2INT(dispid),
3622 StringValuePtr(v));
3625 /* clear dispatch parameter */
3626 if(dispParams.cArgs > 0) {
3627 set_argv(realargs, 0, dispParams.cArgs);
3630 obj = ole_variant2val(&result);
3631 VariantClear(&result);
3632 return obj;
3636 * call-seq:
3637 * WIN32OLE#_invoke(dispid, args, types)
3639 * Runs the early binding method.
3640 * The 1st argument specifies dispatch ID,
3641 * the 2nd argument specifies the array of arguments,
3642 * the 3rd argument specifies the array of the type of arguments.
3644 * excel = WIN32OLE.new('Excel.Application')
3645 * excel._invoke(302, [], []) # same effect as excel.Quit
3647 static VALUE
3648 fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
3650 return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD);
3654 * call-seq:
3655 * WIN32OLE#_getproperty(dispid, args, types)
3657 * Runs the early binding method to get property.
3658 * The 1st argument specifies dispatch ID,
3659 * the 2nd argument specifies the array of arguments,
3660 * the 3rd argument specifies the array of the type of arguments.
3662 * excel = WIN32OLE.new('Excel.Application')
3663 * puts excel._getproperty(558, [], []) # same effect as puts excel.visible
3665 static VALUE
3666 fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
3668 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET);
3672 * call-seq:
3673 * WIN32OLE#_setproperty(dispid, args, types)
3675 * Runs the early binding method to set property.
3676 * The 1st argument specifies dispatch ID,
3677 * the 2nd argument specifies the array of arguments,
3678 * the 3rd argument specifies the array of the type of arguments.
3680 * excel = WIN32OLE.new('Excel.Application')
3681 * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true
3683 static VALUE
3684 fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
3686 return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT);
3690 * call-seq:
3691 * WIN32OLE[a1, a2, ...]=val
3693 * Sets the value to WIN32OLE object specified by a1, a2, ...
3695 * dict = WIN32OLE.new('Scripting.Dictionary')
3696 * dict.add('ruby', 'RUBY')
3697 * dict['ruby'] = 'Ruby'
3698 * puts dict['ruby'] # => 'Ruby'
3700 * Remark: You can not use this method to set the property value.
3702 * excel = WIN32OLE.new('Excel.Application')
3703 * # excel['Visible'] = true # This is error !!!
3704 * excel.Visible = true # You should to use this style to set the property.
3707 static VALUE
3708 fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
3710 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE);
3714 * call-seq:
3715 * WIN32OLE.setproperty('property', [arg1, arg2,...] val)
3717 * Sets property of OLE object.
3718 * When you want to set property with argument, you can use this method.
3720 * excel = WIN32OLE.new('Excel.Application')
3721 * excel.Visible = true
3722 * book = excel.workbooks.add
3723 * sheet = book.worksheets(1)
3724 * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10.
3726 static VALUE
3727 fole_setproperty(int argc, VALUE *argv, VALUE self)
3729 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE);
3733 * call-seq:
3734 * WIN32OLE[a1,a2,...]
3736 * Returns the value of Collection specified by a1, a2,....
3738 * dict = WIN32OLE.new('Scripting.Dictionary')
3739 * dict.add('ruby', 'Ruby')
3740 * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')')
3742 * Remark: You can not use this method to get the property.
3743 * excel = WIN32OLE.new('Excel.Application')
3744 * # puts excel['Visible'] This is error !!!
3745 * puts excel.Visible # You should to use this style to get the property.
3748 static VALUE
3749 fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self)
3751 return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE);
3754 static VALUE
3755 ole_propertyput(VALUE self, VALUE property, VALUE value)
3757 struct oledata *pole;
3758 unsigned argErr;
3759 unsigned int index;
3760 HRESULT hr;
3761 EXCEPINFO excepinfo;
3762 DISPID dispID = DISPID_VALUE;
3763 DISPID dispIDParam = DISPID_PROPERTYPUT;
3764 USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF;
3765 DISPPARAMS dispParams;
3766 VARIANTARG propertyValue[2];
3767 OLECHAR* pBuf[1];
3768 VALUE v;
3769 LCID lcid = cWIN32OLE_lcid;
3770 dispParams.rgdispidNamedArgs = &dispIDParam;
3771 dispParams.rgvarg = propertyValue;
3772 dispParams.cNamedArgs = 1;
3773 dispParams.cArgs = 1;
3775 VariantInit(&propertyValue[0]);
3776 VariantInit(&propertyValue[1]);
3777 memset(&excepinfo, 0, sizeof(excepinfo));
3779 OLEData_Get_Struct(self, pole);
3781 /* get ID from property name */
3782 pBuf[0] = ole_vstr2wc(property);
3783 hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL,
3784 pBuf, 1, lcid, &dispID);
3785 SysFreeString(pBuf[0]);
3786 pBuf[0] = NULL;
3788 if(FAILED(hr)) {
3789 ole_raise(hr, eWIN32OLERuntimeError,
3790 "unknown property or method: `%s'",
3791 StringValuePtr(property));
3793 /* set property value */
3794 ole_val2variant(value, &propertyValue[0]);
3795 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL,
3796 lcid, wFlags, &dispParams,
3797 NULL, &excepinfo, &argErr);
3799 for(index = 0; index < dispParams.cArgs; ++index) {
3800 VariantClear(&propertyValue[index]);
3802 if (FAILED(hr)) {
3803 v = ole_excepinfo2msg(&excepinfo);
3804 ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s",
3805 StringValuePtr(property),
3806 StringValuePtr(v));
3808 return Qnil;
3812 * call-seq:
3813 * WIN32OLE#ole_free
3815 * invokes Release method of Dispatch interface of WIN32OLE object.
3816 * Usually, you do not need to call this method because Release method
3817 * called automatically when WIN32OLE object garbaged.
3820 static VALUE
3821 fole_free(VALUE self)
3823 struct oledata *pole;
3824 rb_secure(4);
3825 OLEData_Get_Struct(self, pole);
3826 OLE_FREE(pole->pDispatch);
3827 pole->pDispatch = NULL;
3828 return Qnil;
3831 static VALUE
3832 ole_each_sub(VALUE pEnumV)
3834 VARIANT variant;
3835 VALUE obj = Qnil;
3836 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
3837 VariantInit(&variant);
3838 while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) {
3839 obj = ole_variant2val(&variant);
3840 VariantClear(&variant);
3841 VariantInit(&variant);
3842 rb_yield(obj);
3844 return Qnil;
3847 static VALUE
3848 ole_ienum_free(VALUE pEnumV)
3850 IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
3851 OLE_RELEASE(pEnum);
3852 return Qnil;
3856 * call-seq:
3857 * WIN32OLE#each {|i|...}
3859 * Iterates over each item of OLE collection which has IEnumVARIANT interface.
3861 * excel = WIN32OLE.new('Excel.Application')
3862 * book = excel.workbooks.add
3863 * sheets = book.worksheets(1)
3864 * cells = sheets.cells("A1:A5")
3865 * cells.each do |cell|
3866 * cell.value = 10
3867 * end
3869 static VALUE
3870 fole_each(VALUE self)
3872 LCID lcid = cWIN32OLE_lcid;
3874 struct oledata *pole;
3876 unsigned int argErr;
3877 EXCEPINFO excepinfo;
3878 DISPPARAMS dispParams;
3879 VARIANT result;
3880 HRESULT hr;
3881 IEnumVARIANT *pEnum = NULL;
3882 void *p;
3884 RETURN_ENUMERATOR(self, 0, 0);
3886 VariantInit(&result);
3887 dispParams.rgvarg = NULL;
3888 dispParams.rgdispidNamedArgs = NULL;
3889 dispParams.cNamedArgs = 0;
3890 dispParams.cArgs = 0;
3891 memset(&excepinfo, 0, sizeof(excepinfo));
3893 OLEData_Get_Struct(self, pole);
3894 hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM,
3895 &IID_NULL, lcid,
3896 DISPATCH_METHOD | DISPATCH_PROPERTYGET,
3897 &dispParams, &result,
3898 &excepinfo, &argErr);
3900 if (FAILED(hr)) {
3901 VariantClear(&result);
3902 ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface");
3905 if (V_VT(&result) == VT_UNKNOWN) {
3906 hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result),
3907 &IID_IEnumVARIANT,
3908 &p);
3909 pEnum = p;
3910 } else if (V_VT(&result) == VT_DISPATCH) {
3911 hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result),
3912 &IID_IEnumVARIANT,
3913 &p);
3914 pEnum = p;
3916 if (FAILED(hr) || !pEnum) {
3917 VariantClear(&result);
3918 ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface");
3921 VariantClear(&result);
3922 rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
3923 return Qnil;
3927 * call-seq:
3928 * WIN32OLE#method_missing(id [,arg1, arg2, ...])
3930 * Calls WIN32OLE#invoke method.
3932 static VALUE
3933 fole_missing(int argc, VALUE *argv, VALUE self)
3935 ID id;
3936 const char* mname;
3937 int n;
3938 id = rb_to_id(argv[0]);
3939 mname = rb_id2name(id);
3940 if(!mname) {
3941 rb_raise(rb_eRuntimeError, "fail: unknown method or property");
3943 n = strlen(mname);
3944 if(mname[n-1] == '=') {
3945 argv[0] = rb_enc_str_new(mname, n-1, cWIN32OLE_enc);
3947 return ole_propertyput(self, argv[0], argv[1]);
3949 else {
3950 argv[0] = rb_enc_str_new(mname, n, cWIN32OLE_enc);
3951 return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
3955 static VALUE
3956 ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name)
3958 HRESULT hr;
3959 TYPEATTR *pTypeAttr;
3960 BSTR bstr;
3961 FUNCDESC *pFuncDesc;
3962 WORD i;
3963 VALUE fname;
3964 VALUE method = Qnil;
3965 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
3966 if (FAILED(hr)) {
3967 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
3969 for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) {
3970 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
3971 if (FAILED(hr))
3972 continue;
3974 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
3975 &bstr, NULL, NULL, NULL);
3976 if (FAILED(hr)) {
3977 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
3978 continue;
3980 fname = WC2VSTR(bstr);
3981 if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) {
3982 olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname);
3983 method = self;
3985 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
3986 pFuncDesc=NULL;
3988 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
3989 return method;
3992 static VALUE
3993 olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
3995 HRESULT hr;
3996 TYPEATTR *pTypeAttr;
3997 WORD i;
3998 HREFTYPE href;
3999 ITypeInfo *pRefTypeInfo;
4000 VALUE method = Qnil;
4001 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4002 if (FAILED(hr)) {
4003 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4005 method = ole_method_sub(self, 0, pTypeInfo, name);
4006 if (method != Qnil) {
4007 return method;
4009 for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){
4010 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
4011 if(FAILED(hr))
4012 continue;
4013 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
4014 if (FAILED(hr))
4015 continue;
4016 method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name);
4017 OLE_RELEASE(pRefTypeInfo);
4019 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4020 return method;
4023 static VALUE
4024 ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask)
4026 HRESULT hr;
4027 TYPEATTR *pTypeAttr;
4028 BSTR bstr;
4029 char *pstr;
4030 FUNCDESC *pFuncDesc;
4031 VALUE method;
4032 WORD i;
4033 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4034 if (FAILED(hr)) {
4035 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4037 for(i = 0; i < pTypeAttr->cFuncs; i++) {
4038 pstr = NULL;
4039 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
4040 if (FAILED(hr))
4041 continue;
4043 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
4044 &bstr, NULL, NULL, NULL);
4045 if (FAILED(hr)) {
4046 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
4047 continue;
4049 if(pFuncDesc->invkind & mask) {
4050 method = folemethod_s_allocate(cWIN32OLE_METHOD);
4051 olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo,
4052 i, WC2VSTR(bstr));
4053 rb_ary_push(methods, method);
4055 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
4056 pFuncDesc=NULL;
4058 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4060 return methods;
4063 static VALUE
4064 ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
4066 HRESULT hr;
4067 TYPEATTR *pTypeAttr;
4068 WORD i;
4069 HREFTYPE href;
4070 ITypeInfo *pRefTypeInfo;
4071 VALUE methods = rb_ary_new();
4072 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
4073 if (FAILED(hr)) {
4074 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
4077 ole_methods_sub(0, pTypeInfo, methods, mask);
4078 for(i=0; i < pTypeAttr->cImplTypes; i++){
4079 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
4080 if(FAILED(hr))
4081 continue;
4082 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
4083 if (FAILED(hr))
4084 continue;
4085 ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask);
4086 OLE_RELEASE(pRefTypeInfo);
4088 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
4089 return methods;
4092 static HRESULT
4093 typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti)
4095 ITypeInfo *pTypeInfo;
4096 ITypeLib *pTypeLib;
4097 BSTR bstr;
4098 VALUE type;
4099 UINT i;
4100 UINT count;
4101 LCID lcid = cWIN32OLE_lcid;
4102 HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
4103 0, lcid, &pTypeInfo);
4104 if(FAILED(hr)) {
4105 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
4107 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo,
4109 &bstr,
4110 NULL, NULL, NULL);
4111 type = WC2VSTR(bstr);
4112 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
4113 OLE_RELEASE(pTypeInfo);
4114 if (FAILED(hr)) {
4115 ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib");
4117 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
4118 for (i = 0; i < count; i++) {
4119 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
4120 &bstr, NULL, NULL, NULL);
4121 if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) {
4122 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
4123 if (SUCCEEDED(hr)) {
4124 *ppti = pTypeInfo;
4125 break;
4129 OLE_RELEASE(pTypeLib);
4130 return hr;
4133 static VALUE
4134 ole_methods(VALUE self, int mask)
4136 ITypeInfo *pTypeInfo;
4137 HRESULT hr;
4138 VALUE methods;
4139 struct oledata *pole;
4141 OLEData_Get_Struct(self, pole);
4142 methods = rb_ary_new();
4144 hr = typeinfo_from_ole(pole, &pTypeInfo);
4145 if(FAILED(hr))
4146 return methods;
4147 rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask));
4148 OLE_RELEASE(pTypeInfo);
4149 return methods;
4153 * call-seq:
4154 * WIN32OLE#ole_methods
4156 * Returns the array of WIN32OLE_METHOD object.
4157 * The element is OLE method of WIN32OLE object.
4159 * excel = WIN32OLE.new('Excel.Application')
4160 * methods = excel.ole_methods
4163 static VALUE
4164 fole_methods(VALUE self)
4166 return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
4170 * call-seq:
4171 * WIN32OLE#ole_get_methods
4173 * Returns the array of WIN32OLE_METHOD object .
4174 * The element of the array is property (gettable) of WIN32OLE object.
4176 * excel = WIN32OLE.new('Excel.Application')
4177 * properties = excel.ole_get_methods
4179 static VALUE
4180 fole_get_methods(VALUE self)
4182 return ole_methods( self, INVOKE_PROPERTYGET);
4186 * call-seq:
4187 * WIN32OLE#ole_put_methods
4189 * Returns the array of WIN32OLE_METHOD object .
4190 * The element of the array is property (settable) of WIN32OLE object.
4192 * excel = WIN32OLE.new('Excel.Application')
4193 * properties = excel.ole_put_methods
4195 static VALUE
4196 fole_put_methods(VALUE self)
4198 return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF);
4202 * call-seq:
4203 * WIN32OLE#ole_func_methods
4205 * Returns the array of WIN32OLE_METHOD object .
4206 * The element of the array is property (settable) of WIN32OLE object.
4208 * excel = WIN32OLE.new('Excel.Application')
4209 * properties = excel.ole_func_methods
4212 static VALUE
4213 fole_func_methods(VALUE self)
4215 return ole_methods( self, INVOKE_FUNC);
4218 static VALUE
4219 ole_type_from_itypeinfo(ITypeInfo *pTypeInfo)
4221 ITypeLib *pTypeLib;
4222 VALUE type = Qnil;
4223 HRESULT hr;
4224 unsigned int index;
4225 BSTR bstr;
4227 hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index );
4228 if(FAILED(hr)) {
4229 return Qnil;
4231 hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index,
4232 &bstr, NULL, NULL, NULL);
4233 OLE_RELEASE(pTypeLib);
4234 if (FAILED(hr)) {
4235 return Qnil;
4237 type = foletype_s_allocate(cWIN32OLE_TYPE);
4238 oletype_set_member(type, pTypeInfo, WC2VSTR(bstr));
4239 return type;
4243 * call-seq:
4244 * WIN32OLE#ole_type
4246 * Returns WIN32OLE_TYPE object.
4248 * excel = WIN32OLE.new('Excel.Application')
4249 * tobj = excel.ole_type
4251 static VALUE
4252 fole_type(VALUE self)
4254 ITypeInfo *pTypeInfo;
4255 HRESULT hr;
4256 struct oledata *pole;
4257 LCID lcid = cWIN32OLE_lcid;
4258 VALUE type = Qnil;
4260 OLEData_Get_Struct(self, pole);
4262 hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo );
4263 if(FAILED(hr)) {
4264 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
4266 type = ole_type_from_itypeinfo(pTypeInfo);
4267 OLE_RELEASE(pTypeInfo);
4268 if (type == Qnil) {
4269 rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo");
4271 return type;
4274 static VALUE
4275 make_oletypelib_obj(VALUE guid, VALUE major_version, VALUE minor_version)
4277 VALUE args = rb_ary_new();
4278 rb_ary_push(args, guid);
4279 rb_ary_push(args, major_version);
4280 rb_ary_push(args, minor_version);
4281 return rb_apply(cWIN32OLE_TYPELIB, rb_intern("new"), args);
4284 static VALUE
4285 ole_typelib_from_itypelib(ITypeLib *pTypeLib)
4287 TLIBATTR *pTLibAttr;
4288 OLECHAR bstr[80];
4289 VALUE guid = Qnil;
4290 VALUE major;
4291 VALUE minor;
4292 int len = 0;
4293 HRESULT hr = S_OK;
4294 hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, &pTLibAttr);
4295 if (FAILED(hr)) {
4296 return Qnil;
4298 len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
4299 if (len > 3) {
4300 guid = ole_wc2vstr(bstr, FALSE);
4302 major = INT2NUM(pTLibAttr->wMajorVerNum);
4303 minor = INT2NUM(pTLibAttr->wMinorVerNum);
4304 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
4305 if (guid == Qnil) {
4306 return Qnil;
4308 return make_oletypelib_obj(guid, major, minor);
4312 static VALUE
4313 ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
4315 HRESULT hr;
4316 ITypeLib *pTypeLib;
4317 unsigned int index;
4318 VALUE retval = Qnil;
4320 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
4321 if(FAILED(hr)) {
4322 return Qnil;
4324 retval = ole_typelib_from_itypelib(pTypeLib);
4325 OLE_RELEASE(pTypeLib);
4326 return retval;
4330 * call-seq:
4331 * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object
4333 * Returns the WIN32OLE_TYPELIB object. The object represents the
4334 * type library which contains the WIN32OLE object.
4336 * excel = WIN32OLE.new('Excel.Application')
4337 * tlib = excel.ole_typelib
4338 * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library'
4340 static VALUE
4341 fole_typelib(VALUE self)
4343 struct oledata *pole;
4344 HRESULT hr;
4345 ITypeInfo *pTypeInfo;
4346 LCID lcid = cWIN32OLE_lcid;
4347 VALUE vtlib = Qnil;
4349 OLEData_Get_Struct(self, pole);
4350 hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
4351 0, lcid, &pTypeInfo);
4352 if(FAILED(hr)) {
4353 ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo");
4355 vtlib = ole_typelib_from_itypeinfo(pTypeInfo);
4356 OLE_RELEASE(pTypeInfo);
4357 if (vtlib == Qnil) {
4358 rb_raise(rb_eRuntimeError, "failed to get type library info.");
4360 return vtlib;
4364 * call-seq:
4365 * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object
4367 * Returns WIN32OLE object for a specific dispatch or dual
4368 * interface specified by iid.
4370 * ie = WIN32OLE.new('InternetExplorer.Application')
4371 * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp
4373 static VALUE
4374 fole_query_interface(VALUE self, VALUE str_iid)
4376 HRESULT hr;
4377 OLECHAR *pBuf;
4378 IID iid;
4379 struct oledata *pole;
4380 IDispatch *pDispatch;
4381 void *p;
4383 pBuf = ole_vstr2wc(str_iid);
4384 hr = CLSIDFromString(pBuf, &iid);
4385 SysFreeString(pBuf);
4386 if(FAILED(hr)) {
4387 ole_raise(hr, eWIN32OLERuntimeError,
4388 "invalid iid: `%s'",
4389 StringValuePtr(str_iid));
4392 OLEData_Get_Struct(self, pole);
4393 if(!pole->pDispatch) {
4394 rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
4397 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid,
4398 &p);
4399 if(FAILED(hr)) {
4400 ole_raise(hr, eWIN32OLERuntimeError,
4401 "failed to get interface `%s'",
4402 StringValuePtr(str_iid));
4405 pDispatch = p;
4406 return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
4410 * call-seq:
4411 * WIN32OLE#ole_respond_to?(method) -> true or false
4413 * Returns true when OLE object has OLE method, otherwise returns false.
4415 * ie = WIN32OLE.new('InternetExplorer.Application')
4416 * ie.ole_respond_to?("gohome") => true
4418 static VALUE
4419 fole_respond_to(VALUE self, VALUE method)
4421 struct oledata *pole;
4422 BSTR wcmdname;
4423 DISPID DispID;
4424 HRESULT hr;
4425 rb_secure(4);
4426 if(TYPE(method) != T_STRING && TYPE(method) != T_SYMBOL) {
4427 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
4429 if (TYPE(method) == T_SYMBOL) {
4430 method = rb_sym_to_s(method);
4432 OLEData_Get_Struct(self, pole);
4433 wcmdname = ole_vstr2wc(method);
4434 hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
4435 &wcmdname, 1, cWIN32OLE_lcid, &DispID);
4436 SysFreeString(wcmdname);
4437 return SUCCEEDED(hr) ? Qtrue : Qfalse;
4440 static HRESULT
4441 ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
4443 HRESULT hr;
4444 ITypeLib *pTypeLib;
4445 UINT i;
4447 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
4448 if (FAILED(hr)) {
4449 return hr;
4452 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
4453 name, helpstr,
4454 helpcontext, helpfile);
4455 if (FAILED(hr)) {
4456 OLE_RELEASE(pTypeLib);
4457 return hr;
4459 OLE_RELEASE(pTypeLib);
4460 return hr;
4463 static VALUE
4464 ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
4466 HRESULT hr;
4467 BSTR bstr;
4468 ITypeInfo *pRefTypeInfo;
4469 VALUE type = Qnil;
4471 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
4472 V_UNION1(pTypeDesc, hreftype),
4473 &pRefTypeInfo);
4474 if(FAILED(hr))
4475 return Qnil;
4476 hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL);
4477 if(FAILED(hr)) {
4478 OLE_RELEASE(pRefTypeInfo);
4479 return Qnil;
4481 OLE_RELEASE(pRefTypeInfo);
4482 type = WC2VSTR(bstr);
4483 if(typedetails != Qnil)
4484 rb_ary_push(typedetails, type);
4485 return type;
4488 static VALUE
4489 ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
4491 TYPEDESC *p = pTypeDesc;
4492 VALUE type = rb_str_new2("");
4494 if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) {
4495 p = V_UNION1(p, lptdesc);
4496 type = ole_typedesc2val(pTypeInfo, p, typedetails);
4498 return type;
4501 static VALUE
4502 ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
4504 VALUE str;
4505 VALUE typestr = Qnil;
4506 switch(pTypeDesc->vt) {
4507 case VT_I2:
4508 typestr = rb_str_new2("I2");
4509 break;
4510 case VT_I4:
4511 typestr = rb_str_new2("I4");
4512 break;
4513 case VT_R4:
4514 typestr = rb_str_new2("R4");
4515 break;
4516 case VT_R8:
4517 typestr = rb_str_new2("R8");
4518 break;
4519 case VT_CY:
4520 typestr = rb_str_new2("CY");
4521 break;
4522 case VT_DATE:
4523 typestr = rb_str_new2("DATE");
4524 break;
4525 case VT_BSTR:
4526 typestr = rb_str_new2("BSTR");
4527 break;
4528 case VT_BOOL:
4529 typestr = rb_str_new2("BOOL");
4530 break;
4531 case VT_VARIANT:
4532 typestr = rb_str_new2("VARIANT");
4533 break;
4534 case VT_DECIMAL:
4535 typestr = rb_str_new2("DECIMAL");
4536 break;
4537 case VT_I1:
4538 typestr = rb_str_new2("I1");
4539 break;
4540 case VT_UI1:
4541 typestr = rb_str_new2("UI1");
4542 break;
4543 case VT_UI2:
4544 typestr = rb_str_new2("UI2");
4545 break;
4546 case VT_UI4:
4547 typestr = rb_str_new2("UI4");
4548 break;
4549 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
4550 case VT_I8:
4551 typestr = rb_str_new2("I8");
4552 break;
4553 case VT_UI8:
4554 typestr = rb_str_new2("UI8");
4555 break;
4556 #endif
4557 case VT_INT:
4558 typestr = rb_str_new2("INT");
4559 break;
4560 case VT_UINT:
4561 typestr = rb_str_new2("UINT");
4562 break;
4563 case VT_VOID:
4564 typestr = rb_str_new2("VOID");
4565 break;
4566 case VT_HRESULT:
4567 typestr = rb_str_new2("HRESULT");
4568 break;
4569 case VT_PTR:
4570 typestr = rb_str_new2("PTR");
4571 if(typedetails != Qnil)
4572 rb_ary_push(typedetails, typestr);
4573 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
4574 case VT_SAFEARRAY:
4575 typestr = rb_str_new2("SAFEARRAY");
4576 if(typedetails != Qnil)
4577 rb_ary_push(typedetails, typestr);
4578 return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
4579 case VT_CARRAY:
4580 typestr = rb_str_new2("CARRAY");
4581 break;
4582 case VT_USERDEFINED:
4583 typestr = rb_str_new2("USERDEFINED");
4584 if (typedetails != Qnil)
4585 rb_ary_push(typedetails, typestr);
4586 str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails);
4587 if (str != Qnil) {
4588 return str;
4590 return typestr;
4591 case VT_UNKNOWN:
4592 typestr = rb_str_new2("UNKNOWN");
4593 break;
4594 case VT_DISPATCH:
4595 typestr = rb_str_new2("DISPATCH");
4596 break;
4597 case VT_ERROR:
4598 typestr = rb_str_new2("ERROR");
4599 break;
4600 case VT_LPWSTR:
4601 typestr = rb_str_new2("LPWSTR");
4602 break;
4603 case VT_LPSTR:
4604 typestr = rb_str_new2("LPSTR");
4605 break;
4606 default:
4607 typestr = rb_str_new2("Unknown Type ");
4608 rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10));
4609 break;
4611 if (typedetails != Qnil)
4612 rb_ary_push(typedetails, typestr);
4613 return typestr;
4617 * call-seq:
4618 * WIN32OLE#ole_method_help(method)
4620 * Returns WIN32OLE_METHOD object corresponding with method
4621 * specified by 1st argument.
4623 * excel = WIN32OLE.new('Excel.Application')
4624 * method = excel.ole_method_help('Quit')
4627 static VALUE
4628 fole_method_help(VALUE self, VALUE cmdname)
4630 ITypeInfo *pTypeInfo;
4631 HRESULT hr;
4632 struct oledata *pole;
4633 VALUE method, obj;
4635 Check_SafeStr(cmdname);
4636 OLEData_Get_Struct(self, pole);
4637 hr = typeinfo_from_ole(pole, &pTypeInfo);
4638 if(FAILED(hr))
4639 ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo");
4640 method = folemethod_s_allocate(cWIN32OLE_METHOD);
4641 obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname);
4642 OLE_RELEASE(pTypeInfo);
4643 if (obj == Qnil)
4644 rb_raise(eWIN32OLERuntimeError, "not found %s",
4645 StringValuePtr(cmdname));
4646 return obj;
4650 * call-seq:
4651 * WIN32OLE#ole_activex_initialize() -> Qnil
4653 * Initialize WIN32OLE object(ActiveX Control) by calling
4654 * IPersistMemory::InitNew.
4656 * Before calling OLE method, some kind of the ActiveX controls
4657 * created with MFC should be initialized by calling
4658 * IPersistXXX::InitNew.
4660 * If and only if you received the exception "HRESULT error code:
4661 * 0x8000ffff catastrophic failure", try this method before
4662 * invoking any ole_method.
4664 * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control")
4665 * obj.ole_activex_initialize
4666 * obj.method(...)
4669 static VALUE
4670 fole_activex_initialize(VALUE self)
4672 struct oledata *pole;
4673 IPersistMemory *pPersistMemory;
4674 void *p;
4676 HRESULT hr = S_OK;
4678 OLEData_Get_Struct(self, pole);
4680 hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p);
4681 pPersistMemory = p;
4682 if (SUCCEEDED(hr)) {
4683 hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory);
4684 OLE_RELEASE(pPersistMemory);
4685 if (SUCCEEDED(hr)) {
4686 return Qnil;
4690 if (FAILED(hr)) {
4691 ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control");
4694 return Qnil;
4698 * call-seq:
4699 * WIN32OLE_TYPE.ole_classes(typelib)
4701 * Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library.
4702 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead.
4704 static VALUE
4705 foletype_s_ole_classes(VALUE self, VALUE typelib)
4707 VALUE obj;
4710 rb_warn("%s is obsolete; use %s instead.",
4711 "WIN32OLE_TYPE.ole_classes",
4712 "WIN32OLE_TYPELIB.new(typelib).ole_types");
4714 obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib);
4715 return rb_funcall(obj, rb_intern("ole_types"), 0);
4719 * call-seq:
4720 * WIN32OLE_TYPE.typelibs
4722 * Returns array of type libraries.
4723 * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead.
4726 static VALUE
4727 foletype_s_typelibs(VALUE self)
4730 rb_warn("%s is obsolete. use %s instead.",
4731 "WIN32OLE_TYPE.typelibs",
4732 "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}");
4734 return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}");
4738 * call-seq:
4739 * WIN32OLE_TYPE.progids
4741 * Returns array of ProgID.
4743 static VALUE
4744 foletype_s_progids(VALUE self)
4746 HKEY hclsids, hclsid;
4747 DWORD i;
4748 LONG err;
4749 VALUE clsid;
4750 VALUE v = rb_str_new2("");
4751 VALUE progids = rb_ary_new();
4753 err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids);
4754 if(err != ERROR_SUCCESS) {
4755 return progids;
4757 for(i = 0; ; i++) {
4758 clsid = reg_enum_key(hclsids, i);
4759 if (clsid == Qnil)
4760 break;
4761 err = reg_open_vkey(hclsids, clsid, &hclsid);
4762 if (err != ERROR_SUCCESS)
4763 continue;
4764 if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil)
4765 rb_ary_push(progids, v);
4766 if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil)
4767 rb_ary_push(progids, v);
4768 RegCloseKey(hclsid);
4770 RegCloseKey(hclsids);
4771 return progids;
4774 static VALUE
4775 foletype_s_allocate(VALUE klass)
4777 struct oletypedata *poletype;
4778 VALUE obj;
4779 ole_initialize();
4780 obj = Data_Make_Struct(klass,struct oletypedata,0,oletype_free,poletype);
4781 poletype->pTypeInfo = NULL;
4782 return obj;
4785 static VALUE
4786 oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
4788 struct oletypedata *ptype;
4789 Data_Get_Struct(self, struct oletypedata, ptype);
4790 rb_ivar_set(self, rb_intern("name"), name);
4791 ptype->pTypeInfo = pTypeInfo;
4792 if(pTypeInfo) OLE_ADDREF(pTypeInfo);
4793 return self;
4796 static VALUE
4797 oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
4800 long count;
4801 int i;
4802 HRESULT hr;
4803 BSTR bstr;
4804 VALUE typelib;
4805 ITypeInfo *pTypeInfo;
4807 VALUE found = Qfalse;
4809 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
4810 for (i = 0; i < count && found == Qfalse; i++) {
4811 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
4812 if (FAILED(hr))
4813 continue;
4814 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
4815 &bstr, NULL, NULL, NULL);
4816 if (FAILED(hr))
4817 continue;
4818 typelib = WC2VSTR(bstr);
4819 if (rb_str_cmp(oleclass, typelib) == 0) {
4820 oletype_set_member(self, pTypeInfo, typelib);
4821 found = Qtrue;
4823 OLE_RELEASE(pTypeInfo);
4825 return found;
4829 * Document-class: WIN32OLE_TYPELIB
4831 * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information.
4835 static VALUE
4836 oletypelib_set_member(VALUE self, VALUE typelib, VALUE guid, VALUE version)
4838 rb_ivar_set(self, rb_intern("name"), typelib);
4839 rb_ivar_set(self, rb_intern("guid"), guid);
4840 rb_ivar_set(self, rb_intern("version"), version);
4841 return self;
4845 * call-seq:
4847 * WIN32OLE_TYPELIB.typelibs
4849 * Returns the array of WIN32OLE_TYPELIB object.
4851 * tlibs = WIN32OLE_TYPELIB.typelibs
4854 static VALUE
4855 foletypelib_s_typelibs(VALUE self)
4857 HKEY htypelib, hguid;
4858 DWORD i, j;
4859 LONG err;
4860 VALUE guid;
4861 VALUE version;
4862 VALUE name = Qnil;
4863 VALUE typelibs = rb_ary_new();
4864 VALUE typelib = Qnil;
4866 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
4867 if(err != ERROR_SUCCESS) {
4868 return typelibs;
4870 for(i = 0; ; i++) {
4871 guid = reg_enum_key(htypelib, i);
4872 if (guid == Qnil)
4873 break;
4874 err = reg_open_vkey(htypelib, guid, &hguid);
4875 if (err != ERROR_SUCCESS)
4876 continue;
4877 for(j = 0; ; j++) {
4878 version = reg_enum_key(hguid, j);
4879 if (version == Qnil)
4880 break;
4881 if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) {
4882 typelib = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("allocate"), 0);
4883 oletypelib_set_member(typelib, name, guid, version);
4884 rb_ary_push(typelibs, typelib);
4887 RegCloseKey(hguid);
4889 RegCloseKey(htypelib);
4890 return typelibs;
4893 static VALUE
4894 make_version_str(VALUE major, VALUE minor)
4896 VALUE version_str = Qnil;
4897 VALUE minor_str = Qnil;
4898 if (major == Qnil) {
4899 return Qnil;
4901 version_str = rb_String(major);
4902 if (minor != Qnil) {
4903 minor_str = rb_String(minor);
4904 rb_str_cat2(version_str, ".");
4905 rb_str_append(version_str, minor_str);
4907 return version_str;
4910 static VALUE
4911 oletypelib_search_registry2(VALUE self, VALUE args)
4913 HKEY htypelib, hguid, hversion;
4914 double fver;
4915 DWORD j;
4916 LONG err;
4917 VALUE found = Qfalse;
4918 VALUE tlib;
4919 VALUE ver;
4920 VALUE version_str;
4921 VALUE version = Qnil;
4922 VALUE typelib = Qnil;
4924 VALUE guid = rb_ary_entry(args, 0);
4925 version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2));
4927 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
4928 if(err != ERROR_SUCCESS) {
4929 return Qfalse;
4931 err = reg_open_vkey(htypelib, guid, &hguid);
4932 if (err != ERROR_SUCCESS) {
4933 RegCloseKey(htypelib);
4934 return Qfalse;
4936 if (version_str != Qnil) {
4937 err = reg_open_vkey(hguid, version_str, &hversion);
4938 if (err == ERROR_SUCCESS) {
4939 tlib = reg_get_val(hversion, NULL);
4940 if (tlib != Qnil) {
4941 typelib = tlib;
4942 version = version_str;
4945 RegCloseKey(hversion);
4946 } else {
4947 fver = 0.0;
4948 for(j = 0; ;j++) {
4949 ver = reg_enum_key(hguid, j);
4950 if (ver == Qnil)
4951 break;
4952 err = reg_open_vkey(hguid, ver, &hversion);
4953 if (err != ERROR_SUCCESS)
4954 continue;
4955 tlib = reg_get_val(hversion, NULL);
4956 if (tlib == Qnil) {
4957 RegCloseKey(hversion);
4958 continue;
4960 if (fver < atof(StringValuePtr(ver))) {
4961 fver = atof(StringValuePtr(ver));
4962 version = ver;
4963 typelib = tlib;
4965 RegCloseKey(hversion);
4968 RegCloseKey(hguid);
4969 RegCloseKey(htypelib);
4970 if (typelib != Qnil) {
4971 found = Qtrue;
4972 oletypelib_set_member(self, typelib, guid, version);
4974 return found;
4977 static VALUE
4978 oletypelib_search_registry(VALUE self, VALUE typelib)
4980 HKEY htypelib, hguid, hversion;
4981 DWORD i, j;
4982 LONG err;
4983 VALUE found = Qfalse;
4984 VALUE tlib;
4985 VALUE guid;
4986 VALUE ver;
4988 err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
4989 if(err != ERROR_SUCCESS) {
4990 return Qfalse;
4992 for(i = 0; !found; i++) {
4993 guid = reg_enum_key(htypelib, i);
4994 if (guid == Qnil)
4995 break;
4996 err = reg_open_vkey(htypelib, guid, &hguid);
4997 if (err != ERROR_SUCCESS)
4998 continue;
4999 for(j = 0; found == Qfalse; j++) {
5000 ver = reg_enum_key(hguid, j);
5001 if (ver == Qnil)
5002 break;
5003 err = reg_open_vkey(hguid, ver, &hversion);
5004 if (err != ERROR_SUCCESS)
5005 continue;
5006 tlib = reg_get_val(hversion, NULL);
5007 if (tlib == Qnil) {
5008 RegCloseKey(hversion);
5009 continue;
5011 if (rb_str_cmp(typelib, tlib) == 0) {
5012 oletypelib_set_member(self, typelib, guid, ver);
5013 found = Qtrue;
5015 RegCloseKey(hversion);
5017 RegCloseKey(hguid);
5019 RegCloseKey(htypelib);
5020 return found;
5024 * call-seq:
5025 * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object
5027 * Returns a new WIN32OLE_TYPELIB object.
5029 * The first argument <i>typelib</i> specifies OLE type library name or GUID or
5030 * OLE library file.
5031 * The second argument is major version or version of the type library.
5032 * The third argument is minor version.
5033 * The second argument and third argument are optional.
5034 * If the first argument is type library name, then the second and third argument
5035 * are ignored.
5037 * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5038 * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}')
5039 * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3)
5040 * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
5041 * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
5042 * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library'
5043 * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library'
5044 * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library'
5045 * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library'
5046 * puts tlib5.name # -> 'Microsoft Shell Controls And Automation'
5049 static VALUE
5050 foletypelib_initialize(VALUE self, VALUE args)
5052 VALUE found = Qfalse;
5053 VALUE typelib = Qnil;
5054 int len = 0;
5055 OLECHAR * pbuf;
5056 ITypeLib *pTypeLib;
5057 VALUE retval;
5058 HRESULT hr = S_OK;
5060 len = RARRAY_LEN(args);
5061 if (len < 1 || len > 3) {
5062 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
5065 typelib = rb_ary_entry(args, 0);
5067 Check_SafeStr(typelib);
5069 found = oletypelib_search_registry(self, typelib);
5070 if (found == Qfalse) {
5071 found = oletypelib_search_registry2(self, args);
5073 if (found == Qfalse) {
5074 pbuf = ole_vstr2wc(typelib);
5075 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
5076 SysFreeString(pbuf);
5077 if (SUCCEEDED(hr)) {
5078 retval = ole_typelib_from_itypelib(pTypeLib);
5079 OLE_RELEASE(pTypeLib);
5080 if (retval != Qnil) {
5081 found = Qtrue;
5082 oletypelib_set_member(self,
5083 rb_ivar_get(retval, rb_intern("name")),
5084 rb_ivar_get(retval, rb_intern("guid")),
5085 rb_ivar_get(retval, rb_intern("version")));
5090 if (found == Qfalse) {
5091 rb_raise(eWIN32OLERuntimeError, "not found type library `%s`",
5092 StringValuePtr(typelib));
5094 return self;
5098 * call-seq:
5099 * WIN32OLE_TYPELIB#guid -> The guid string.
5101 * Returns guid string which specifies type library.
5103 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5104 * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}'
5106 static VALUE
5107 foletypelib_guid(VALUE self)
5109 return rb_ivar_get(self, rb_intern("guid"));
5113 * call-seq:
5114 * WIN32OLE_TYPELIB#name -> The type library name
5116 * Returns the type library name.
5118 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5119 * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library'
5121 static VALUE
5122 foletypelib_name(VALUE self)
5124 return rb_ivar_get(self, rb_intern("name"));
5128 * call-seq:
5129 * WIN32OLE_TYPELIB#version -> The type library version.
5131 * Returns the type library version.
5133 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5134 * puts tlib.version #-> 1.3
5136 static VALUE
5137 foletypelib_version(VALUE self)
5139 VALUE ver = rb_ivar_get(self, rb_intern("version"));
5140 return rb_Float(ver);
5144 * call-seq:
5145 * WIN32OLE_TYPELIB#major_version -> The type library major version.
5147 * Returns the type library major version.
5149 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5150 * puts tlib.major_version # -> 1
5152 static VALUE
5153 foletypelib_major_version(VALUE self)
5155 VALUE ver = rb_ivar_get(self, rb_intern("version"));
5156 VALUE ary = rb_str_split(ver, ".");
5157 return rb_Integer(rb_ary_entry(ary, 0));
5161 * call-seq:
5162 * WIN32OLE_TYPELIB#minor_version -> The type library minor version.
5164 * Returns the type library minor version.
5166 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5167 * puts tlib.minor_version # -> 3
5169 static VALUE
5170 foletypelib_minor_version(VALUE self)
5172 VALUE ver = rb_ivar_get(self, rb_intern("version"));
5173 VALUE ary = rb_str_split(ver, ".");
5174 return rb_Integer(rb_ary_entry(ary, 1));
5177 static VALUE
5178 oletypelib_path(VALUE guid, VALUE version)
5180 int k;
5181 LONG err;
5182 HKEY hkey;
5183 HKEY hlang;
5184 VALUE lang;
5185 VALUE path = Qnil;
5187 VALUE key = rb_str_new2("TypeLib\\");
5188 rb_str_concat(key, guid);
5189 rb_str_cat2(key, "\\");
5190 rb_str_concat(key, version);
5192 err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey);
5193 if (err != ERROR_SUCCESS) {
5194 return Qnil;
5196 for(k = 0; path == Qnil; k++) {
5197 lang = reg_enum_key(hkey, k);
5198 if (lang == Qnil)
5199 break;
5200 err = reg_open_vkey(hkey, lang, &hlang);
5201 if (err == ERROR_SUCCESS) {
5202 path = reg_get_typelib_file_path(hlang);
5203 RegCloseKey(hlang);
5206 RegCloseKey(hkey);
5207 return path;
5211 * call-seq:
5212 * WIN32OLE_TYPELIB#path -> The type library file path.
5214 * Returns the type library file path.
5216 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5217 * puts tlib.path #-> 'C:\...\EXCEL9.OLB'
5219 static VALUE
5220 foletypelib_path(VALUE self)
5222 VALUE guid = rb_ivar_get(self, rb_intern("guid"));
5223 VALUE version = rb_ivar_get(self, rb_intern("version"));
5224 return oletypelib_path(guid, version);
5227 static void
5228 oletypelib2itypelib(VALUE self, ITypeLib **ppTypeLib)
5230 VALUE path = Qnil;
5231 OLECHAR *pbuf;
5232 HRESULT hr = S_OK;
5233 path = rb_funcall(self, rb_intern("path"), 0);
5234 if (path != Qnil) {
5235 pbuf = ole_vstr2wc(path);
5236 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, ppTypeLib);
5237 SysFreeString(pbuf);
5238 if (FAILED(hr))
5239 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx from `%s'",
5240 StringValuePtr(path));
5241 } else {
5242 rb_raise(eWIN32OLERuntimeError, "failed to get type library path");
5247 * call-seq:
5248 * WIN32OLE_TYPELIB#visible?
5250 * Returns true if the type library information is not hidden.
5251 * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN,
5252 * the method returns false, otherwise, returns true.
5253 * If the method fails to access the TLIBATTR information, then
5254 * WIN32OLERuntimeError is raised.
5256 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5257 * tlib.visible? # => true
5259 static VALUE
5260 foletypelib_visible(VALUE self)
5262 HRESULT hr;
5263 ITypeLib *pTypeLib = NULL;
5264 VALUE visible = Qtrue;
5265 TLIBATTR *pTLibAttr;
5267 oletypelib2itypelib(self, &pTypeLib);
5269 hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, &pTLibAttr);
5270 if (FAILED(hr)) {
5271 OLE_RELEASE(pTypeLib);
5272 ole_raise(hr, eWIN32OLERuntimeError, "failed to get TLIBATTR information");
5274 if ((pTLibAttr->wLibFlags == 0) ||
5275 (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) ||
5276 (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) {
5277 visible = Qfalse;
5279 pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
5280 OLE_RELEASE(pTypeLib);
5281 return visible;
5285 * call-seq:
5286 * WIN32OLE_TYPELIB#library_name
5288 * Returns library name.
5289 * If the method fails to access library name, WIN32OLERuntimeError is raised.
5291 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5292 * tlib.library_name # => Excel
5294 static VALUE
5295 foletypelib_library_name(VALUE self)
5297 HRESULT hr;
5298 ITypeLib *pTypeLib = NULL;
5299 VALUE libname = Qnil;
5300 BSTR bstr;
5302 oletypelib2itypelib(self, &pTypeLib);
5303 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
5304 &bstr, NULL, NULL, NULL);
5305 if (FAILED(hr)) {
5306 OLE_RELEASE(pTypeLib);
5307 ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name");
5309 OLE_RELEASE(pTypeLib);
5310 libname = WC2VSTR(bstr);
5311 return libname;
5316 * call-seq:
5317 * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library.
5319 * Returns the type library file path.
5321 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5322 * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...]
5324 static VALUE
5325 foletypelib_ole_types(VALUE self)
5327 ITypeLib *pTypeLib = NULL;
5328 VALUE classes = rb_ary_new();
5329 oletypelib2itypelib(self, &pTypeLib);
5330 ole_types_from_typelib(pTypeLib, classes);
5331 OLE_RELEASE(pTypeLib);
5332 return classes;
5336 * call-seq:
5337 * WIN32OLE_TYPELIB#inspect -> String
5339 * Returns the type library name with class name.
5341 * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
5342 * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>"
5344 static VALUE
5345 foletypelib_inspect(VALUE self)
5347 return default_inspect(self, "WIN32OLE_TYPELIB");
5351 * Document-class: WIN32OLE_TYPE
5353 * <code>WIN32OLE_TYPE</code> objects represent OLE type libarary information.
5357 * call-seq:
5358 * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object
5360 * Returns a new WIN32OLE_TYPE object.
5361 * The first argument <i>typelib</i> specifies OLE type library name.
5362 * The second argument specifies OLE class name.
5364 * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5365 * # => WIN32OLE_TYPE object of Application class of Excel.
5367 static VALUE
5368 foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
5370 VALUE file;
5371 OLECHAR * pbuf;
5372 ITypeLib *pTypeLib;
5373 HRESULT hr;
5375 Check_SafeStr(oleclass);
5376 Check_SafeStr(typelib);
5377 file = typelib_file(typelib);
5378 if (file == Qnil) {
5379 file = typelib;
5381 pbuf = ole_vstr2wc(file);
5382 hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
5383 if (FAILED(hr))
5384 ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
5385 SysFreeString(pbuf);
5386 if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) {
5387 OLE_RELEASE(pTypeLib);
5388 rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`",
5389 StringValuePtr(oleclass), StringValuePtr(typelib));
5391 OLE_RELEASE(pTypeLib);
5392 return self;
5396 * call-seq:
5397 * WIN32OLE_TYPE#name #=> OLE type name
5399 * Returns OLE type name.
5400 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5401 * puts tobj.name # => Application
5403 static VALUE
5404 foletype_name(VALUE self)
5406 return rb_ivar_get(self, rb_intern("name"));
5409 static VALUE
5410 ole_ole_type(ITypeInfo *pTypeInfo)
5412 HRESULT hr;
5413 TYPEATTR *pTypeAttr;
5414 VALUE type = Qnil;
5415 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5416 if(FAILED(hr)){
5417 return type;
5419 switch(pTypeAttr->typekind) {
5420 case TKIND_ENUM:
5421 type = rb_str_new2("Enum");
5422 break;
5423 case TKIND_RECORD:
5424 type = rb_str_new2("Record");
5425 break;
5426 case TKIND_MODULE:
5427 type = rb_str_new2("Module");
5428 break;
5429 case TKIND_INTERFACE:
5430 type = rb_str_new2("Interface");
5431 break;
5432 case TKIND_DISPATCH:
5433 type = rb_str_new2("Dispatch");
5434 break;
5435 case TKIND_COCLASS:
5436 type = rb_str_new2("Class");
5437 break;
5438 case TKIND_ALIAS:
5439 type = rb_str_new2("Alias");
5440 break;
5441 case TKIND_UNION:
5442 type = rb_str_new2("Union");
5443 break;
5444 case TKIND_MAX:
5445 type = rb_str_new2("Max");
5446 break;
5447 default:
5448 type = Qnil;
5449 break;
5451 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5452 return type;
5456 * call-seq:
5457 * WIN32OLE_TYPE#ole_type #=> OLE type string.
5459 * returns type of OLE class.
5460 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5461 * puts tobj.ole_type # => Class
5463 static VALUE
5464 foletype_ole_type(VALUE self)
5466 struct oletypedata *ptype;
5467 Data_Get_Struct(self, struct oletypedata, ptype);
5468 return ole_ole_type(ptype->pTypeInfo);
5471 static VALUE
5472 ole_type_guid(ITypeInfo *pTypeInfo)
5474 HRESULT hr;
5475 TYPEATTR *pTypeAttr;
5476 int len;
5477 OLECHAR bstr[80];
5478 VALUE guid = Qnil;
5479 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5480 if (FAILED(hr))
5481 return guid;
5482 len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
5483 if (len > 3) {
5484 guid = ole_wc2vstr(bstr, FALSE);
5486 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5487 return guid;
5491 * call-seq:
5492 * WIN32OLE_TYPE#guid #=> GUID
5494 * Returns GUID.
5495 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5496 * puts tobj.guid # => {00024500-0000-0000-C000-000000000046}
5498 static VALUE
5499 foletype_guid(VALUE self)
5501 struct oletypedata *ptype;
5502 Data_Get_Struct(self, struct oletypedata, ptype);
5503 return ole_type_guid(ptype->pTypeInfo);
5506 static VALUE
5507 ole_type_progid(ITypeInfo *pTypeInfo)
5509 HRESULT hr;
5510 TYPEATTR *pTypeAttr;
5511 OLECHAR *pbuf;
5512 VALUE progid = Qnil;
5513 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5514 if (FAILED(hr))
5515 return progid;
5516 hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf);
5517 if (SUCCEEDED(hr)) {
5518 progid = ole_wc2vstr(pbuf, FALSE);
5519 CoTaskMemFree(pbuf);
5521 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5522 return progid;
5526 * call-seq:
5527 * WIN32OLE_TYPE#progid #=> ProgID
5529 * Returns ProgID if it exists. If not found, then returns nil.
5530 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5531 * puts tobj.progid # => Excel.Application.9
5533 static VALUE
5534 foletype_progid(VALUE self)
5536 struct oletypedata *ptype;
5537 Data_Get_Struct(self, struct oletypedata, ptype);
5538 return ole_type_progid(ptype->pTypeInfo);
5542 static VALUE
5543 ole_type_visible(ITypeInfo *pTypeInfo)
5545 HRESULT hr;
5546 TYPEATTR *pTypeAttr;
5547 VALUE visible;
5548 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5549 if (FAILED(hr))
5550 return Qtrue;
5551 if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) {
5552 visible = Qfalse;
5553 } else {
5554 visible = Qtrue;
5556 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5557 return visible;
5561 * call-seq:
5562 * WIN32OLE_TYPE#visible #=> true or false
5564 * Returns true if the OLE class is public.
5565 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
5566 * puts tobj.visible # => true
5568 static VALUE
5569 foletype_visible(VALUE self)
5571 struct oletypedata *ptype;
5572 Data_Get_Struct(self, struct oletypedata, ptype);
5573 return ole_type_visible(ptype->pTypeInfo);
5576 static VALUE
5577 ole_type_major_version(ITypeInfo *pTypeInfo)
5579 VALUE ver;
5580 TYPEATTR *pTypeAttr;
5581 HRESULT hr;
5582 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5583 if (FAILED(hr))
5584 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5585 ver = INT2FIX(pTypeAttr->wMajorVerNum);
5586 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5587 return ver;
5591 * call-seq:
5592 * WIN32OLE_TYPE#major_version
5594 * Returns major version.
5595 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
5596 * puts tobj.major_version # => 8
5598 static VALUE
5599 foletype_major_version(VALUE self)
5601 struct oletypedata *ptype;
5602 Data_Get_Struct(self, struct oletypedata, ptype);
5603 return ole_type_major_version(ptype->pTypeInfo);
5606 static VALUE
5607 ole_type_minor_version(ITypeInfo *pTypeInfo)
5609 VALUE ver;
5610 TYPEATTR *pTypeAttr;
5611 HRESULT hr;
5612 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5613 if (FAILED(hr))
5614 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5615 ver = INT2FIX(pTypeAttr->wMinorVerNum);
5616 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5617 return ver;
5621 * call-seq:
5622 * WIN32OLE_TYPE#minor_version #=> OLE minor version
5624 * Returns minor version.
5625 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
5626 * puts tobj.minor_version # => 2
5628 static VALUE
5629 foletype_minor_version(VALUE self)
5631 struct oletypedata *ptype;
5632 Data_Get_Struct(self, struct oletypedata, ptype);
5633 return ole_type_minor_version(ptype->pTypeInfo);
5636 static VALUE
5637 ole_type_typekind(ITypeInfo *pTypeInfo)
5639 VALUE typekind;
5640 TYPEATTR *pTypeAttr;
5641 HRESULT hr;
5642 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5643 if (FAILED(hr))
5644 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5645 typekind = INT2FIX(pTypeAttr->typekind);
5646 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5647 return typekind;
5651 * call-seq:
5652 * WIN32OLE_TYPE#typekind #=> number of type.
5654 * Returns number which represents type.
5655 * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
5656 * puts tobj.typekind # => 4
5659 static VALUE
5660 foletype_typekind(VALUE self)
5662 struct oletypedata *ptype;
5663 Data_Get_Struct(self, struct oletypedata, ptype);
5664 return ole_type_typekind(ptype->pTypeInfo);
5667 static VALUE
5668 ole_type_helpstring(ITypeInfo *pTypeInfo)
5670 HRESULT hr;
5671 BSTR bhelpstr;
5672 hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL);
5673 if(FAILED(hr)) {
5674 return Qnil;
5676 return WC2VSTR(bhelpstr);
5680 * call-seq:
5681 * WIN32OLE_TYPE#helpstring #=> help string.
5683 * Returns help string.
5684 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
5685 * puts tobj.helpstring # => Web Browser interface
5687 static VALUE
5688 foletype_helpstring(VALUE self)
5690 struct oletypedata *ptype;
5691 Data_Get_Struct(self, struct oletypedata, ptype);
5692 return ole_type_helpstring(ptype->pTypeInfo);
5695 static VALUE
5696 ole_type_src_type(ITypeInfo *pTypeInfo)
5698 HRESULT hr;
5699 TYPEATTR *pTypeAttr;
5700 VALUE alias = Qnil;
5701 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5702 if (FAILED(hr))
5703 return alias;
5704 if(pTypeAttr->typekind != TKIND_ALIAS) {
5705 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5706 return alias;
5708 alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil);
5709 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5710 return alias;
5714 * call-seq:
5715 * WIN32OLE_TYPE#src_type #=> OLE source class
5717 * Returns source class when the OLE class is 'Alias'.
5718 * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType')
5719 * puts tobj.src_type # => I4
5722 static VALUE
5723 foletype_src_type(VALUE self)
5725 struct oletypedata *ptype;
5726 Data_Get_Struct(self, struct oletypedata, ptype);
5727 return ole_type_src_type(ptype->pTypeInfo);
5730 static VALUE
5731 ole_type_helpfile(ITypeInfo *pTypeInfo)
5733 HRESULT hr;
5734 BSTR bhelpfile;
5735 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile);
5736 if(FAILED(hr)) {
5737 return Qnil;
5739 return WC2VSTR(bhelpfile);
5743 * call-seq:
5744 * WIN32OLE_TYPE#helpfile
5746 * Returns helpfile path. If helpfile is not found, then returns nil.
5747 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5748 * puts tobj.helpfile # => C:\...\VBAXL9.CHM
5751 static VALUE
5752 foletype_helpfile(VALUE self)
5754 struct oletypedata *ptype;
5755 Data_Get_Struct(self, struct oletypedata, ptype);
5756 return ole_type_helpfile(ptype->pTypeInfo);
5759 static VALUE
5760 ole_type_helpcontext(ITypeInfo *pTypeInfo)
5762 HRESULT hr;
5763 DWORD helpcontext;
5764 hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL,
5765 &helpcontext, NULL);
5766 if(FAILED(hr))
5767 return Qnil;
5768 return INT2FIX(helpcontext);
5772 * call-seq:
5773 * WIN32OLE_TYPE#helpcontext
5775 * Returns helpcontext. If helpcontext is not found, then returns nil.
5776 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5777 * puts tobj.helpfile # => 131185
5779 static VALUE
5780 foletype_helpcontext(VALUE self)
5782 struct oletypedata *ptype;
5783 Data_Get_Struct(self, struct oletypedata, ptype);
5784 return ole_type_helpcontext(ptype->pTypeInfo);
5788 * call-seq:
5789 * WIN32OLE_TYPE#ole_typelib
5791 * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE
5792 * object. If it is not found, then returns nil.
5793 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5794 * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library'
5796 static VALUE
5797 foletype_ole_typelib(VALUE self)
5799 struct oletypedata *ptype;
5800 Data_Get_Struct(self, struct oletypedata, ptype);
5801 return ole_typelib_from_itypeinfo(ptype->pTypeInfo);
5804 static VALUE
5805 ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
5807 HRESULT hr;
5808 ITypeInfo *pRefTypeInfo;
5809 HREFTYPE href;
5810 WORD i;
5811 VALUE type;
5812 TYPEATTR *pTypeAttr;
5813 int flags;
5815 VALUE types = rb_ary_new();
5816 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5817 if (FAILED(hr)) {
5818 return types;
5820 for (i = 0; i < pTypeAttr->cImplTypes; i++) {
5821 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
5822 if (FAILED(hr))
5823 continue;
5825 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
5826 if (FAILED(hr))
5827 continue;
5828 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
5829 if (FAILED(hr))
5830 continue;
5832 if ((flags & implflags) == implflags) {
5833 type = ole_type_from_itypeinfo(pRefTypeInfo);
5834 if (type != Qnil) {
5835 rb_ary_push(types, type);
5839 OLE_RELEASE(pRefTypeInfo);
5841 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5842 return types;
5846 * call-seq:
5847 * WIN32OLE_TYPE#implemented_ole_types
5849 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
5850 * object.
5851 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
5852 * p tobj.implemented_ole_types # => [_Worksheet, DocEvents]
5854 static VALUE
5855 foletype_impl_ole_types(VALUE self)
5857 struct oletypedata *ptype;
5858 Data_Get_Struct(self, struct oletypedata, ptype);
5859 return ole_type_impl_ole_types(ptype->pTypeInfo, 0);
5863 * call-seq:
5864 * WIN32OLE_TYPE#source_ole_types
5866 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
5867 * object and having IMPLTYPEFLAG_FSOURCE.
5868 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
5869 * p tobj.source_ole_types
5870 * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>]
5872 static VALUE
5873 foletype_source_ole_types(VALUE self)
5875 struct oletypedata *ptype;
5876 Data_Get_Struct(self, struct oletypedata, ptype);
5877 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE);
5881 * call-seq:
5882 * WIN32OLE_TYPE#default_event_sources
5884 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
5885 * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT.
5886 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
5887 * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>]
5889 static VALUE
5890 foletype_default_event_sources(VALUE self)
5892 struct oletypedata *ptype;
5893 Data_Get_Struct(self, struct oletypedata, ptype);
5894 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT);
5898 * call-seq:
5899 * WIN32OLE_TYPE#default_ole_types
5901 * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
5902 * object and having IMPLTYPEFLAG_FDEFAULT.
5903 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
5904 * p tobj.default_ole_types
5905 * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>]
5907 static VALUE
5908 foletype_default_ole_types(VALUE self)
5910 struct oletypedata *ptype;
5911 Data_Get_Struct(self, struct oletypedata, ptype);
5912 return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT);
5916 * call-seq:
5917 * WIN32OLE_TYPE#inspect -> String
5919 * Returns the type name with class name.
5921 * ie = WIN32OLE.new('InternetExplorer.Application')
5922 * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2>
5924 static VALUE
5925 foletype_inspect(VALUE self)
5927 return default_inspect(self, "WIN32OLE_TYPE");
5930 static VALUE
5931 ole_variables(ITypeInfo *pTypeInfo)
5933 HRESULT hr;
5934 TYPEATTR *pTypeAttr;
5935 WORD i;
5936 UINT len;
5937 BSTR bstr;
5938 char *pstr;
5939 VARDESC *pVarDesc;
5940 struct olevariabledata *pvar;
5941 VALUE var;
5942 VALUE variables = rb_ary_new();
5943 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
5944 if (FAILED(hr)) {
5945 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
5948 for(i = 0; i < pTypeAttr->cVars; i++) {
5949 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc);
5950 if(FAILED(hr))
5951 continue;
5952 len = 0;
5953 pstr = NULL;
5954 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
5955 1, &len);
5956 if(FAILED(hr) || len == 0 || !bstr)
5957 continue;
5959 var = Data_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata,
5960 0,olevariable_free,pvar);
5961 pvar->pTypeInfo = pTypeInfo;
5962 OLE_ADDREF(pTypeInfo);
5963 pvar->index = i;
5964 rb_ivar_set(var, rb_intern("name"), WC2VSTR(bstr));
5965 rb_ary_push(variables, var);
5967 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
5968 pVarDesc = NULL;
5970 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
5971 return variables;
5975 * call-seq:
5976 * WIN32OLE_TYPE#variables
5978 * Returns array of WIN32OLE_VARIABLE objects which represent variables
5979 * defined in OLE class.
5980 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
5981 * vars = tobj.variables
5982 * vars.each do |v|
5983 * puts "#{v.name} = #{v.value}"
5984 * end
5986 * The result of above sample script is follows:
5987 * xlChart = -4109
5988 * xlDialogSheet = -4116
5989 * xlExcel4IntlMacroSheet = 4
5990 * xlExcel4MacroSheet = 3
5991 * xlWorksheet = -4167
5994 static VALUE
5995 foletype_variables(VALUE self)
5997 struct oletypedata *ptype;
5998 Data_Get_Struct(self, struct oletypedata, ptype);
5999 return ole_variables(ptype->pTypeInfo);
6003 * call-seq:
6004 * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects.
6006 * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in
6007 * OLE type library.
6008 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
6009 * methods = tobj.ole_methods.collect{|m|
6010 * m.name
6011 * }
6012 * # => ['Activate', 'Copy', 'Delete',....]
6014 static VALUE
6015 foletype_methods(VALUE self)
6017 struct oletypedata *ptype;
6018 Data_Get_Struct(self, struct oletypedata, ptype);
6019 return ole_methods_from_typeinfo(ptype->pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
6023 * Document-class: WIN32OLE_VARIABLE
6025 * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information.
6029 * call-seq:
6030 * WIN32OLE_VARIABLE#name
6032 * Returns the name of variable.
6034 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6035 * variables = tobj.variables
6036 * variables.each do |variable|
6037 * puts "#{variable.name}"
6038 * end
6040 * The result of above script is following:
6041 * xlChart
6042 * xlDialogSheet
6043 * xlExcel4IntlMacroSheet
6044 * xlExcel4MacroSheet
6045 * xlWorksheet
6048 static VALUE
6049 folevariable_name(VALUE self)
6051 return rb_ivar_get(self, rb_intern("name"));
6054 static VALUE
6055 ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
6057 VARDESC *pVarDesc;
6058 HRESULT hr;
6059 VALUE type;
6060 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6061 if (FAILED(hr))
6062 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
6063 type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil);
6064 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6065 return type;
6069 * call-seq:
6070 * WIN32OLE_VARIABLE#ole_type
6072 * Returns OLE type string.
6074 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6075 * variables = tobj.variables
6076 * variables.each do |variable|
6077 * puts "#{variable.ole_type} #{variable.name}"
6078 * end
6080 * The result of above script is following:
6081 * INT xlChart
6082 * INT xlDialogSheet
6083 * INT xlExcel4IntlMacroSheet
6084 * INT xlExcel4MacroSheet
6085 * INT xlWorksheet
6088 static VALUE
6089 folevariable_ole_type(VALUE self)
6091 struct olevariabledata *pvar;
6092 Data_Get_Struct(self, struct olevariabledata, pvar);
6093 return ole_variable_ole_type(pvar->pTypeInfo, pvar->index);
6096 static VALUE
6097 ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
6099 VARDESC *pVarDesc;
6100 HRESULT hr;
6101 VALUE type = rb_ary_new();
6102 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6103 if (FAILED(hr))
6104 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
6105 ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type);
6106 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6107 return type;
6111 * call-seq:
6112 * WIN32OLE_VARIABLE#ole_type_detail
6114 * Returns detail information of type. The information is array of type.
6116 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS')
6117 * variable = tobj.variables.find {|variable| variable.name == 'lFlags'}
6118 * tdetail = variable.ole_type_detail
6119 * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"]
6122 static VALUE
6123 folevariable_ole_type_detail(VALUE self)
6125 struct olevariabledata *pvar;
6126 Data_Get_Struct(self, struct olevariabledata, pvar);
6127 return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index);
6130 static VALUE
6131 ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
6133 VARDESC *pVarDesc;
6134 HRESULT hr;
6135 VALUE val = Qnil;
6136 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6137 if (FAILED(hr))
6138 return Qnil;
6139 if(pVarDesc->varkind == VAR_CONST)
6140 val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
6141 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6142 return val;
6146 * call-seq:
6147 * WIN32OLE_VARIABLE#value
6149 * Returns value if value is exists. If the value does not exist,
6150 * this method returns nil.
6152 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6153 * variables = tobj.variables
6154 * variables.each do |variable|
6155 * puts "#{variable.name} #{variable.value}"
6156 * end
6158 * The result of above script is following:
6159 * xlChart = -4109
6160 * xlDialogSheet = -4116
6161 * xlExcel4IntlMacroSheet = 4
6162 * xlExcel4MacroSheet = 3
6163 * xlWorksheet = -4167
6166 static VALUE
6167 folevariable_value(VALUE self)
6169 struct olevariabledata *pvar;
6170 Data_Get_Struct(self, struct olevariabledata, pvar);
6171 return ole_variable_value(pvar->pTypeInfo, pvar->index);
6174 static VALUE
6175 ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
6177 VARDESC *pVarDesc;
6178 HRESULT hr;
6179 VALUE visible = Qfalse;
6180 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6181 if (FAILED(hr))
6182 return visible;
6183 if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
6184 VARFLAG_FRESTRICTED |
6185 VARFLAG_FNONBROWSABLE))) {
6186 visible = Qtrue;
6188 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6189 return visible;
6193 * call-seq:
6194 * WIN32OLE_VARIABLE#visible?
6196 * Returns true if the variable is public.
6198 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6199 * variables = tobj.variables
6200 * variables.each do |variable|
6201 * puts "#{variable.name} #{variable.visible?}"
6202 * end
6204 * The result of above script is following:
6205 * xlChart true
6206 * xlDialogSheet true
6207 * xlExcel4IntlMacroSheet true
6208 * xlExcel4MacroSheet true
6209 * xlWorksheet true
6212 static VALUE
6213 folevariable_visible(VALUE self)
6215 struct olevariabledata *pvar;
6216 Data_Get_Struct(self, struct olevariabledata, pvar);
6217 return ole_variable_visible(pvar->pTypeInfo, pvar->index);
6220 static VALUE
6221 ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
6223 VARDESC *pVarDesc;
6224 HRESULT hr;
6225 VALUE kind = rb_str_new2("UNKNOWN");
6226 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6227 if (FAILED(hr))
6228 return kind;
6229 switch(pVarDesc->varkind) {
6230 case VAR_PERINSTANCE:
6231 kind = rb_str_new2("PERINSTANCE");
6232 break;
6233 case VAR_STATIC:
6234 kind = rb_str_new2("STATIC");
6235 break;
6236 case VAR_CONST:
6237 kind = rb_str_new2("CONSTANT");
6238 break;
6239 case VAR_DISPATCH:
6240 kind = rb_str_new2("DISPATCH");
6241 break;
6242 default:
6243 break;
6245 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6246 return kind;
6250 * call-seq:
6251 * WIN32OLE_VARIABLE#variable_kind
6253 * Returns variable kind string.
6255 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6256 * variables = tobj.variables
6257 * variables.each do |variable|
6258 * puts "#{variable.name} #{variable.variable_kind}"
6259 * end
6261 * The result of above script is following:
6262 * xlChart CONSTANT
6263 * xlDialogSheet CONSTANT
6264 * xlExcel4IntlMacroSheet CONSTANT
6265 * xlExcel4MacroSheet CONSTANT
6266 * xlWorksheet CONSTANT
6268 static VALUE
6269 folevariable_variable_kind(VALUE self)
6271 struct olevariabledata *pvar;
6272 Data_Get_Struct(self, struct olevariabledata, pvar);
6273 return ole_variable_kind(pvar->pTypeInfo, pvar->index);
6276 static VALUE
6277 ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
6279 VARDESC *pVarDesc;
6280 HRESULT hr;
6281 VALUE kind = Qnil;
6282 hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
6283 if (FAILED(hr))
6284 return kind;
6285 pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
6286 kind = INT2FIX(pVarDesc->varkind);
6287 return kind;
6291 * call-seq:
6292 * WIN32OLE_VARIABLE#varkind
6294 * Returns the number which represents variable kind.
6295 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
6296 * variables = tobj.variables
6297 * variables.each do |variable|
6298 * puts "#{variable.name} #{variable.varkind}"
6299 * end
6301 * The result of above script is following:
6302 * xlChart 2
6303 * xlDialogSheet 2
6304 * xlExcel4IntlMacroSheet 2
6305 * xlExcel4MacroSheet 2
6306 * xlWorksheet 2
6308 static VALUE
6309 folevariable_varkind(VALUE self)
6311 struct olevariabledata *pvar;
6312 Data_Get_Struct(self, struct olevariabledata, pvar);
6313 return ole_variable_varkind(pvar->pTypeInfo, pvar->index);
6317 * call-seq:
6318 * WIN32OLE_VARIABLE#inspect -> String
6320 * Returns the OLE variable name and the value with class name.
6323 static VALUE
6324 folevariable_inspect(VALUE self)
6326 VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
6327 rb_str_cat2(detail, "=");
6328 rb_str_concat(detail, rb_funcall(rb_funcall(self, rb_intern("value"), 0), rb_intern("inspect"), 0));
6329 return make_inspect("WIN32OLE_VARIABLE", detail);
6333 * Document-class: WIN32OLE_METHOD
6335 * <code>WIN32OLE_METHOD</code> objects represent OLE method information.
6338 static VALUE
6339 olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name)
6341 struct olemethoddata *pmethod;
6342 Data_Get_Struct(self, struct olemethoddata, pmethod);
6343 pmethod->pTypeInfo = pTypeInfo;
6344 OLE_ADDREF(pTypeInfo);
6345 pmethod->pOwnerTypeInfo = pOwnerTypeInfo;
6346 if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo);
6347 pmethod->index = index;
6348 rb_ivar_set(self, rb_intern("name"), name);
6349 return self;
6352 static VALUE
6353 folemethod_s_allocate(VALUE klass)
6355 struct olemethoddata *pmethod;
6356 VALUE obj;
6357 obj = Data_Make_Struct(klass,
6358 struct olemethoddata,
6359 0, olemethod_free, pmethod);
6360 pmethod->pTypeInfo = NULL;
6361 pmethod->pOwnerTypeInfo = NULL;
6362 pmethod->index = 0;
6363 return obj;
6367 * call-seq:
6368 * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object
6370 * Returns a new WIN32OLE_METHOD object which represents the information
6371 * about OLE method.
6372 * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object.
6373 * The second argument <i>method</i> specifies OLE method name defined OLE class
6374 * which represents WIN32OLE_TYPE object.
6376 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6377 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
6379 static VALUE
6380 folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
6382 struct oletypedata *ptype;
6383 VALUE obj = Qnil;
6384 if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) {
6385 Check_SafeStr(method);
6386 Data_Get_Struct(oletype, struct oletypedata, ptype);
6387 obj = olemethod_from_typeinfo(self, ptype->pTypeInfo, method);
6388 if (obj == Qnil) {
6389 rb_raise(eWIN32OLERuntimeError, "not found %s",
6390 StringValuePtr(method));
6393 else {
6394 rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object");
6396 return obj;
6400 * call-seq
6401 * WIN32OLE_METHOD#name
6403 * Returns the name of the method.
6405 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6406 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
6407 * puts method.name # => SaveAs
6410 static VALUE
6411 folemethod_name(VALUE self)
6413 return rb_ivar_get(self, rb_intern("name"));
6416 static VALUE
6417 ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
6419 FUNCDESC *pFuncDesc;
6420 HRESULT hr;
6421 VALUE type;
6423 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6424 if (FAILED(hr))
6425 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
6427 type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil);
6428 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6429 return type;
6433 * call-seq:
6434 * WIN32OLE_METHOD#return_type
6436 * Returns string of return value type of method.
6437 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6438 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6439 * puts method.return_type # => Workbook
6442 static VALUE
6443 folemethod_return_type(VALUE self)
6445 struct olemethoddata *pmethod;
6446 Data_Get_Struct(self, struct olemethoddata, pmethod);
6447 return ole_method_return_type(pmethod->pTypeInfo, pmethod->index);
6450 static VALUE
6451 ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
6453 FUNCDESC *pFuncDesc;
6454 HRESULT hr;
6455 VALUE vvt;
6457 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6458 if (FAILED(hr))
6459 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
6461 vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt);
6462 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6463 return vvt;
6467 * call-seq:
6468 * WIN32OLE_METHOD#return_vtype
6470 * Returns number of return value type of method.
6471 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6472 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6473 * puts method.return_vtype # => 26
6476 static VALUE
6477 folemethod_return_vtype(VALUE self)
6479 struct olemethoddata *pmethod;
6480 Data_Get_Struct(self, struct olemethoddata, pmethod);
6481 return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index);
6484 static VALUE
6485 ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
6487 FUNCDESC *pFuncDesc;
6488 HRESULT hr;
6489 VALUE type = rb_ary_new();
6491 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6492 if (FAILED(hr))
6493 return type;
6495 ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type);
6496 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6497 return type;
6501 * call-seq:
6502 * WIN32OLE_METHOD#return_type_detail
6504 * Returns detail information of return value type of method.
6505 * The information is array.
6506 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6507 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6508 * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"]
6510 static VALUE
6511 folemethod_return_type_detail(VALUE self)
6513 struct olemethoddata *pmethod;
6514 Data_Get_Struct(self, struct olemethoddata, pmethod);
6515 return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index);
6518 static VALUE
6519 ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index)
6521 FUNCDESC *pFuncDesc;
6522 HRESULT hr;
6523 VALUE invkind;
6524 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6525 if(FAILED(hr))
6526 ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
6527 invkind = INT2FIX(pFuncDesc->invkind);
6528 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6529 return invkind;
6532 static VALUE
6533 ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
6535 VALUE type = rb_str_new2("UNKNOWN");
6536 VALUE invkind = ole_method_invkind(pTypeInfo, method_index);
6537 if((FIX2INT(invkind) & INVOKE_PROPERTYGET) &&
6538 (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) {
6539 type = rb_str_new2("PROPERTY");
6540 } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) {
6541 type = rb_str_new2("PROPERTYGET");
6542 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) {
6543 type = rb_str_new2("PROPERTYPUT");
6544 } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) {
6545 type = rb_str_new2("PROPERTYPUTREF");
6546 } else if(FIX2INT(invkind) & INVOKE_FUNC) {
6547 type = rb_str_new2("FUNC");
6549 return type;
6553 * call-seq:
6554 * WIN32OLE_MTHOD#invkind
6556 * Returns the method invoke kind.
6557 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6558 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6559 * puts method.invkind # => 1
6562 static VALUE
6563 folemethod_invkind(VALUE self)
6565 struct olemethoddata *pmethod;
6566 Data_Get_Struct(self, struct olemethoddata, pmethod);
6567 return ole_method_invkind(pmethod->pTypeInfo, pmethod->index);
6571 * call-seq:
6572 * WIN32OLE_METHOD#invoke_kind
6574 * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY"
6575 * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF"
6576 * or "FUNC".
6577 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6578 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6579 * puts method.invoke_kind # => "FUNC"
6581 static VALUE
6582 folemethod_invoke_kind(VALUE self)
6584 struct olemethoddata *pmethod;
6585 Data_Get_Struct(self, struct olemethoddata, pmethod);
6586 return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index);
6589 static VALUE
6590 ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
6592 FUNCDESC *pFuncDesc;
6593 HRESULT hr;
6594 VALUE visible;
6595 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6596 if(FAILED(hr))
6597 return Qfalse;
6598 if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED |
6599 FUNCFLAG_FHIDDEN |
6600 FUNCFLAG_FNONBROWSABLE)) {
6601 visible = Qfalse;
6602 } else {
6603 visible = Qtrue;
6605 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6606 return visible;
6610 * call-seq:
6611 * WIN32OLE_METHOD#visible?
6613 * Returns true if the method is public.
6614 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6615 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6616 * puts method.visible? # => true
6618 static VALUE
6619 folemethod_visible(VALUE self)
6621 struct olemethoddata *pmethod;
6622 Data_Get_Struct(self, struct olemethoddata, pmethod);
6623 return ole_method_visible(pmethod->pTypeInfo, pmethod->index);
6626 static VALUE
6627 ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
6629 TYPEATTR *pTypeAttr;
6630 HRESULT hr;
6631 WORD i;
6632 int flags;
6633 HREFTYPE href;
6634 ITypeInfo *pRefTypeInfo;
6635 FUNCDESC *pFuncDesc;
6636 BSTR bstr;
6637 VALUE name;
6638 VALUE event = Qfalse;
6640 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
6641 if (FAILED(hr))
6642 return event;
6643 if(pTypeAttr->typekind != TKIND_COCLASS) {
6644 pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
6645 return event;
6647 for (i = 0; i < pTypeAttr->cImplTypes; i++) {
6648 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
6649 if (FAILED(hr))
6650 continue;
6652 if (flags & IMPLTYPEFLAG_FSOURCE) {
6653 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
6654 i, &href);
6655 if (FAILED(hr))
6656 continue;
6657 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
6658 href, &pRefTypeInfo);
6659 if (FAILED(hr))
6660 continue;
6661 hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index,
6662 &pFuncDesc);
6663 if (FAILED(hr)) {
6664 OLE_RELEASE(pRefTypeInfo);
6665 continue;
6668 hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo,
6669 pFuncDesc->memid,
6670 &bstr, NULL, NULL, NULL);
6671 if (FAILED(hr)) {
6672 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
6673 OLE_RELEASE(pRefTypeInfo);
6674 continue;
6677 name = WC2VSTR(bstr);
6678 pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
6679 OLE_RELEASE(pRefTypeInfo);
6680 if (rb_str_cmp(method_name, name) == 0) {
6681 event = Qtrue;
6682 break;
6686 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
6687 return event;
6691 * call-seq:
6692 * WIN32OLE_METHOD#event?
6694 * Returns true if the method is event.
6695 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6696 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
6697 * puts method.event? # => true
6700 static VALUE
6701 folemethod_event(VALUE self)
6703 struct olemethoddata *pmethod;
6704 Data_Get_Struct(self, struct olemethoddata, pmethod);
6705 if (!pmethod->pOwnerTypeInfo)
6706 return Qfalse;
6707 return ole_method_event(pmethod->pOwnerTypeInfo,
6708 pmethod->index,
6709 rb_ivar_get(self, rb_intern("name")));
6713 * call-seq:
6714 * WIN32OLE_METHOD#event_interface
6716 * Returns event interface name if the method is event.
6717 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6718 * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
6719 * puts method.event_interface # => WorkbookEvents
6721 static VALUE
6722 folemethod_event_interface(VALUE self)
6724 BSTR name;
6725 struct olemethoddata *pmethod;
6726 HRESULT hr;
6727 Data_Get_Struct(self, struct olemethoddata, pmethod);
6728 if(folemethod_event(self) == Qtrue) {
6729 hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL);
6730 if(SUCCEEDED(hr))
6731 return WC2VSTR(name);
6733 return Qnil;
6736 static VALUE
6737 ole_method_docinfo_from_type(
6738 ITypeInfo *pTypeInfo,
6739 UINT method_index,
6740 BSTR *name,
6741 BSTR *helpstr,
6742 DWORD *helpcontext,
6743 BSTR *helpfile
6746 FUNCDESC *pFuncDesc;
6747 HRESULT hr;
6748 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6749 if (FAILED(hr))
6750 return hr;
6751 hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
6752 name, helpstr,
6753 helpcontext, helpfile);
6754 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6755 return hr;
6758 static VALUE
6759 ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
6761 HRESULT hr;
6762 BSTR bhelpstring;
6763 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring,
6764 NULL, NULL);
6765 if (FAILED(hr))
6766 return Qnil;
6767 return WC2VSTR(bhelpstring);
6771 * call-seq:
6772 * WIN32OLE_METHOD#helpstring
6774 * Returns help string of OLE method. If the help string is not found,
6775 * then the method returns nil.
6776 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
6777 * method = WIN32OLE_METHOD.new(tobj, 'Navigate')
6778 * puts method.helpstring # => Navigates to a URL or file.
6781 static VALUE
6782 folemethod_helpstring(VALUE self)
6784 struct olemethoddata *pmethod;
6785 Data_Get_Struct(self, struct olemethoddata, pmethod);
6786 return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index);
6789 static VALUE
6790 ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
6792 HRESULT hr;
6793 BSTR bhelpfile;
6794 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
6795 NULL, &bhelpfile);
6796 if (FAILED(hr))
6797 return Qnil;
6798 return WC2VSTR(bhelpfile);
6802 * call-seq:
6803 * WIN32OLE_METHOD#helpfile
6805 * Returns help file. If help file is not found, then
6806 * the method returns nil.
6807 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6808 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6809 * puts method.helpfile # => C:\...\VBAXL9.CHM
6811 static VALUE
6812 folemethod_helpfile(VALUE self)
6814 struct olemethoddata *pmethod;
6815 Data_Get_Struct(self, struct olemethoddata, pmethod);
6817 return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index);
6820 static VALUE
6821 ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
6823 HRESULT hr;
6824 DWORD helpcontext = 0;
6825 hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
6826 &helpcontext, NULL);
6827 if (FAILED(hr))
6828 return Qnil;
6829 return INT2FIX(helpcontext);
6833 * call-seq:
6834 * WIN32OLE_METHOD#helpcontext
6836 * Returns help context.
6837 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6838 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6839 * puts method.helpcontext # => 65717
6841 static VALUE
6842 folemethod_helpcontext(VALUE self)
6844 struct olemethoddata *pmethod;
6845 Data_Get_Struct(self, struct olemethoddata, pmethod);
6846 return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index);
6849 static VALUE
6850 ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
6852 FUNCDESC *pFuncDesc;
6853 HRESULT hr;
6854 VALUE dispid = Qnil;
6855 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6856 if (FAILED(hr))
6857 return dispid;
6858 dispid = INT2NUM(pFuncDesc->memid);
6859 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6860 return dispid;
6864 * call-seq:
6865 * WIN32OLE_METHOD#dispid
6867 * Returns dispatch ID.
6868 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6869 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6870 * puts method.dispid # => 181
6872 static VALUE
6873 folemethod_dispid(VALUE self)
6875 struct olemethoddata *pmethod;
6876 Data_Get_Struct(self, struct olemethoddata, pmethod);
6877 return ole_method_dispid(pmethod->pTypeInfo, pmethod->index);
6880 static VALUE
6881 ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
6883 FUNCDESC *pFuncDesc;
6884 HRESULT hr;
6885 VALUE offset_vtbl = Qnil;
6886 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6887 if (FAILED(hr))
6888 return offset_vtbl;
6889 offset_vtbl = INT2FIX(pFuncDesc->oVft);
6890 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6891 return offset_vtbl;
6895 * call-seq:
6896 * WIN32OLE_METHOD#offset_vtbl
6898 * Returns the offset ov VTBL.
6899 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
6900 * method = WIN32OLE_METHOD.new(tobj, 'Add')
6901 * puts method.offset_vtbl # => 40
6903 static VALUE
6904 folemethod_offset_vtbl(VALUE self)
6906 struct olemethoddata *pmethod;
6907 Data_Get_Struct(self, struct olemethoddata, pmethod);
6908 return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index);
6911 static VALUE
6912 ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
6914 FUNCDESC *pFuncDesc;
6915 HRESULT hr;
6916 VALUE size_params = Qnil;
6917 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6918 if (FAILED(hr))
6919 return size_params;
6920 size_params = INT2FIX(pFuncDesc->cParams);
6921 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6922 return size_params;
6926 * call-seq:
6927 * WIN32OLE_METHOD#size_params
6929 * Returns the size of arguments of the method.
6930 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6931 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
6932 * puts method.size_params # => 11
6935 static VALUE
6936 folemethod_size_params(VALUE self)
6938 struct olemethoddata *pmethod;
6939 Data_Get_Struct(self, struct olemethoddata, pmethod);
6940 return ole_method_size_params(pmethod->pTypeInfo, pmethod->index);
6943 static VALUE
6944 ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
6946 FUNCDESC *pFuncDesc;
6947 HRESULT hr;
6948 VALUE size_opt_params = Qnil;
6949 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6950 if (FAILED(hr))
6951 return size_opt_params;
6952 size_opt_params = INT2FIX(pFuncDesc->cParamsOpt);
6953 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6954 return size_opt_params;
6958 * call-seq:
6959 * WIN32OLE_METHOD#size_opt_params
6961 * Returns the size of optional parameters.
6962 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
6963 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
6964 * puts method.size_opt_params # => 4
6966 static VALUE
6967 folemethod_size_opt_params(VALUE self)
6969 struct olemethoddata *pmethod;
6970 Data_Get_Struct(self, struct olemethoddata, pmethod);
6971 return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index);
6974 static VALUE
6975 ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
6977 FUNCDESC *pFuncDesc;
6978 HRESULT hr;
6979 BSTR *bstrs;
6980 UINT len, i;
6981 struct oleparamdata *pparam;
6982 VALUE param;
6983 VALUE params = rb_ary_new();
6984 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
6985 if (FAILED(hr))
6986 return params;
6988 len = 0;
6989 bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
6990 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
6991 bstrs, pFuncDesc->cParams + 1,
6992 &len);
6993 if (FAILED(hr)) {
6994 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
6995 return params;
6997 SysFreeString(bstrs[0]);
6998 if (pFuncDesc->cParams > 0) {
6999 for(i = 1; i < len; i++) {
7000 param = Data_Make_Struct(cWIN32OLE_PARAM, struct oleparamdata, 0,
7001 oleparam_free, pparam);
7002 pparam->pTypeInfo = pTypeInfo;
7003 OLE_ADDREF(pTypeInfo);
7004 pparam->method_index = method_index;
7005 pparam->index = i - 1;
7006 rb_ivar_set(param, rb_intern("name"), WC2VSTR(bstrs[i]));
7007 rb_ary_push(params, param);
7010 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7011 return params;
7016 * call-seq:
7017 * WIN32OLE_METHOD#params
7019 * returns array of WIN32OLE_PARAM object corresponding with method parameters.
7020 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7021 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7022 * p method.params # => [Filename, FileFormat, Password, WriteResPassword,
7023 * ReadOnlyRecommended, CreateBackup, AccessMode,
7024 * ConflictResolution, AddToMru, TextCodepage,
7025 * TextVisualLayout]
7027 static VALUE
7028 folemethod_params(VALUE self)
7030 struct olemethoddata *pmethod;
7031 Data_Get_Struct(self, struct olemethoddata, pmethod);
7032 return ole_method_params(pmethod->pTypeInfo, pmethod->index);
7036 * call-seq:
7037 * WIN32OLE_METHOD#inspect -> String
7039 * Returns the method name with class name.
7042 static VALUE
7043 folemethod_inspect(VALUE self)
7045 return default_inspect(self, "WIN32OLE_METHOD");
7049 * Document-class: WIN32OLE_PARAM
7051 * <code>WIN32OLE_PARAM</code> objects represent param information of
7052 * the OLE method.
7056 * call-seq:
7057 * WIN32OLE_PARAM#name
7059 * Returns name.
7060 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7061 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7062 * param1 = method.params[0]
7063 * puts param1.name # => Filename
7065 static VALUE
7066 foleparam_name(VALUE self)
7068 return rb_ivar_get(self, rb_intern("name"));
7071 static VALUE
7072 ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
7074 FUNCDESC *pFuncDesc;
7075 HRESULT hr;
7076 VALUE type = rb_str_new2("unknown type");
7077 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7078 if (FAILED(hr))
7079 return type;
7080 type = ole_typedesc2val(pTypeInfo,
7081 &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil);
7082 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7083 return type;
7087 * call-seq:
7088 * WIN32OLE_PARAM#ole_type
7090 * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method).
7091 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7092 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7093 * param1 = method.params[0]
7094 * puts param1.ole_type # => VARIANT
7096 static VALUE
7097 foleparam_ole_type(VALUE self)
7099 struct oleparamdata *pparam;
7100 Data_Get_Struct(self, struct oleparamdata, pparam);
7101 return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index,
7102 pparam->index);
7105 static VALUE
7106 ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
7108 FUNCDESC *pFuncDesc;
7109 HRESULT hr;
7110 VALUE typedetail = rb_ary_new();
7111 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7112 if (FAILED(hr))
7113 return typedetail;
7114 ole_typedesc2val(pTypeInfo,
7115 &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail);
7116 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7117 return typedetail;
7121 * call-seq:
7122 * WIN32OLE_PARAM#ole_type_detail
7124 * Returns detail information of type of argument.
7125 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction')
7126 * method = WIN32OLE_METHOD.new(tobj, 'SumIf')
7127 * param1 = method.params[0]
7128 * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"]
7130 static VALUE
7131 foleparam_ole_type_detail(VALUE self)
7133 struct oleparamdata *pparam;
7134 Data_Get_Struct(self, struct oleparamdata, pparam);
7135 return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index,
7136 pparam->index);
7139 static VALUE
7140 ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask)
7142 FUNCDESC *pFuncDesc;
7143 HRESULT hr;
7144 VALUE ret = Qfalse;
7145 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7146 if(FAILED(hr))
7147 return ret;
7148 if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask)
7149 ret = Qtrue;
7150 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7151 return ret;
7155 * call-seq:
7156 * WIN32OLE_PARAM#input?
7158 * Returns true if the parameter is input.
7159 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7160 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7161 * param1 = method.params[0]
7162 * puts param1.input? # => true
7164 static VALUE foleparam_input(VALUE self)
7166 struct oleparamdata *pparam;
7167 Data_Get_Struct(self, struct oleparamdata, pparam);
7168 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7169 pparam->index, PARAMFLAG_FIN);
7173 * call-seq:
7174 * WIN32OLE#output?
7176 * Returns true if argument is output.
7177 * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents')
7178 * method = WIN32OLE_METHOD.new(tobj, 'NewWindow')
7179 * method.params.each do |param|
7180 * puts "#{param.name} #{param.output?}"
7181 * end
7183 * The result of above script is following:
7184 * URL false
7185 * Flags false
7186 * TargetFrameName false
7187 * PostData false
7188 * Headers false
7189 * Processed true
7191 static VALUE foleparam_output(VALUE self)
7193 struct oleparamdata *pparam;
7194 Data_Get_Struct(self, struct oleparamdata, pparam);
7195 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7196 pparam->index, PARAMFLAG_FOUT);
7200 * call-seq:
7201 * WIN32OLE_PARAM#optional?
7203 * Returns true if argument is optional.
7204 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7205 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7206 * param1 = method.params[0]
7207 * puts "#{param1.name} #{param1.optional?}" # => Filename true
7209 static VALUE foleparam_optional(VALUE self)
7211 struct oleparamdata *pparam;
7212 Data_Get_Struct(self, struct oleparamdata, pparam);
7213 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7214 pparam->index, PARAMFLAG_FOPT);
7218 * call-seq:
7219 * WIN32OLE_PARAM#retval?
7221 * Returns true if argument is return value.
7222 * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library',
7223 * 'DirectPlayLobbyConnection')
7224 * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName')
7225 * param = method.params[0]
7226 * puts "#{param.name} #{param.retval?}" # => name true
7228 static VALUE foleparam_retval(VALUE self)
7230 struct oleparamdata *pparam;
7231 Data_Get_Struct(self, struct oleparamdata, pparam);
7232 return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
7233 pparam->index, PARAMFLAG_FRETVAL);
7236 static VALUE
7237 ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
7239 FUNCDESC *pFuncDesc;
7240 ELEMDESC *pElemDesc;
7241 PARAMDESCEX * pParamDescEx;
7242 HRESULT hr;
7243 USHORT wParamFlags;
7244 USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT;
7245 VALUE defval = Qnil;
7246 hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
7247 if (FAILED(hr))
7248 return defval;
7249 pElemDesc = &pFuncDesc->lprgelemdescParam[index];
7250 wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags;
7251 if ((wParamFlags & mask) == mask) {
7252 pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex;
7253 defval = ole_variant2val(&pParamDescEx->varDefaultValue);
7255 pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
7256 return defval;
7260 * call-seq:
7261 * WIN32OLE_PARAM#default
7263 * Returns default value. If the default value does not exist,
7264 * this method returns nil.
7265 * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
7266 * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
7267 * method.params.each do |param|
7268 * if param.default
7269 * puts "#{param.name} (= #{param.default})"
7270 * else
7271 * puts "#{param}"
7272 * end
7273 * end
7275 * The above script result is following:
7276 * Filename
7277 * FileFormat
7278 * Password
7279 * WriteResPassword
7280 * ReadOnlyRecommended
7281 * CreateBackup
7282 * AccessMode (= 1)
7283 * ConflictResolution
7284 * AddToMru
7285 * TextCodepage
7286 * TextVisualLayout
7288 static VALUE foleparam_default(VALUE self)
7290 struct oleparamdata *pparam;
7291 Data_Get_Struct(self, struct oleparamdata, pparam);
7292 return ole_param_default(pparam->pTypeInfo, pparam->method_index,
7293 pparam->index);
7297 * call-seq:
7298 * WIN32OLE_PARAM#inspect -> String
7300 * Returns the parameter name with class name. If the parameter has default value,
7301 * then returns name=value string with class name.
7304 static VALUE
7305 foleparam_inspect(VALUE self)
7307 VALUE detail = foleparam_name(self);
7308 VALUE defval = foleparam_default(self);
7309 if (defval != Qnil) {
7310 rb_str_cat2(detail, "=");
7311 rb_str_concat(detail, rb_funcall(defval, rb_intern("inspect"), 0));
7313 return make_inspect("WIN32OLE_PARAM", detail);
7317 * Document-class: WIN32OLE_EVENT
7319 * <code>WIN32OLE_EVENT</code> objects controls OLE event.
7322 static IEventSinkVtbl vtEventSink;
7323 static BOOL g_IsEventSinkVtblInitialized = FALSE;
7325 void EVENTSINK_Destructor(PIEVENTSINKOBJ);
7327 STDMETHODIMP
7328 EVENTSINK_QueryInterface(
7329 PEVENTSINK pEV,
7330 REFIID iid,
7331 LPVOID* ppv
7333 if (IsEqualIID(iid, &IID_IUnknown) ||
7334 IsEqualIID(iid, &IID_IDispatch) ||
7335 IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) {
7336 *ppv = pEV;
7338 else {
7339 *ppv = NULL;
7340 return E_NOINTERFACE;
7342 ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
7343 return NOERROR;
7346 STDMETHODIMP_(ULONG)
7347 EVENTSINK_AddRef(
7348 PEVENTSINK pEV
7350 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
7351 return ++pEVObj->m_cRef;
7354 STDMETHODIMP_(ULONG) EVENTSINK_Release(
7355 PEVENTSINK pEV
7357 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
7358 --pEVObj->m_cRef;
7359 if(pEVObj->m_cRef != 0)
7360 return pEVObj->m_cRef;
7361 EVENTSINK_Destructor(pEVObj);
7362 return 0;
7365 STDMETHODIMP EVENTSINK_GetTypeInfoCount(
7366 PEVENTSINK pEV,
7367 UINT *pct
7369 *pct = 0;
7370 return NOERROR;
7373 STDMETHODIMP EVENTSINK_GetTypeInfo(
7374 PEVENTSINK pEV,
7375 UINT info,
7376 LCID lcid,
7377 ITypeInfo **pInfo
7379 *pInfo = NULL;
7380 return DISP_E_BADINDEX;
7383 STDMETHODIMP EVENTSINK_GetIDsOfNames(
7384 PEVENTSINK pEventSink,
7385 REFIID riid,
7386 OLECHAR **szNames,
7387 UINT cNames,
7388 LCID lcid,
7389 DISPID *pDispID
7391 ITypeInfo *pTypeInfo;
7392 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
7393 pTypeInfo = pEV->pTypeInfo;
7394 if (pTypeInfo) {
7395 return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
7397 return DISP_E_UNKNOWNNAME;
7400 static long
7401 ole_search_event_at(VALUE ary, VALUE ev)
7403 VALUE event;
7404 VALUE def_event;
7405 VALUE event_name;
7406 long i, len;
7407 long ret = -1;
7408 def_event = Qnil;
7409 len = RARRAY_LEN(ary);
7410 for(i = 0; i < len; i++) {
7411 event = rb_ary_entry(ary, i);
7412 event_name = rb_ary_entry(event, 1);
7413 if(NIL_P(event_name) && NIL_P(ev)) {
7414 ret = i;
7415 break;
7417 else if (TYPE(ev) == T_STRING &&
7418 TYPE(event_name) == T_STRING &&
7419 rb_str_cmp(ev, event_name) == 0) {
7420 ret = i;
7421 break;
7424 return ret;
7427 static VALUE
7428 ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
7430 VALUE event;
7431 VALUE def_event;
7432 VALUE event_name;
7433 int i, len;
7434 *is_default = FALSE;
7435 def_event = Qnil;
7436 len = RARRAY_LEN(ary);
7437 for(i = 0; i < len; i++) {
7438 event = rb_ary_entry(ary, i);
7439 event_name = rb_ary_entry(event, 1);
7440 if(NIL_P(event_name)) {
7441 *is_default = TRUE;
7442 def_event = event;
7444 else if (rb_str_cmp(ev, event_name) == 0) {
7445 *is_default = FALSE;
7446 return event;
7449 return def_event;
7451 static VALUE
7452 ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
7454 VALUE mid;
7456 *is_default_handler = FALSE;
7457 mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev)));
7458 if (rb_respond_to(handler, mid)) {
7459 return mid;
7461 mid = rb_intern("method_missing");
7462 if (rb_respond_to(handler, mid)) {
7463 *is_default_handler = TRUE;
7464 return mid;
7466 return Qnil;
7469 static void
7470 ole_delete_event(VALUE ary, VALUE ev)
7472 long at = -1;
7473 at = ole_search_event_at(ary, ev);
7474 if (at >= 0) {
7475 rb_ary_delete_at(ary, at);
7479 static void
7480 hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
7482 BSTR *bstrs;
7483 HRESULT hr;
7484 UINT len, i;
7485 VARIANT *pvar;
7486 VALUE val;
7487 VALUE key;
7488 len = 0;
7489 bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
7490 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
7491 bstrs, pdispparams->cArgs + 1,
7492 &len);
7493 if (FAILED(hr))
7494 return;
7496 for (i = 0; i < len - 1; i++) {
7497 key = WC2VSTR(bstrs[i + 1]);
7498 val = rb_hash_aref(hash, INT2FIX(i));
7499 if (val == Qnil)
7500 val = rb_hash_aref(hash, key);
7501 if (val == Qnil)
7502 val = rb_hash_aref(hash, rb_str_intern(key));
7503 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
7504 ole_val2ptr_variant(val, pvar);
7508 static VALUE
7509 hash2result(VALUE hash)
7511 VALUE ret = Qnil;
7512 ret = rb_hash_aref(hash, rb_str_new2("return"));
7513 if (ret == Qnil)
7514 ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
7515 return ret;
7518 static void
7519 ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
7521 int i;
7522 VALUE v;
7523 VARIANT *pvar;
7524 for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) {
7525 v = rb_ary_entry(ary, i);
7526 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
7527 ole_val2ptr_variant(v, pvar);
7531 static VALUE
7532 exec_callback(VALUE arg)
7534 VALUE *parg = (VALUE *)arg;
7535 VALUE handler = parg[0];
7536 VALUE mid = parg[1];
7537 VALUE args = parg[2];
7538 return rb_apply(handler, mid, args);
7541 static VALUE
7542 rescue_callback(VALUE arg)
7545 VALUE e = rb_errinfo();
7546 VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
7547 VALUE msg = rb_funcall(e, rb_intern("message"), 0);
7548 bt = rb_ary_entry(bt, 0);
7549 fprintf(stdout, "%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e));
7550 rb_backtrace();
7551 ruby_finalize();
7552 exit(-1);
7554 return Qnil;
7557 STDMETHODIMP EVENTSINK_Invoke(
7558 PEVENTSINK pEventSink,
7559 DISPID dispid,
7560 REFIID riid,
7561 LCID lcid,
7562 WORD wFlags,
7563 DISPPARAMS *pdispparams,
7564 VARIANT *pvarResult,
7565 EXCEPINFO *pexcepinfo,
7566 UINT *puArgErr
7569 HRESULT hr;
7570 BSTR bstr;
7571 unsigned int count;
7572 unsigned int i;
7573 ITypeInfo *pTypeInfo;
7574 VARIANT *pvar;
7575 VALUE ary, obj, event, args, outargv, ev, result;
7576 VALUE handler = Qnil;
7577 VALUE arg[3];
7578 VALUE mid;
7579 VALUE is_outarg = Qfalse;
7580 BOOL is_default_handler = FALSE;
7581 int state;
7583 PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
7584 pTypeInfo = pEV->pTypeInfo;
7585 obj = evs_entry(pEV->m_event_id);
7586 if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
7587 return NOERROR;
7590 ary = rb_ivar_get(obj, id_events);
7591 if (NIL_P(ary) || TYPE(ary) != T_ARRAY) {
7592 return NOERROR;
7594 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
7595 &bstr, 1, &count);
7596 if (FAILED(hr)) {
7597 return NOERROR;
7599 ev = WC2VSTR(bstr);
7600 event = ole_search_event(ary, ev, &is_default_handler);
7601 if (TYPE(event) == T_ARRAY) {
7602 handler = rb_ary_entry(event, 0);
7603 mid = rb_intern("call");
7604 is_outarg = rb_ary_entry(event, 3);
7605 } else {
7606 handler = rb_ivar_get(obj, rb_intern("handler"));
7607 if (handler == Qnil) {
7608 return NOERROR;
7610 mid = ole_search_handler_method(handler, ev, &is_default_handler);
7612 if (handler == Qnil || mid == Qnil) {
7613 return NOERROR;
7616 args = rb_ary_new();
7617 if (is_default_handler) {
7618 rb_ary_push(args, ev);
7621 /* make argument of event handler */
7622 for (i = 0; i < pdispparams->cArgs; ++i) {
7623 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
7624 rb_ary_push(args, ole_variant2val(pvar));
7626 outargv = Qnil;
7627 if (is_outarg == Qtrue) {
7628 outargv = rb_ary_new();
7629 rb_ary_push(args, outargv);
7633 * if exception raised in event callback,
7634 * then you receive cfp consistency error.
7635 * to avoid this error we use begin rescue end.
7636 * and the exception raised then error message print
7637 * and exit ruby process by Win32OLE itself.
7639 arg[0] = handler;
7640 arg[1] = mid;
7641 arg[2] = args;
7642 result = rb_protect(exec_callback, (VALUE)arg, &state);
7643 if (state != 0) {
7644 rescue_callback(Qnil);
7646 if(TYPE(result) == T_HASH) {
7647 hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
7648 result = hash2result(result);
7649 }else if (is_outarg == Qtrue && TYPE(outargv) == T_ARRAY) {
7650 ary2ptr_dispparams(outargv, pdispparams);
7653 if (pvarResult) {
7654 ole_val2variant(result, pvarResult);
7657 return NOERROR;
7660 PIEVENTSINKOBJ
7661 EVENTSINK_Constructor() {
7662 PIEVENTSINKOBJ pEv;
7663 if (!g_IsEventSinkVtblInitialized) {
7664 vtEventSink.QueryInterface=EVENTSINK_QueryInterface;
7665 vtEventSink.AddRef = EVENTSINK_AddRef;
7666 vtEventSink.Release = EVENTSINK_Release;
7667 vtEventSink.Invoke = EVENTSINK_Invoke;
7668 vtEventSink.GetIDsOfNames = EVENTSINK_GetIDsOfNames;
7669 vtEventSink.GetTypeInfoCount = EVENTSINK_GetTypeInfoCount;
7670 vtEventSink.GetTypeInfo = EVENTSINK_GetTypeInfo;
7672 g_IsEventSinkVtblInitialized = TRUE;
7674 pEv = ALLOC_N(IEVENTSINKOBJ, 1);
7675 if(pEv == NULL) return NULL;
7676 pEv->lpVtbl = &vtEventSink;
7677 pEv->m_cRef = 0;
7678 pEv->m_event_id = 0;
7679 pEv->pTypeInfo = NULL;
7680 return pEv;
7683 void EVENTSINK_Destructor(
7684 PIEVENTSINKOBJ pEVObj
7686 if(pEVObj != NULL) {
7687 OLE_RELEASE(pEVObj->pTypeInfo);
7688 free(pEVObj);
7689 pEVObj = NULL;
7693 static HRESULT
7694 find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
7696 HRESULT hr;
7697 IDispatch *pDispatch;
7698 ITypeInfo *pTypeInfo;
7699 ITypeLib *pTypeLib;
7700 TYPEATTR *pTypeAttr;
7701 HREFTYPE RefType;
7702 ITypeInfo *pImplTypeInfo;
7703 TYPEATTR *pImplTypeAttr;
7705 struct oledata *pole;
7706 unsigned int index;
7707 unsigned int count;
7708 int type;
7709 BSTR bstr;
7710 char *pstr;
7712 BOOL is_found = FALSE;
7713 LCID lcid = cWIN32OLE_lcid;
7715 OLEData_Get_Struct(ole, pole);
7717 pDispatch = pole->pDispatch;
7719 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo);
7720 if (FAILED(hr))
7721 return hr;
7723 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
7724 &pTypeLib,
7725 &index);
7726 OLE_RELEASE(pTypeInfo);
7727 if (FAILED(hr))
7728 return hr;
7730 if (!pitf) {
7731 hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
7732 piid,
7733 ppTypeInfo);
7734 OLE_RELEASE(pTypeLib);
7735 return hr;
7737 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
7738 for (index = 0; index < count; index++) {
7739 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
7740 index,
7741 &pTypeInfo);
7742 if (FAILED(hr))
7743 break;
7744 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
7746 if(FAILED(hr)) {
7747 OLE_RELEASE(pTypeInfo);
7748 break;
7750 if(pTypeAttr->typekind == TKIND_COCLASS) {
7751 for (type = 0; type < pTypeAttr->cImplTypes; type++) {
7752 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
7753 type,
7754 &RefType);
7755 if (FAILED(hr))
7756 break;
7757 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
7758 RefType,
7759 &pImplTypeInfo);
7760 if (FAILED(hr))
7761 break;
7763 hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo,
7765 &bstr,
7766 NULL, NULL, NULL);
7767 if (FAILED(hr)) {
7768 OLE_RELEASE(pImplTypeInfo);
7769 break;
7771 pstr = ole_wc2mb(bstr);
7772 if (strcmp(pitf, pstr) == 0) {
7773 hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo,
7774 &pImplTypeAttr);
7775 if (SUCCEEDED(hr)) {
7776 is_found = TRUE;
7777 *piid = pImplTypeAttr->guid;
7778 if (ppTypeInfo) {
7779 *ppTypeInfo = pImplTypeInfo;
7780 (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo));
7782 pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo,
7783 pImplTypeAttr);
7786 free(pstr);
7787 OLE_RELEASE(pImplTypeInfo);
7788 if (is_found || FAILED(hr))
7789 break;
7793 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
7794 OLE_RELEASE(pTypeInfo);
7795 if (is_found || FAILED(hr))
7796 break;
7798 OLE_RELEASE(pTypeLib);
7799 if(!is_found)
7800 return E_NOINTERFACE;
7801 return hr;
7804 static HRESULT
7805 find_coclass(
7806 ITypeInfo *pTypeInfo,
7807 TYPEATTR *pTypeAttr,
7808 ITypeInfo **pCOTypeInfo,
7809 TYPEATTR **pCOTypeAttr)
7811 HRESULT hr = E_NOINTERFACE;
7812 ITypeLib *pTypeLib;
7813 int count;
7814 BOOL found = FALSE;
7815 ITypeInfo *pTypeInfo2;
7816 TYPEATTR *pTypeAttr2;
7817 int flags;
7818 int i,j;
7819 HREFTYPE href;
7820 ITypeInfo *pRefTypeInfo;
7821 TYPEATTR *pRefTypeAttr;
7823 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
7824 if (FAILED(hr)) {
7825 return hr;
7827 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
7828 for (i = 0; i < count && !found; i++) {
7829 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
7830 if (FAILED(hr))
7831 continue;
7832 hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
7833 if (FAILED(hr)) {
7834 OLE_RELEASE(pTypeInfo2);
7835 continue;
7837 if (pTypeAttr2->typekind != TKIND_COCLASS) {
7838 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
7839 OLE_RELEASE(pTypeInfo2);
7840 continue;
7842 for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
7843 hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
7844 if (FAILED(hr))
7845 continue;
7846 if (!(flags & IMPLTYPEFLAG_FDEFAULT))
7847 continue;
7848 hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
7849 if (FAILED(hr))
7850 continue;
7851 hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
7852 if (FAILED(hr))
7853 continue;
7854 hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
7855 if (FAILED(hr)) {
7856 OLE_RELEASE(pRefTypeInfo);
7857 continue;
7859 if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
7860 found = TRUE;
7863 if (!found) {
7864 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
7865 OLE_RELEASE(pTypeInfo2);
7868 OLE_RELEASE(pTypeLib);
7869 if (found) {
7870 *pCOTypeInfo = pTypeInfo2;
7871 *pCOTypeAttr = pTypeAttr2;
7872 hr = S_OK;
7873 } else {
7874 hr = E_NOINTERFACE;
7876 return hr;
7879 static HRESULT
7880 find_default_source_from_typeinfo(
7881 ITypeInfo *pTypeInfo,
7882 TYPEATTR *pTypeAttr,
7883 ITypeInfo **ppTypeInfo)
7885 int i = 0;
7886 HRESULT hr = E_NOINTERFACE;
7887 int flags;
7888 HREFTYPE hRefType;
7889 /* Enumerate all implemented types of the COCLASS */
7890 for (i = 0; i < pTypeAttr->cImplTypes; i++) {
7891 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
7892 if (FAILED(hr))
7893 continue;
7896 looking for the [default] [source]
7897 we just hope that it is a dispinterface :-)
7899 if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
7900 (flags & IMPLTYPEFLAG_FSOURCE)) {
7902 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
7903 i, &hRefType);
7904 if (FAILED(hr))
7905 continue;
7906 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
7907 hRefType, ppTypeInfo);
7908 if (SUCCEEDED(hr))
7909 break;
7912 return hr;
7915 static HRESULT
7916 find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
7918 HRESULT hr;
7919 IProvideClassInfo2 *pProvideClassInfo2;
7920 IProvideClassInfo *pProvideClassInfo;
7921 void *p;
7923 IDispatch *pDispatch;
7924 ITypeInfo *pTypeInfo;
7925 ITypeInfo *pTypeInfo2 = NULL;
7926 TYPEATTR *pTypeAttr;
7927 TYPEATTR *pTypeAttr2 = NULL;
7929 struct oledata *pole;
7931 OLEData_Get_Struct(ole, pole);
7932 pDispatch = pole->pDispatch;
7933 hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
7934 &IID_IProvideClassInfo2,
7935 &p);
7936 if (SUCCEEDED(hr)) {
7937 pProvideClassInfo2 = p;
7938 hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
7939 GUIDKIND_DEFAULT_SOURCE_DISP_IID,
7940 piid);
7941 OLE_RELEASE(pProvideClassInfo2);
7942 if (SUCCEEDED(hr)) {
7943 hr = find_iid(ole, NULL, piid, ppTypeInfo);
7946 if (SUCCEEDED(hr)) {
7947 return hr;
7949 hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
7950 &IID_IProvideClassInfo,
7951 &p);
7952 if (SUCCEEDED(hr)) {
7953 pProvideClassInfo = p;
7954 hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
7955 &pTypeInfo);
7956 OLE_RELEASE(pProvideClassInfo);
7958 if (FAILED(hr)) {
7959 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
7961 if (FAILED(hr))
7962 return hr;
7963 hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
7964 if (FAILED(hr)) {
7965 OLE_RELEASE(pTypeInfo);
7966 return hr;
7969 *ppTypeInfo = 0;
7970 hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
7971 if (!*ppTypeInfo) {
7972 hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
7973 if (SUCCEEDED(hr)) {
7974 hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
7975 OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
7976 OLE_RELEASE(pTypeInfo2);
7979 OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
7980 OLE_RELEASE(pTypeInfo);
7981 /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
7982 if (!*ppTypeInfo) {
7983 if (SUCCEEDED(hr))
7984 hr = E_UNEXPECTED;
7985 return hr;
7988 /* Determine IID of default source interface */
7989 hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr);
7990 if (SUCCEEDED(hr)) {
7991 *piid = pTypeAttr->guid;
7992 (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr);
7994 else
7995 OLE_RELEASE(*ppTypeInfo);
7997 return hr;
8001 static void
8002 ole_event_free(struct oleeventdata *poleev)
8004 OLE_FREE(poleev->pConnectionPoint);
8005 free(poleev);
8008 static VALUE
8009 fev_s_allocate(VALUE klass)
8011 VALUE obj;
8012 struct oleeventdata *poleev;
8013 obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev);
8014 poleev->dwCookie = 0;
8015 poleev->pConnectionPoint = NULL;
8016 poleev->event_id = 0;
8017 return obj;
8020 static VALUE
8021 ev_advise(int argc, VALUE *argv, VALUE self)
8024 VALUE ole, itf;
8025 struct oledata *pole;
8026 char *pitf;
8027 HRESULT hr;
8028 IID iid;
8029 ITypeInfo *pTypeInfo = 0;
8030 IDispatch *pDispatch;
8031 IConnectionPointContainer *pContainer;
8032 IConnectionPoint *pConnectionPoint;
8033 IEVENTSINKOBJ *pIEV;
8034 DWORD dwCookie;
8035 struct oleeventdata *poleev;
8036 void *p;
8038 rb_secure(4);
8039 rb_scan_args(argc, argv, "11", &ole, &itf);
8041 if (!rb_obj_is_kind_of(ole, cWIN32OLE)) {
8042 rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object");
8045 if(TYPE(itf) != T_NIL) {
8046 if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) {
8047 rb_raise(rb_eSecurityError, "Insecure Event Creation - %s",
8048 StringValuePtr(itf));
8050 Check_SafeStr(itf);
8051 pitf = StringValuePtr(itf);
8052 hr = find_iid(ole, pitf, &iid, &pTypeInfo);
8054 else {
8055 hr = find_default_source(ole, &iid, &pTypeInfo);
8057 if (FAILED(hr)) {
8058 ole_raise(hr, rb_eRuntimeError, "interface not found");
8061 OLEData_Get_Struct(ole, pole);
8062 pDispatch = pole->pDispatch;
8063 hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
8064 &IID_IConnectionPointContainer,
8065 &p);
8066 if (FAILED(hr)) {
8067 OLE_RELEASE(pTypeInfo);
8068 ole_raise(hr, rb_eRuntimeError,
8069 "failed to query IConnectionPointContainer");
8071 pContainer = p;
8073 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
8074 &iid,
8075 &pConnectionPoint);
8076 OLE_RELEASE(pContainer);
8077 if (FAILED(hr)) {
8078 OLE_RELEASE(pTypeInfo);
8079 ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint");
8081 pIEV = EVENTSINK_Constructor();
8082 pIEV->m_iid = iid;
8083 hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
8084 (IUnknown*)pIEV,
8085 &dwCookie);
8086 if (FAILED(hr)) {
8087 ole_raise(hr, rb_eRuntimeError, "Advise Error");
8090 Data_Get_Struct(self, struct oleeventdata, poleev);
8091 pIEV->m_event_id
8092 = NUM2INT(evs_length());
8093 pIEV->pTypeInfo = pTypeInfo;
8094 poleev->dwCookie = dwCookie;
8095 poleev->pConnectionPoint = pConnectionPoint;
8096 poleev->event_id = pIEV->m_event_id;
8098 return self;
8102 * call-seq:
8103 * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
8105 * Returns OLE event object.
8106 * The first argument specifies WIN32OLE object.
8107 * The second argument specifies OLE event name.
8108 * ie = WIN32OLE.new('InternetExplorer.Application')
8109 * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
8111 static VALUE
8112 fev_initialize(int argc, VALUE *argv, VALUE self)
8114 ev_advise(argc, argv, self);
8115 evs_push(self);
8116 rb_ivar_set(self, id_events, rb_ary_new());
8117 return self;
8121 * call-seq:
8122 * WIN32OLE_EVENT.message_loop
8124 * Translates and dispatches Windows message.
8126 static VALUE
8127 fev_s_msg_loop(VALUE klass)
8129 ole_msg_loop();
8130 return Qnil;
8134 static void
8135 add_event_call_back(VALUE obj, VALUE event, VALUE data)
8137 VALUE events = rb_ivar_get(obj, id_events);
8138 if (NIL_P(events) || TYPE(events) != T_ARRAY) {
8139 events = rb_ary_new();
8140 rb_ivar_set(obj, id_events, events);
8142 ole_delete_event(events, event);
8143 rb_ary_push(events, data);
8146 static VALUE
8147 ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
8149 struct oleeventdata *poleev;
8150 VALUE event, args, data;
8151 Data_Get_Struct(self, struct oleeventdata, poleev);
8152 if (poleev->pConnectionPoint == NULL) {
8153 rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
8155 rb_scan_args(argc, argv, "01*", &event, &args);
8156 if(!NIL_P(event)) {
8157 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) {
8158 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
8160 if (TYPE(event) == T_SYMBOL) {
8161 event = rb_sym_to_s(event);
8164 data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
8165 add_event_call_back(self, event, data);
8166 return Qnil;
8170 * call-seq:
8171 * WIN32OLE_EVENT#on_event([event]){...}
8173 * Defines the callback event.
8174 * If argument is omitted, this method defines the callback of all events.
8175 * If you want to modify reference argument in callback, return hash in
8176 * callback. If you want to return value to OLE server as result of callback
8177 * use `return' or :return.
8179 * ie = WIN32OLE.new('InternetExplorer.Application')
8180 * ev = WIN32OLE_EVENT.new(ie)
8181 * ev.on_event("NavigateComplete") {|url| puts url}
8182 * ev.on_event() {|ev, *args| puts "#{ev} fired"}
8184 * ev.on_event("BeforeNavigate2") {|*args|
8185 * ...
8186 * # set true to BeforeNavigate reference argument `Cancel'.
8187 * # Cancel is 7-th argument of BeforeNavigate,
8188 * # so you can use 6 as key of hash instead of 'Cancel'.
8189 * # The argument is counted from 0.
8190 * # The hash key of 0 means first argument.)
8191 * {:Cancel => true} # or {'Cancel' => true} or {6 => true}
8194 * ev.on_event(...) {|*args|
8195 * {:return => 1, :xxx => yyy}
8198 static VALUE
8199 fev_on_event(int argc, VALUE *argv, VALUE self)
8201 return ev_on_event(argc, argv, self, Qfalse);
8205 * call-seq:
8206 * WIN32OLE_EVENT#on_event_with_outargs([event]){...}
8208 * Defines the callback of event.
8209 * If you want modify argument in callback,
8210 * you could use this method instead of WIN32OLE_EVENT#on_event.
8212 * ie = WIN32OLE.new('InternetExplorer.Application')
8213 * ev = WIN32OLE_EVENT.new(ie)
8214 * ev.on_event_with_outargs('BeforeNavigate2') {|*args|
8215 * args.last[6] = true
8218 static VALUE
8219 fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
8221 return ev_on_event(argc, argv, self, Qtrue);
8225 * call-seq:
8226 * WIN32OLE_EVENT#off_event([event])
8228 * removes the callback of event.
8230 * ie = WIN32OLE.new('InternetExplorer.Application')
8231 * ev = WIN32OLE_EVENT.new(ie)
8232 * ev.on_event('BeforeNavigate2') {|*args|
8233 * args.last[6] = true
8235 * ...
8236 * ev.off_event('BeforeNavigate2')
8237 * ...
8239 static VALUE
8240 fev_off_event(int argc, VALUE *argv, VALUE self)
8242 VALUE event = Qnil;
8243 VALUE events;
8245 rb_secure(4);
8246 rb_scan_args(argc, argv, "01", &event);
8247 if(!NIL_P(event)) {
8248 if(TYPE(event) != T_STRING && TYPE(event) != T_SYMBOL) {
8249 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
8251 if (TYPE(event) == T_SYMBOL) {
8252 event = rb_sym_to_s(event);
8255 events = rb_ivar_get(self, id_events);
8256 if (NIL_P(events)) {
8257 return Qnil;
8259 ole_delete_event(events, event);
8260 return Qnil;
8264 * call-seq:
8265 * WIN32OLE_EVENT#unadvise -> nil
8267 * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
8268 * does not receive the OLE server event any more.
8269 * This method is trial implementation.
8271 * ie = WIN32OLE.new('InternetExplorer.Application')
8272 * ev = WIN32OLE_EVENT.new(ie)
8273 * ev.on_event() {...}
8274 * ...
8275 * ev.unadvise
8278 static VALUE
8279 fev_unadvise(VALUE self)
8281 struct oleeventdata *poleev;
8282 Data_Get_Struct(self, struct oleeventdata, poleev);
8283 if (poleev->pConnectionPoint) {
8284 ole_msg_loop();
8285 evs_delete(poleev->event_id);
8286 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
8287 OLE_RELEASE(poleev->pConnectionPoint);
8288 poleev->pConnectionPoint = NULL;
8290 return Qnil;
8293 static VALUE
8294 evs_push(VALUE ev)
8296 return rb_ary_push(ary_ole_event, ev);
8299 static VALUE
8300 evs_delete(long i)
8302 rb_ary_store(ary_ole_event, i, Qnil);
8303 return Qnil;
8306 static VALUE
8307 evs_entry(long i)
8309 return rb_ary_entry(ary_ole_event, i);
8312 static VALUE
8313 evs_length()
8315 return rb_funcall(ary_ole_event, rb_intern("length"), 0);
8319 * call-seq:
8320 * WIN32OLE_EVENT#handler=
8322 * sets event handler object. If handler object has onXXX
8323 * method according to XXX event, then onXXX method is called
8324 * when XXX event occurs.
8326 * If handler object has method_missing and there is no
8327 * method according to the event, then method_missing
8328 * called and 1-st argument is event name.
8330 * If handler object has onXXX method and there is block
8331 * defined by WIN32OLE_EVENT#on_event('XXX'){},
8332 * then block is executed but handler object method is not called
8333 * when XXX event occurs.
8335 * class Handler
8336 * def onStatusTextChange(text)
8337 * puts "StatusTextChanged"
8338 * end
8339 * def onPropertyChange(prop)
8340 * puts "PropertyChanged"
8341 * end
8342 * def method_missing(ev, *arg)
8343 * puts "other event #{ev}"
8344 * end
8345 * end
8347 * handler = Handler.new
8348 * ie = WIN32OLE.new('InternetExplorer.Application')
8349 * ev = WIN32OLE_EVENT.new(ie)
8350 * ev.on_event("StatusTextChange") {|*args|
8351 * puts "this block executed."
8352 * puts "handler.onStatusTextChange method is not called."
8354 * ev.handler = handler
8357 static VALUE
8358 fev_set_handler(VALUE self, VALUE val)
8360 return rb_ivar_set(self, rb_intern("handler"), val);
8364 * call-seq:
8365 * WIN32OLE_EVENT#handler
8367 * returns handler object.
8370 static VALUE
8371 fev_get_handler(VALUE self)
8373 return rb_ivar_get(self, rb_intern("handler"));
8376 static void
8377 olevariant_free(struct olevariantdata *pvar)
8379 VariantClear(&(pvar->realvar));
8380 VariantClear(&(pvar->var));
8381 free(pvar);
8384 static VALUE
8385 folevariant_s_allocate(VALUE klass)
8387 struct olevariantdata *pvar;
8388 VALUE obj;
8389 ole_initialize();
8390 obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar);
8391 VariantInit(&(pvar->var));
8392 VariantInit(&(pvar->realvar));
8393 return obj;
8397 * call-seq:
8398 * WIN32OLE_VARIANT.array(ary, vt)
8400 * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
8401 * The first argument should be Array object which specifies dimensions
8402 * and each size of dimensions of OLE array.
8403 * The second argument specifies variant type of the element of OLE array.
8405 * The following create 2 dimensions OLE array. The first dimensions size
8406 * is 3, and the second is 4.
8408 * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
8409 * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
8412 static VALUE
8413 folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
8415 VALUE obj = Qnil;
8416 VARTYPE vt;
8417 struct olevariantdata *pvar;
8418 SAFEARRAYBOUND *psab = NULL;
8419 SAFEARRAY *psa = NULL;
8420 UINT dim = 0;
8421 UINT i = 0;
8423 ole_initialize();
8425 vt = NUM2UINT(vvt);
8426 vt = (vt | VT_ARRAY);
8427 Check_Type(elems, T_ARRAY);
8428 obj = folevariant_s_allocate(klass);
8430 Data_Get_Struct(obj, struct olevariantdata, pvar);
8431 dim = RARRAY_LEN(elems);
8433 psab = ALLOC_N(SAFEARRAYBOUND, dim);
8435 if(!psab) {
8436 rb_raise(rb_eRuntimeError, "memory allocation error");
8439 for (i = 0; i < dim; i++) {
8440 psab[i].cElements = FIX2INT(rb_ary_entry(elems, i));
8441 psab[i].lLbound = 0;
8444 psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
8445 if (psa == NULL) {
8446 if (psab) free(psab);
8447 rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
8450 V_VT(&(pvar->var)) = vt;
8451 if (vt & VT_BYREF) {
8452 V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
8453 V_ARRAY(&(pvar->realvar)) = psa;
8454 V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
8455 } else {
8456 V_ARRAY(&(pvar->var)) = psa;
8458 if (psab) free(psab);
8459 return obj;
8463 * call-seq:
8464 * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object.
8466 * Returns Ruby object wrapping OLE variant.
8467 * The first argument specifies Ruby object to convert OLE variant variable.
8468 * The second argument specifies VARIANT type.
8469 * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method
8471 * shell = WIN32OLE.new("Shell.Application")
8472 * folder = shell.NameSpace("C:\\Windows")
8473 * item = folder.ParseName("tmp.txt")
8474 * # You can't use Ruby String object to call FolderItem.InvokeVerb.
8475 * # Instead, you have to use WIN32OLE_VARIANT object to call the method.
8476 * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
8477 * item.invokeVerb(shortcut)
8480 static VALUE
8481 folevariant_initialize(VALUE self, VALUE args)
8483 int len = 0;
8484 VARIANT var;
8485 VALUE val;
8486 VALUE vvt;
8487 VARTYPE vt;
8488 struct olevariantdata *pvar;
8490 len = RARRAY_LEN(args);
8491 if (len < 1 || len > 3) {
8492 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
8494 VariantInit(&var);
8495 val = rb_ary_entry(args, 0);
8496 Data_Get_Struct(self, struct olevariantdata, pvar);
8497 if (len == 1) {
8498 ole_val2variant(val, &(pvar->var));
8499 } else {
8500 vvt = rb_ary_entry(args, 1);
8501 vt = NUM2INT(vvt);
8502 ole_val2olevariantdata(val, vt, pvar);
8504 vt = V_VT(&pvar->var);
8505 return self;
8508 static SAFEARRAY *
8509 get_locked_safe_array(VALUE val)
8511 struct olevariantdata *pvar;
8512 SAFEARRAY *psa = NULL;
8513 HRESULT hr;
8514 Data_Get_Struct(val, struct olevariantdata, pvar);
8515 if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
8516 rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
8518 psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
8519 if (psa == NULL) {
8520 return psa;
8522 hr = SafeArrayLock(psa);
8523 if (FAILED(hr)) {
8524 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
8526 return psa;
8529 static long *
8530 ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
8532 long dim;
8533 long *pid;
8534 long i;
8535 dim = SafeArrayGetDim(psa);
8536 if (dim != ary_size) {
8537 rb_raise(rb_eArgError, "unmatch number of indices");
8539 pid = ALLOC_N(long, dim);
8540 if (pid == NULL) {
8541 rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
8543 for (i = 0; i < dim; i++) {
8544 pid[i] = NUM2INT(ary[i]);
8546 return pid;
8549 static void
8550 unlock_safe_array(SAFEARRAY *psa)
8552 HRESULT hr;
8553 hr = SafeArrayUnlock(psa);
8554 if (FAILED(hr)) {
8555 ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
8560 * call-seq:
8561 * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array.
8563 * Returns the element of WIN32OLE_VARIANT object(OLE array).
8564 * This method is available only when the variant type of
8565 * WIN32OLE_VARIANT object is VT_ARRAY.
8567 * REMARK:
8568 * The all indicies should be 0 or natural number and
8569 * lower than or equal to max indicies.
8570 * (This point is different with Ruby Array indicies.)
8572 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
8573 * p obj[0,0] # => 1
8574 * p obj[1,0] # => 4
8575 * p obj[2,0] # => WIN32OLERuntimeError
8576 * p obj[0, -1] # => WIN32OLERuntimeError
8579 static VALUE
8580 folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
8582 struct olevariantdata *pvar;
8583 SAFEARRAY *psa;
8584 VALUE val = Qnil;
8585 VARIANT variant;
8586 long *pid;
8587 HRESULT hr;
8589 Data_Get_Struct(self, struct olevariantdata, pvar);
8590 if (!V_ISARRAY(&(pvar->var))) {
8591 rb_raise(eWIN32OLERuntimeError,
8592 "`[]' is not available for this variant type object");
8594 psa = get_locked_safe_array(self);
8595 if (psa == NULL) {
8596 return val;
8599 pid = ary2safe_array_index(argc, argv, psa);
8601 VariantInit(&variant);
8602 V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF;
8603 hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
8604 if (FAILED(hr)) {
8605 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex");
8607 val = ole_variant2val(&variant);
8609 unlock_safe_array(psa);
8610 if (pid) free(pid);
8611 return val;
8614 static VOID *
8615 val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
8617 VOID *p = NULL;
8618 HRESULT hr = S_OK;
8619 ole_val2variant_ex(val, var, vt);
8620 if ((vt & ~VT_BYREF) == VT_VARIANT) {
8621 p = var;
8622 } else {
8623 if ( (vt & ~VT_BYREF) != V_VT(var)) {
8624 hr = VariantChangeTypeEx(var, var,
8625 cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
8626 if (FAILED(hr)) {
8627 ole_raise(hr, rb_eRuntimeError, "failed to change type");
8630 p = get_ptr_of_variant(var);
8632 if (p == NULL) {
8633 rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
8635 return p;
8639 * call-seq:
8640 * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array
8642 * Set the element of WIN32OLE_VARIANT object(OLE array) to val.
8643 * This method is available only when the variant type of
8644 * WIN32OLE_VARIANT object is VT_ARRAY.
8646 * REMARK:
8647 * The all indicies should be 0 or natural number and
8648 * lower than or equal to max indicies.
8649 * (This point is different with Ruby Array indicies.)
8651 * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
8652 * obj[0,0] = 7
8653 * obj[1,0] = 8
8654 * p obj.value # => [[7,2,3], [8,5,6]]
8655 * obj[2,0] = 9 # => WIN32OLERuntimeError
8656 * obj[0, -1] = 9 # => WIN32OLERuntimeError
8659 static VALUE
8660 folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
8662 struct olevariantdata *pvar;
8663 SAFEARRAY *psa;
8664 VARIANT var;
8665 VARTYPE vt;
8666 long *pid;
8667 HRESULT hr;
8668 VOID *p = NULL;
8670 Data_Get_Struct(self, struct olevariantdata, pvar);
8671 if (!V_ISARRAY(&(pvar->var))) {
8672 rb_raise(eWIN32OLERuntimeError,
8673 "`[]' is not available for this variant type object");
8675 psa = get_locked_safe_array(self);
8676 if (psa == NULL) {
8677 rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
8680 pid = ary2safe_array_index(argc-1, argv, psa);
8682 VariantInit(&var);
8683 vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
8684 p = val2variant_ptr(argv[argc-1], &var, vt);
8685 if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
8686 (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
8687 rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
8689 hr = SafeArrayPutElement(psa, pid, p);
8690 if (FAILED(hr)) {
8691 ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
8694 unlock_safe_array(psa);
8695 if (pid) free(pid);
8696 return argv[argc-1];
8700 * call-seq:
8701 * WIN32OLE_VARIANT.value #=> Ruby object.
8703 * Returns Ruby object value from OLE variant.
8704 * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR)
8705 * obj.value # => "1" (not Fixnum object, but String object "1")
8708 static VALUE
8709 folevariant_value(VALUE self)
8711 struct olevariantdata *pvar;
8712 VALUE val = Qnil;
8713 VARTYPE vt;
8714 int dim;
8715 SAFEARRAY *psa;
8716 Data_Get_Struct(self, struct olevariantdata, pvar);
8718 val = ole_variant2val(&(pvar->var));
8719 vt = V_VT(&(pvar->var));
8721 if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) {
8722 if (vt & VT_BYREF) {
8723 psa = *V_ARRAYREF(&(pvar->var));
8724 } else {
8725 psa = V_ARRAY(&(pvar->var));
8727 if (!psa) {
8728 return val;
8730 dim = SafeArrayGetDim(psa);
8731 if (dim == 1) {
8732 val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*"));
8735 return val;
8739 * call-seq:
8740 * WIN32OLE_VARIANT.vartype #=> OLE variant type.
8742 * Returns OLE variant type.
8743 * obj = WIN32OLE_VARIANT.new("string")
8744 * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
8747 static VALUE
8748 folevariant_vartype(VALUE self)
8750 struct olevariantdata *pvar;
8751 Data_Get_Struct(self, struct olevariantdata, pvar);
8752 return INT2FIX(V_VT(&pvar->var));
8756 * call-seq:
8757 * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
8759 * Sets variant value to val. If the val type does not match variant value
8760 * type(vartype), then val is changed to match variant value type(vartype)
8761 * before setting val.
8762 * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
8763 * If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
8765 * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
8766 * obj.value = 3.2 # 3.2 is changed to 3 when setting value.
8767 * p obj.value # => 3
8769 static VALUE
8770 folevariant_set_value(VALUE self, VALUE val)
8772 struct olevariantdata *pvar;
8773 VARTYPE vt;
8774 Data_Get_Struct(self, struct olevariantdata, pvar);
8775 vt = V_VT(&(pvar->var));
8776 if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) {
8777 rb_raise(eWIN32OLERuntimeError,
8778 "`value=' is not available for this variant type object");
8780 ole_val2olevariantdata(val, vt, pvar);
8781 return Qnil;
8784 static void
8785 init_enc2cp()
8787 enc2cp_table = st_init_numtable();
8790 static void
8791 free_enc2cp()
8793 st_free_table(enc2cp_table);
8796 void
8797 Init_win32ole()
8799 ary_ole_event = rb_ary_new();
8800 rb_register_mark_object(ary_ole_event);
8801 id_events = rb_intern("events");
8803 com_vtbl.QueryInterface = QueryInterface;
8804 com_vtbl.AddRef = AddRef;
8805 com_vtbl.Release = Release;
8806 com_vtbl.GetTypeInfoCount = GetTypeInfoCount;
8807 com_vtbl.GetTypeInfo = GetTypeInfo;
8808 com_vtbl.GetIDsOfNames = GetIDsOfNames;
8809 com_vtbl.Invoke = Invoke;
8811 message_filter.QueryInterface = mf_QueryInterface;
8812 message_filter.AddRef = mf_AddRef;
8813 message_filter.Release = mf_Release;
8814 message_filter.HandleInComingCall = mf_HandleInComingCall;
8815 message_filter.RetryRejectedCall = mf_RetryRejectedCall;
8816 message_filter.MessagePending = mf_MessagePending;
8818 com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
8819 rb_register_mark_object(com_hash);
8821 cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
8823 rb_define_alloc_func(cWIN32OLE, fole_s_allocate);
8825 rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1);
8827 rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1);
8828 rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1);
8830 rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1);
8831 rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1);
8832 rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1);
8833 rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0);
8834 rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1);
8835 rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0);
8836 rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1);
8837 rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0);
8839 rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1);
8840 rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1);
8841 rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3);
8842 rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3);
8843 rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3);
8845 /* support propput method that takes an argument */
8846 rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1);
8848 rb_define_method(cWIN32OLE, "ole_free", fole_free, 0);
8850 rb_define_method(cWIN32OLE, "each", fole_each, 0);
8851 rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1);
8853 /* support setproperty method much like Perl ;-) */
8854 rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1);
8856 rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0);
8857 rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0);
8858 rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0);
8859 rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0);
8861 rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1);
8862 rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method");
8863 rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0);
8864 rb_define_method(cWIN32OLE, "ole_type", fole_type, 0);
8865 rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type");
8866 rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0);
8867 rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1);
8868 rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1);
8870 rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION));
8871 rb_define_const(cWIN32OLE, "ARGV", rb_ary_new());
8873 rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP));
8874 rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP));
8875 rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP));
8876 rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP));
8877 rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL));
8878 rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7));
8879 rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8));
8881 rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT));
8882 rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT));
8884 mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT");
8885 rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY));
8886 rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL));
8887 rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2));
8888 rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4));
8889 rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4));
8890 rb_define_const(mWIN32OLE_VARIANT, "VT_R8", INT2FIX(VT_R8));
8891 rb_define_const(mWIN32OLE_VARIANT, "VT_CY", INT2FIX(VT_CY));
8892 rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", INT2FIX(VT_DATE));
8893 rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", INT2FIX(VT_BSTR));
8894 rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", INT2FIX(VT_USERDEFINED));
8895 rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", INT2FIX(VT_PTR));
8896 rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", INT2FIX(VT_DISPATCH));
8897 rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", INT2FIX(VT_ERROR));
8898 rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", INT2FIX(VT_BOOL));
8899 rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", INT2FIX(VT_VARIANT));
8900 rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", INT2FIX(VT_UNKNOWN));
8901 rb_define_const(mWIN32OLE_VARIANT, "VT_I1", INT2FIX(VT_I1));
8902 rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1));
8903 rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2));
8904 rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4));
8905 #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
8906 rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8));
8907 rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8));
8908 #endif
8909 rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT));
8910 rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT));
8911 rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY));
8912 rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF));
8914 cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject);
8915 rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0);
8916 rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2);
8917 rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0);
8918 rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0);
8919 rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0);
8920 rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0);
8921 rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0);
8922 rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0);
8923 rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0);
8924 rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types");
8925 rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0);
8926 rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0);
8927 rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name");
8928 rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0);
8930 cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject);
8931 rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1);
8932 rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0);
8933 rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0);
8934 rb_define_alloc_func(cWIN32OLE_TYPE, foletype_s_allocate);
8935 rb_define_method(cWIN32OLE_TYPE, "initialize", foletype_initialize, 2);
8936 rb_define_method(cWIN32OLE_TYPE, "name", foletype_name, 0);
8937 rb_define_method(cWIN32OLE_TYPE, "ole_type", foletype_ole_type, 0);
8938 rb_define_method(cWIN32OLE_TYPE, "guid", foletype_guid, 0);
8939 rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0);
8940 rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0);
8941 rb_define_alias(cWIN32OLE_TYPE, "to_s", "name");
8942 rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0);
8943 rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0);
8944 rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0);
8945 rb_define_method(cWIN32OLE_TYPE, "helpstring", foletype_helpstring, 0);
8946 rb_define_method(cWIN32OLE_TYPE, "src_type", foletype_src_type, 0);
8947 rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0);
8948 rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0);
8949 rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0);
8950 rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0);
8951 rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0);
8952 rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0);
8953 rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0);
8954 rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0);
8955 rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0);
8956 rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0);
8958 cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject);
8959 rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0);
8960 rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0);
8961 rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0);
8962 rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0);
8963 rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0);
8964 rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0);
8965 rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0);
8966 rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0);
8967 rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name");
8969 cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject);
8970 rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate);
8971 rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2);
8972 rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0);
8973 rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0);
8974 rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0);
8975 rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0);
8976 rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0);
8977 rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0);
8978 rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0);
8979 rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0);
8980 rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0);
8981 rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0);
8982 rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0);
8983 rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0);
8984 rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0);
8985 rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0);
8986 rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0);
8987 rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0);
8988 rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0);
8989 rb_define_alias(cWIN32OLE_METHOD, "to_s", "name");
8990 rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0);
8992 cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject);
8993 rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0);
8994 rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0);
8995 rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0);
8996 rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0);
8997 rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0);
8998 rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0);
8999 rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0);
9000 rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0);
9001 rb_define_alias(cWIN32OLE_PARAM, "to_s", "name");
9002 rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0);
9004 cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
9005 rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
9006 rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
9007 rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
9008 rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
9009 rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
9010 rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
9011 rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
9012 rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
9013 rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
9015 cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
9016 rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
9017 rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
9018 rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
9019 rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
9020 rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
9021 rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
9022 rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
9023 rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
9024 rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY)));
9025 rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL)));
9026 rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH)));
9028 eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError);
9030 init_enc2cp();
9031 atexit((void (*)(void))free_enc2cp);
9032 ole_init_cp();
9033 cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);