PageRenderTime 87ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/ext/win32ole/win32ole.c

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