PageRenderTime 77ms CodeModel.GetById 34ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * (c) 1995 Microsoft Corporation. All rights reserved.
  3. * Developed by ActiveWare Internet Corp., http://www.ActiveWare.com
  4. *
  5. * Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy
  6. * <gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net>
  7. *
  8. * You may distribute under the terms of either the GNU General Public
  9. * License or the Artistic License, as specified in the README file
  10. * of the Perl distribution.
  11. *
  12. */
  13. /*
  14. 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) {

Large files files are truncated, but you can click here to view the full file