Ruby  2.5.0dev(2017-10-22revision60238)
win32ole_typelib.c
Go to the documentation of this file.
1 #include "win32ole.h"
2 
3 struct oletypelibdata {
4  ITypeLib *pTypeLib;
5 };
6 
7 static VALUE reg_get_typelib_file_path(HKEY hkey);
8 static VALUE oletypelib_path(VALUE guid, VALUE version);
9 static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib);
10 static VALUE foletypelib_s_typelibs(VALUE self);
11 static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib);
12 static void oletypelib_free(void *ptr);
13 static size_t oletypelib_size(const void *ptr);
14 static VALUE foletypelib_s_allocate(VALUE klass);
15 static VALUE oletypelib_search_registry(VALUE self, VALUE typelib);
16 static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr);
17 static VALUE oletypelib_search_registry2(VALUE self, VALUE args);
18 static VALUE foletypelib_initialize(VALUE self, VALUE args);
19 static VALUE foletypelib_guid(VALUE self);
20 static VALUE foletypelib_name(VALUE self);
21 static VALUE make_version_str(VALUE major, VALUE minor);
22 static VALUE foletypelib_version(VALUE self);
23 static VALUE foletypelib_major_version(VALUE self);
24 static VALUE foletypelib_minor_version(VALUE self);
25 static VALUE foletypelib_path(VALUE self);
26 static VALUE foletypelib_visible(VALUE self);
27 static VALUE foletypelib_library_name(VALUE self);
28 static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes);
29 static VALUE typelib_file_from_typelib(VALUE ole);
30 static VALUE typelib_file_from_clsid(VALUE ole);
31 static VALUE foletypelib_ole_types(VALUE self);
32 static VALUE foletypelib_inspect(VALUE self);
33 
34 static const rb_data_type_t oletypelib_datatype = {
35  "win32ole_typelib",
36  {NULL, oletypelib_free, oletypelib_size,},
38 };
39 
40 static VALUE
41 reg_get_typelib_file_path(HKEY hkey)
42 {
43  VALUE path = Qnil;
44  path = reg_get_val2(hkey, "win64");
45  if (path != Qnil) {
46  return path;
47  }
48  path = reg_get_val2(hkey, "win32");
49  if (path != Qnil) {
50  return path;
51  }
52  path = reg_get_val2(hkey, "win16");
53  return path;
54 }
55 
56 static VALUE
57 oletypelib_path(VALUE guid, VALUE version)
58 {
59  int k;
60  LONG err;
61  HKEY hkey;
62  HKEY hlang;
63  VALUE lang;
64  VALUE path = Qnil;
65 
66  VALUE key = rb_str_new2("TypeLib\\");
67  rb_str_concat(key, guid);
68  rb_str_cat2(key, "\\");
69  rb_str_concat(key, version);
70 
71  err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey);
72  if (err != ERROR_SUCCESS) {
73  return Qnil;
74  }
75  for(k = 0; path == Qnil; k++) {
76  lang = reg_enum_key(hkey, k);
77  if (lang == Qnil)
78  break;
79  err = reg_open_vkey(hkey, lang, &hlang);
80  if (err == ERROR_SUCCESS) {
81  path = reg_get_typelib_file_path(hlang);
82  RegCloseKey(hlang);
83  }
84  }
85  RegCloseKey(hkey);
86  return path;
87 }
88 
89 static HRESULT
90 oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib)
91 {
92  VALUE path;
93  OLECHAR *pBuf;
94  HRESULT hr;
95  path = oletypelib_path(guid, version);
96  if (path == Qnil) {
97  return E_UNEXPECTED;
98  }
99  pBuf = ole_vstr2wc(path);
100  hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib);
101  SysFreeString(pBuf);
102  return hr;
103 }
104 
105 ITypeLib *
107 {
108  struct oletypelibdata *ptlib;
109  TypedData_Get_Struct(self, struct oletypelibdata, &oletypelib_datatype, ptlib);
110  return ptlib->pTypeLib;
111 }
112 
113 VALUE
114 ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
115 {
116  HRESULT hr;
117  ITypeLib *pTypeLib;
118  unsigned int index;
119  VALUE retval = Qnil;
120 
121  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
122  if(FAILED(hr)) {
123  return Qnil;
124  }
125  retval = create_win32ole_typelib(pTypeLib);
126  return retval;
127 }
128 
129 /*
130  * Document-class: WIN32OLE_TYPELIB
131  *
132  * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information.
133  */
134 
135 /*
136  * call-seq:
137  *
138  * WIN32OLE_TYPELIB.typelibs
139  *
140  * Returns the array of WIN32OLE_TYPELIB object.
141  *
142  * tlibs = WIN32OLE_TYPELIB.typelibs
143  *
144  */
145 static VALUE
146 foletypelib_s_typelibs(VALUE self)
147 {
148  HKEY htypelib, hguid;
149  DWORD i, j;
150  LONG err;
151  VALUE guid;
152  VALUE version;
153  VALUE name = Qnil;
154  VALUE typelibs = rb_ary_new();
155  VALUE typelib = Qnil;
156  HRESULT hr;
157  ITypeLib *pTypeLib;
158 
159  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
160  if(err != ERROR_SUCCESS) {
161  return typelibs;
162  }
163  for(i = 0; ; i++) {
164  guid = reg_enum_key(htypelib, i);
165  if (guid == Qnil)
166  break;
167  err = reg_open_vkey(htypelib, guid, &hguid);
168  if (err != ERROR_SUCCESS)
169  continue;
170  for(j = 0; ; j++) {
171  version = reg_enum_key(hguid, j);
172  if (version == Qnil)
173  break;
174  if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) {
175  hr = oletypelib_from_guid(guid, version, &pTypeLib);
176  if (SUCCEEDED(hr)) {
177  typelib = create_win32ole_typelib(pTypeLib);
178  rb_ary_push(typelibs, typelib);
179  }
180  }
181  }
182  RegCloseKey(hguid);
183  }
184  RegCloseKey(htypelib);
185  return typelibs;
186 }
187 
188 static VALUE
189 oletypelib_set_member(VALUE self, ITypeLib *pTypeLib)
190 {
191  struct oletypelibdata *ptlib;
192  TypedData_Get_Struct(self, struct oletypelibdata, &oletypelib_datatype, ptlib);
193  ptlib->pTypeLib = pTypeLib;
194  return self;
195 }
196 
197 static void
198 oletypelib_free(void *ptr)
199 {
200  struct oletypelibdata *poletypelib = ptr;
201  OLE_FREE(poletypelib->pTypeLib);
202  free(poletypelib);
203 }
204 
205 static size_t
206 oletypelib_size(const void *ptr)
207 {
208  return ptr ? sizeof(struct oletypelibdata) : 0;
209 }
210 
211 static VALUE
212 foletypelib_s_allocate(VALUE klass)
213 {
214  struct oletypelibdata *poletypelib;
215  VALUE obj;
216  ole_initialize();
217  obj = TypedData_Make_Struct(klass, struct oletypelibdata, &oletypelib_datatype, poletypelib);
218  poletypelib->pTypeLib = NULL;
219  return obj;
220 }
221 
222 VALUE
223 create_win32ole_typelib(ITypeLib *pTypeLib)
224 {
225  VALUE obj = foletypelib_s_allocate(cWIN32OLE_TYPELIB);
226  oletypelib_set_member(obj, pTypeLib);
227  return obj;
228 }
229 
230 static VALUE
231 oletypelib_search_registry(VALUE self, VALUE typelib)
232 {
233  HKEY htypelib, hguid, hversion;
234  DWORD i, j;
235  LONG err;
236  VALUE found = Qfalse;
237  VALUE tlib;
238  VALUE guid;
239  VALUE ver;
240  HRESULT hr;
241  ITypeLib *pTypeLib;
242 
243  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
244  if(err != ERROR_SUCCESS) {
245  return Qfalse;
246  }
247  for(i = 0; !found; i++) {
248  guid = reg_enum_key(htypelib, i);
249  if (guid == Qnil)
250  break;
251  err = reg_open_vkey(htypelib, guid, &hguid);
252  if (err != ERROR_SUCCESS)
253  continue;
254  for(j = 0; found == Qfalse; j++) {
255  ver = reg_enum_key(hguid, j);
256  if (ver == Qnil)
257  break;
258  err = reg_open_vkey(hguid, ver, &hversion);
259  if (err != ERROR_SUCCESS)
260  continue;
261  tlib = reg_get_val(hversion, NULL);
262  if (tlib == Qnil) {
263  RegCloseKey(hversion);
264  continue;
265  }
266  if (rb_str_cmp(typelib, tlib) == 0) {
267  hr = oletypelib_from_guid(guid, ver, &pTypeLib);
268  if (SUCCEEDED(hr)) {
269  oletypelib_set_member(self, pTypeLib);
270  found = Qtrue;
271  }
272  }
273  RegCloseKey(hversion);
274  }
275  RegCloseKey(hguid);
276  }
277  RegCloseKey(htypelib);
278  return found;
279 }
280 
281 static void
282 oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr)
283 {
284  HRESULT hr;
285  hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr);
286  if (FAILED(hr)) {
288  "failed to get library attribute(TLIBATTR) from ITypeLib");
289  }
290 }
291 
292 static VALUE
293 oletypelib_search_registry2(VALUE self, VALUE args)
294 {
295  HKEY htypelib, hguid, hversion;
296  double fver;
297  DWORD j;
298  LONG err;
299  VALUE found = Qfalse;
300  VALUE tlib;
301  VALUE ver;
302  VALUE version_str;
303  VALUE version = Qnil;
304  VALUE typelib = Qnil;
305  HRESULT hr;
306  ITypeLib *pTypeLib;
307 
308  VALUE guid = rb_ary_entry(args, 0);
309  version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2));
310 
311  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
312  if(err != ERROR_SUCCESS) {
313  return Qfalse;
314  }
315  err = reg_open_vkey(htypelib, guid, &hguid);
316  if (err != ERROR_SUCCESS) {
317  RegCloseKey(htypelib);
318  return Qfalse;
319  }
320  if (version_str != Qnil) {
321  err = reg_open_vkey(hguid, version_str, &hversion);
322  if (err == ERROR_SUCCESS) {
323  tlib = reg_get_val(hversion, NULL);
324  if (tlib != Qnil) {
325  typelib = tlib;
326  version = version_str;
327  }
328  }
329  RegCloseKey(hversion);
330  } else {
331  fver = 0.0;
332  for(j = 0; ;j++) {
333  ver = reg_enum_key(hguid, j);
334  if (ver == Qnil)
335  break;
336  err = reg_open_vkey(hguid, ver, &hversion);
337  if (err != ERROR_SUCCESS)
338  continue;
339  tlib = reg_get_val(hversion, NULL);
340  if (tlib == Qnil) {
341  RegCloseKey(hversion);
342  continue;
343  }
344  if (fver < atof(StringValuePtr(ver))) {
345  fver = atof(StringValuePtr(ver));
346  version = ver;
347  typelib = tlib;
348  }
349  RegCloseKey(hversion);
350  }
351  }
352  RegCloseKey(hguid);
353  RegCloseKey(htypelib);
354  if (typelib != Qnil) {
355  hr = oletypelib_from_guid(guid, version, &pTypeLib);
356  if (SUCCEEDED(hr)) {
357  found = Qtrue;
358  oletypelib_set_member(self, pTypeLib);
359  }
360  }
361  return found;
362 }
363 
364 
365 /*
366  * call-seq:
367  * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object
368  *
369  * Returns a new WIN32OLE_TYPELIB object.
370  *
371  * The first argument <i>typelib</i> specifies OLE type library name or GUID or
372  * OLE library file.
373  * The second argument is major version or version of the type library.
374  * The third argument is minor version.
375  * The second argument and third argument are optional.
376  * If the first argument is type library name, then the second and third argument
377  * are ignored.
378  *
379  * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
380  * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}')
381  * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3)
382  * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
383  * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
384  * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library'
385  * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library'
386  * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library'
387  * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library'
388  * puts tlib5.name # -> 'Microsoft Shell Controls And Automation'
389  *
390  */
391 static VALUE
392 foletypelib_initialize(VALUE self, VALUE args)
393 {
394  VALUE found = Qfalse;
395  VALUE typelib = Qnil;
396  int len = 0;
397  OLECHAR * pbuf;
398  ITypeLib *pTypeLib;
399  HRESULT hr = S_OK;
400 
401  len = RARRAY_LEN(args);
402  rb_check_arity(len, 1, 3);
403 
404  typelib = rb_ary_entry(args, 0);
405 
406  SafeStringValue(typelib);
407 
408  found = oletypelib_search_registry(self, typelib);
409  if (found == Qfalse) {
410  found = oletypelib_search_registry2(self, args);
411  }
412  if (found == Qfalse) {
413  pbuf = ole_vstr2wc(typelib);
414  hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
415  SysFreeString(pbuf);
416  if (SUCCEEDED(hr)) {
417  found = Qtrue;
418  oletypelib_set_member(self, pTypeLib);
419  }
420  }
421 
422  if (found == Qfalse) {
423  rb_raise(eWIN32OLERuntimeError, "not found type library `%s`",
424  StringValuePtr(typelib));
425  }
426  return self;
427 }
428 
429 /*
430  * call-seq:
431  * WIN32OLE_TYPELIB#guid -> The guid string.
432  *
433  * Returns guid string which specifies type library.
434  *
435  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
436  * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}'
437  */
438 static VALUE
439 foletypelib_guid(VALUE self)
440 {
441  ITypeLib *pTypeLib;
442  OLECHAR bstr[80];
443  VALUE guid = Qnil;
444  int len;
445  TLIBATTR *pTLibAttr;
446 
447  pTypeLib = itypelib(self);
448  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
449  len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
450  if (len > 3) {
451  guid = ole_wc2vstr(bstr, FALSE);
452  }
453  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
454  return guid;
455 }
456 
457 /*
458  * call-seq:
459  * WIN32OLE_TYPELIB#name -> The type library name
460  *
461  * Returns the type library name.
462  *
463  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
464  * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library'
465  */
466 static VALUE
467 foletypelib_name(VALUE self)
468 {
469  ITypeLib *pTypeLib;
470  HRESULT hr;
471  BSTR bstr;
472  VALUE name;
473  pTypeLib = itypelib(self);
474  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
475  NULL, &bstr, NULL, NULL);
476 
477  if (FAILED(hr)) {
478  ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib");
479  }
480  name = WC2VSTR(bstr);
481  return name;
482 }
483 
484 static VALUE
485 make_version_str(VALUE major, VALUE minor)
486 {
487  VALUE version_str = Qnil;
488  VALUE minor_str = Qnil;
489  if (major == Qnil) {
490  return Qnil;
491  }
492  version_str = rb_String(major);
493  if (minor != Qnil) {
494  minor_str = rb_String(minor);
495  rb_str_cat2(version_str, ".");
496  rb_str_append(version_str, minor_str);
497  }
498  return version_str;
499 }
500 
501 /*
502  * call-seq:
503  * WIN32OLE_TYPELIB#version -> The type library version String object.
504  *
505  * Returns the type library version.
506  *
507  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
508  * puts tlib.version #-> "1.3"
509  */
510 static VALUE
511 foletypelib_version(VALUE self)
512 {
513  TLIBATTR *pTLibAttr;
514  ITypeLib *pTypeLib;
515  VALUE version;
516 
517  pTypeLib = itypelib(self);
518  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
519  version = rb_sprintf("%d.%d", pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum);
520  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
521  return version;
522 }
523 
524 /*
525  * call-seq:
526  * WIN32OLE_TYPELIB#major_version -> The type library major version.
527  *
528  * Returns the type library major version.
529  *
530  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
531  * puts tlib.major_version # -> 1
532  */
533 static VALUE
534 foletypelib_major_version(VALUE self)
535 {
536  TLIBATTR *pTLibAttr;
537  VALUE major;
538  ITypeLib *pTypeLib;
539  pTypeLib = itypelib(self);
540  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
541 
542  major = RB_INT2NUM(pTLibAttr->wMajorVerNum);
543  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
544  return major;
545 }
546 
547 /*
548  * call-seq:
549  * WIN32OLE_TYPELIB#minor_version -> The type library minor version.
550  *
551  * Returns the type library minor version.
552  *
553  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
554  * puts tlib.minor_version # -> 3
555  */
556 static VALUE
557 foletypelib_minor_version(VALUE self)
558 {
559  TLIBATTR *pTLibAttr;
560  VALUE minor;
561  ITypeLib *pTypeLib;
562  pTypeLib = itypelib(self);
563  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
564  minor = RB_INT2NUM(pTLibAttr->wMinorVerNum);
565  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
566  return minor;
567 }
568 
569 /*
570  * call-seq:
571  * WIN32OLE_TYPELIB#path -> The type library file path.
572  *
573  * Returns the type library file path.
574  *
575  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
576  * puts tlib.path #-> 'C:\...\EXCEL9.OLB'
577  */
578 static VALUE
579 foletypelib_path(VALUE self)
580 {
581  TLIBATTR *pTLibAttr;
582  HRESULT hr = S_OK;
583  BSTR bstr;
584  LCID lcid = cWIN32OLE_lcid;
585  VALUE path;
586  ITypeLib *pTypeLib;
587 
588  pTypeLib = itypelib(self);
589  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
590  hr = QueryPathOfRegTypeLib(&pTLibAttr->guid,
591  pTLibAttr->wMajorVerNum,
592  pTLibAttr->wMinorVerNum,
593  lcid,
594  &bstr);
595  if (FAILED(hr)) {
596  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
597  ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib");
598  }
599 
600  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
601  path = WC2VSTR(bstr);
602  return path;
603 }
604 
605 /*
606  * call-seq:
607  * WIN32OLE_TYPELIB#visible?
608  *
609  * Returns true if the type library information is not hidden.
610  * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN,
611  * the method returns false, otherwise, returns true.
612  * If the method fails to access the TLIBATTR information, then
613  * WIN32OLERuntimeError is raised.
614  *
615  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
616  * tlib.visible? # => true
617  */
618 static VALUE
619 foletypelib_visible(VALUE self)
620 {
621  ITypeLib *pTypeLib = NULL;
622  VALUE visible = Qtrue;
623  TLIBATTR *pTLibAttr;
624 
625  pTypeLib = itypelib(self);
626  oletypelib_get_libattr(pTypeLib, &pTLibAttr);
627 
628  if ((pTLibAttr->wLibFlags == 0) ||
629  (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) ||
630  (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) {
631  visible = Qfalse;
632  }
633  pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
634  return visible;
635 }
636 
637 /*
638  * call-seq:
639  * WIN32OLE_TYPELIB#library_name
640  *
641  * Returns library name.
642  * If the method fails to access library name, WIN32OLERuntimeError is raised.
643  *
644  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
645  * tlib.library_name # => Excel
646  */
647 static VALUE
648 foletypelib_library_name(VALUE self)
649 {
650  HRESULT hr;
651  ITypeLib *pTypeLib = NULL;
652  VALUE libname = Qnil;
653  BSTR bstr;
654 
655  pTypeLib = itypelib(self);
656  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
657  &bstr, NULL, NULL, NULL);
658  if (FAILED(hr)) {
659  ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name");
660  }
661  libname = WC2VSTR(bstr);
662  return libname;
663 }
664 
665 static VALUE
666 ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes)
667 {
668  long count;
669  int i;
670  HRESULT hr;
671  BSTR bstr;
672  ITypeInfo *pTypeInfo;
673  VALUE type;
674 
675  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
676  for (i = 0; i < count; i++) {
677  hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
678  &bstr, NULL, NULL, NULL);
679  if (FAILED(hr))
680  continue;
681 
682  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
683  if (FAILED(hr))
684  continue;
685 
686  type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr));
687 
688  rb_ary_push(classes, type);
689  OLE_RELEASE(pTypeInfo);
690  }
691  return classes;
692 }
693 
694 static VALUE
695 typelib_file_from_typelib(VALUE ole)
696 {
697  HKEY htypelib, hclsid, hversion, hlang;
698  double fver;
699  DWORD i, j, k;
700  LONG err;
701  BOOL found = FALSE;
702  VALUE typelib;
703  VALUE file = Qnil;
704  VALUE clsid;
705  VALUE ver;
706  VALUE lang;
707 
708  err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
709  if(err != ERROR_SUCCESS) {
710  return Qnil;
711  }
712  for(i = 0; !found; i++) {
713  clsid = reg_enum_key(htypelib, i);
714  if (clsid == Qnil)
715  break;
716  err = reg_open_vkey(htypelib, clsid, &hclsid);
717  if (err != ERROR_SUCCESS)
718  continue;
719  fver = 0;
720  for(j = 0; !found; j++) {
721  ver = reg_enum_key(hclsid, j);
722  if (ver == Qnil)
723  break;
724  err = reg_open_vkey(hclsid, ver, &hversion);
725  if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
726  continue;
727  fver = atof(StringValuePtr(ver));
728  typelib = reg_get_val(hversion, NULL);
729  if (typelib == Qnil)
730  continue;
731  if (rb_str_cmp(typelib, ole) == 0) {
732  for(k = 0; !found; k++) {
733  lang = reg_enum_key(hversion, k);
734  if (lang == Qnil)
735  break;
736  err = reg_open_vkey(hversion, lang, &hlang);
737  if (err == ERROR_SUCCESS) {
738  if ((file = reg_get_typelib_file_path(hlang)) != Qnil)
739  found = TRUE;
740  RegCloseKey(hlang);
741  }
742  }
743  }
744  RegCloseKey(hversion);
745  }
746  RegCloseKey(hclsid);
747  }
748  RegCloseKey(htypelib);
749  return file;
750 }
751 
752 static VALUE
753 typelib_file_from_clsid(VALUE ole)
754 {
755  HKEY hroot, hclsid;
756  LONG err;
757  VALUE typelib;
758  char path[MAX_PATH + 1];
759 
760  err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot);
761  if (err != ERROR_SUCCESS) {
762  return Qnil;
763  }
764  err = reg_open_key(hroot, StringValuePtr(ole), &hclsid);
765  if (err != ERROR_SUCCESS) {
766  RegCloseKey(hroot);
767  return Qnil;
768  }
769  typelib = reg_get_val2(hclsid, "InprocServer32");
770  RegCloseKey(hroot);
771  RegCloseKey(hclsid);
772  if (typelib != Qnil) {
773  ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path));
774  path[MAX_PATH] = '\0';
775  typelib = rb_str_new2(path);
776  }
777  return typelib;
778 }
779 
780 VALUE
782 {
783  VALUE file = typelib_file_from_clsid(ole);
784  if (file != Qnil) {
785  return file;
786  }
787  return typelib_file_from_typelib(ole);
788 }
789 
790 
791 /*
792  * call-seq:
793  * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library.
794  *
795  * Returns the type library file path.
796  *
797  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
798  * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...]
799  */
800 static VALUE
801 foletypelib_ole_types(VALUE self)
802 {
803  ITypeLib *pTypeLib = NULL;
804  VALUE classes = rb_ary_new();
805  pTypeLib = itypelib(self);
806  ole_types_from_typelib(pTypeLib, classes);
807  return classes;
808 }
809 
810 /*
811  * call-seq:
812  * WIN32OLE_TYPELIB#inspect -> String
813  *
814  * Returns the type library name with class name.
815  *
816  * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
817  * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>"
818  */
819 static VALUE
820 foletypelib_inspect(VALUE self)
821 {
822  return default_inspect(self, "WIN32OLE_TYPELIB");
823 }
824 
825 void
827 {
828  cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject);
829  rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0);
830  rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate);
831  rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2);
832  rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0);
833  rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0);
834  rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0);
835  rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0);
836  rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0);
837  rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0);
838  rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0);
839  rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types");
840  rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0);
841  rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0);
842  rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name");
843  rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0);
844 }
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
LCID cWIN32OLE_lcid
Definition: win32ole.h:116
int count
Definition: encoding.c:56
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define Qtrue
Definition: ruby.h:437
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
ITypeLib * itypelib(VALUE self)
#define rb_check_arity
Definition: intern.h:298
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2999
LPWSTR ole_vstr2wc(VALUE vstr)
Definition: win32ole.c:864
VALUE rb_String(VALUE)
Equivalent to Kernel#String in Ruby.
Definition: object.c:3560
VALUE cWIN32OLE_TYPELIB
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void ole_initialize(void)
Definition: win32ole.c:812
VALUE reg_get_val(HKEY hkey, const char *subkey)
Definition: win32ole.c:1724
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3159
#define RB_INT2NUM(x)
Definition: ruby.h:1526
VALUE create_win32ole_typelib(ITypeLib *pTypeLib)
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
VALUE default_inspect(VALUE self, const char *class_name)
Definition: win32ole.c:1344
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
IUnknown DWORD
Definition: win32ole.c:32
VALUE reg_get_val2(HKEY hkey, const char *subkey)
Definition: win32ole.c:1752
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_ary_new(void)
Definition: array.c:499
VALUE typelib_file(VALUE ole)
LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
Definition: win32ole.c:1697
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
#define WC2VSTR(x)
Definition: win32ole.h:130
#define Qfalse
Definition: ruby.h:436
#define rb_str_new2
Definition: intern.h:835
int err
Definition: win32.c:135
LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
Definition: win32ole.c:1703
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
#define TRUE
Definition: nkf.h:175
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
ITypeLib * pTypeLib
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
register unsigned int len
Definition: zonetab.h:51
#define OLE_RELEASE(X)
Definition: win32ole.h:98
void Init_win32ole_typelib(void)
VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree)
Definition: win32ole.c:945
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
VALUE reg_enum_key(HKEY hkey, DWORD i)
Definition: win32ole.c:1709
static UINT LCID lcid
Definition: win32ole.c:86
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
#define SafeStringValue(v)
Definition: ruby.h:574
const char * name
Definition: nkf.c:208
#define StringValuePtr(v)
Definition: ruby.h:570
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2900
VALUE create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name)
free(psz)
#define OLE_FREE(x)
Definition: win32ole.h:99