Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
win32ole_record.c
Go to the documentation of this file.
1#include "win32ole.h"
2
4 IRecordInfo *pri;
5 void *pdata;
6};
7
8static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri);
9static int hash2olerec(VALUE key, VALUE val, VALUE rec);
10static void olerecord_free(void *pvar);
11static size_t olerecord_size(const void *ptr);
12static VALUE folerecord_s_allocate(VALUE klass);
13static VALUE folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj);
14static VALUE folerecord_to_h(VALUE self);
15static VALUE folerecord_typename(VALUE self);
16static VALUE olerecord_ivar_get(VALUE self, VALUE name);
17static VALUE olerecord_ivar_set(VALUE self, VALUE name, VALUE val);
18static VALUE folerecord_method_missing(int argc, VALUE *argv, VALUE self);
19static VALUE folerecord_ole_instance_variable_get(VALUE self, VALUE name);
20static VALUE folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val);
21static VALUE folerecord_inspect(VALUE self);
22
23static const rb_data_type_t olerecord_datatype = {
24 "win32ole_record",
25 {NULL, olerecord_free, olerecord_size,},
27};
28
29static HRESULT
30recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri)
31{
32
33 unsigned int count;
34 unsigned int i;
35 ITypeInfo *pTypeInfo;
36 HRESULT hr = OLE_E_LAST;
37 BSTR bstr;
38
39 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
40 for (i = 0; i < count; i++) {
41 hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
42 &bstr, NULL, NULL, NULL);
43 if (FAILED(hr))
44 continue;
45
46 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
47 if (FAILED(hr))
48 continue;
49
50 if (rb_str_cmp(WC2VSTR(bstr), name) == 0) {
51 hr = GetRecordInfoFromTypeInfo(pTypeInfo, ppri);
52 OLE_RELEASE(pTypeInfo);
53 return hr;
54 }
55 OLE_RELEASE(pTypeInfo);
56 }
57 hr = OLE_E_LAST;
58 return hr;
59}
60
61static int
62hash2olerec(VALUE key, VALUE val, VALUE rec)
63{
64 VARIANT var;
65 OLECHAR *pbuf;
66 struct olerecorddata *prec;
67 IRecordInfo *pri;
68 HRESULT hr;
69
70 if (val != Qnil) {
71 TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
72 pri = prec->pri;
73 VariantInit(&var);
74 ole_val2variant(val, &var);
75 pbuf = ole_vstr2wc(key);
76 hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, prec->pdata, pbuf, &var);
77 SysFreeString(pbuf);
78 VariantClear(&var);
79 if (FAILED(hr)) {
80 ole_raise(hr, eWIN32OLERuntimeError, "failed to putfield of `%s`", StringValuePtr(key));
81 }
82 }
83 return ST_CONTINUE;
84}
85
86void
87ole_rec2variant(VALUE rec, VARIANT *var)
88{
89 struct olerecorddata *prec;
90 ULONG size = 0;
91 IRecordInfo *pri;
92 HRESULT hr;
93 VALUE fields;
94 TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
95 pri = prec->pri;
96 if (pri) {
97 hr = pri->lpVtbl->GetSize(pri, &size);
98 if (FAILED(hr)) {
99 ole_raise(hr, eWIN32OLERuntimeError, "failed to get size for allocation of VT_RECORD object");
100 }
101 if (prec->pdata) {
102 free(prec->pdata);
103 }
104 prec->pdata = ALLOC_N(char, size);
105 if (!prec->pdata) {
106 rb_raise(rb_eRuntimeError, "failed to memory allocation of %lu bytes", (unsigned long)size);
107 }
108 hr = pri->lpVtbl->RecordInit(pri, prec->pdata);
109 if (FAILED(hr)) {
110 ole_raise(hr, eWIN32OLERuntimeError, "failed to initialize VT_RECORD object");
111 }
112 fields = folerecord_to_h(rec);
113 rb_hash_foreach(fields, hash2olerec, rec);
114 V_RECORDINFO(var) = pri;
115 V_RECORD(var) = prec->pdata;
116 V_VT(var) = VT_RECORD;
117 } else {
118 rb_raise(eWIN32OLERuntimeError, "failed to retrieve IRecordInfo interface");
119 }
120}
121
122void
123olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec)
124{
125 HRESULT hr;
126 BSTR bstr;
127 BSTR *bstrs;
128 ULONG count = 0;
129 ULONG i;
130 VALUE fields;
131 VALUE val;
132 VARIANT var;
133 void *pdata = NULL;
134 struct olerecorddata *pvar;
135
136 TypedData_Get_Struct(obj, struct olerecorddata, &olerecord_datatype, pvar);
138 OLE_RELEASE(pvar->pri);
139 pvar->pri = pri;
140
141 hr = pri->lpVtbl->GetName(pri, &bstr);
142 if (SUCCEEDED(hr)) {
143 rb_ivar_set(obj, rb_intern("typename"), WC2VSTR(bstr));
144 }
145
146 hr = pri->lpVtbl->GetFieldNames(pri, &count, NULL);
147 if (FAILED(hr) || count == 0)
148 return;
149 bstrs = ALLOCA_N(BSTR, count);
150 hr = pri->lpVtbl->GetFieldNames(pri, &count, bstrs);
151 if (FAILED(hr)) {
152 return;
153 }
154
155 fields = rb_hash_new();
156 rb_ivar_set(obj, rb_intern("fields"), fields);
157 for (i = 0; i < count; i++) {
158 pdata = NULL;
159 VariantInit(&var);
160 val = Qnil;
161 if (prec) {
162 hr = pri->lpVtbl->GetFieldNoCopy(pri, prec, bstrs[i], &var, &pdata);
163 if (SUCCEEDED(hr)) {
164 val = ole_variant2val(&var);
165 }
166 }
167 rb_hash_aset(fields, WC2VSTR(bstrs[i]), val);
168 }
169}
170
171VALUE
172create_win32ole_record(IRecordInfo *pri, void *prec)
173{
174 VALUE obj = folerecord_s_allocate(cWIN32OLE_RECORD);
175 olerecord_set_ivar(obj, pri, prec);
176 return obj;
177}
178
179/*
180 * Document-class: WIN32OLE_RECORD
181 *
182 * <code>WIN32OLE_RECORD</code> objects represents VT_RECORD OLE variant.
183 * Win32OLE returns WIN32OLE_RECORD object if the result value of invoking
184 * OLE methods.
185 *
186 * If COM server in VB.NET ComServer project is the following:
187 *
188 * Imports System.Runtime.InteropServices
189 * Public Class ComClass
190 * Public Structure Book
191 * <MarshalAs(UnmanagedType.BStr)> _
192 * Public title As String
193 * Public cost As Integer
194 * End Structure
195 * Public Function getBook() As Book
196 * Dim book As New Book
197 * book.title = "The Ruby Book"
198 * book.cost = 20
199 * Return book
200 * End Function
201 * End Class
202 *
203 * then, you can retrieve getBook return value from the following
204 * Ruby script:
205 *
206 * require 'win32ole'
207 * obj = WIN32OLE.new('ComServer.ComClass')
208 * book = obj.getBook
209 * book.class # => WIN32OLE_RECORD
210 * book.title # => "The Ruby Book"
211 * book.cost # => 20
212 *
213 */
214
215static void
216olerecord_free(void *ptr) {
217 struct olerecorddata *pvar = ptr;
218 OLE_FREE(pvar->pri);
219 if (pvar->pdata) {
220 free(pvar->pdata);
221 }
222 free(pvar);
223}
224
225static size_t
226olerecord_size(const void *ptr)
227{
228 const struct olerecorddata *pvar = ptr;
229 size_t s = 0;
230 ULONG size = 0;
231 HRESULT hr;
232 if (ptr) {
233 s += sizeof(struct olerecorddata);
234 if (pvar->pri) {
235 hr = pvar->pri->lpVtbl->GetSize(pvar->pri, &size);
236 if (SUCCEEDED(hr)) {
237 s += size;
238 }
239 }
240 }
241 return s;
242}
243
244static VALUE
245folerecord_s_allocate(VALUE klass) {
246 VALUE obj = Qnil;
247 struct olerecorddata *pvar;
248 obj = TypedData_Make_Struct(klass, struct olerecorddata, &olerecord_datatype, pvar);
249 pvar->pri = NULL;
250 pvar->pdata = NULL;
251 return obj;
252}
253
254/*
255 * call-seq:
256 * WIN32OLE_RECORD.new(typename, obj) -> WIN32OLE_RECORD object
257 *
258 * Returns WIN32OLE_RECORD object. The first argument is struct name (String
259 * or Symbol).
260 * The second parameter obj should be WIN32OLE object or WIN32OLE_TYPELIB object.
261 * If COM server in VB.NET ComServer project is the following:
262 *
263 * Imports System.Runtime.InteropServices
264 * Public Class ComClass
265 * Public Structure Book
266 * <MarshalAs(UnmanagedType.BStr)> _
267 * Public title As String
268 * Public cost As Integer
269 * End Structure
270 * End Class
271 *
272 * then, you can create WIN32OLE_RECORD object is as following:
273 *
274 * require 'win32ole'
275 * obj = WIN32OLE.new('ComServer.ComClass')
276 * book1 = WIN32OLE_RECORD.new('Book', obj) # => WIN32OLE_RECORD object
277 * tlib = obj.ole_typelib
278 * book2 = WIN32OLE_RECORD.new('Book', tlib) # => WIN32OLE_RECORD object
279 *
280 */
281static VALUE
282folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
283 HRESULT hr;
284 ITypeLib *pTypeLib = NULL;
285 IRecordInfo *pri = NULL;
286
287 if (!RB_TYPE_P(typename, T_STRING) && !RB_TYPE_P(typename, T_SYMBOL)) {
288 rb_raise(rb_eArgError, "1st argument should be String or Symbol");
289 }
290 if (RB_TYPE_P(typename, T_SYMBOL)) {
291 typename = rb_sym2str(typename);
292 }
293
294 hr = S_OK;
295 if(rb_obj_is_kind_of(oleobj, cWIN32OLE)) {
296 hr = typelib_from_val(oleobj, &pTypeLib);
297 } else if (rb_obj_is_kind_of(oleobj, cWIN32OLE_TYPELIB)) {
298 pTypeLib = itypelib(oleobj);
299 OLE_ADDREF(pTypeLib);
300 if (pTypeLib) {
301 hr = S_OK;
302 } else {
303 hr = E_FAIL;
304 }
305 } else {
306 rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE_TYPELIB object");
307 }
308
309 if (FAILED(hr)) {
310 ole_raise(hr, eWIN32OLERuntimeError, "fail to query ITypeLib interface");
311 }
312
313 hr = recordinfo_from_itypelib(pTypeLib, typename, &pri);
314 OLE_RELEASE(pTypeLib);
315 if (FAILED(hr)) {
316 ole_raise(hr, eWIN32OLERuntimeError, "fail to query IRecordInfo interface for `%s'", StringValuePtr(typename));
317 }
318
320
321 return self;
322}
323
324/*
325 * call-seq:
326 * WIN32OLE_RECORD#to_h #=> Ruby Hash object.
327 *
328 * Returns Ruby Hash object which represents VT_RECORD variable.
329 * The keys of Hash object are member names of VT_RECORD OLE variable and
330 * the values of Hash object are values of VT_RECORD OLE variable.
331 *
332 * If COM server in VB.NET ComServer project is the following:
333 *
334 * Imports System.Runtime.InteropServices
335 * Public Class ComClass
336 * Public Structure Book
337 * <MarshalAs(UnmanagedType.BStr)> _
338 * Public title As String
339 * Public cost As Integer
340 * End Structure
341 * Public Function getBook() As Book
342 * Dim book As New Book
343 * book.title = "The Ruby Book"
344 * book.cost = 20
345 * Return book
346 * End Function
347 * End Class
348 *
349 * then, the result of WIN32OLE_RECORD#to_h is the following:
350 *
351 * require 'win32ole'
352 * obj = WIN32OLE.new('ComServer.ComClass')
353 * book = obj.getBook
354 * book.to_h # => {"title"=>"The Ruby Book", "cost"=>20}
355 *
356 */
357static VALUE
358folerecord_to_h(VALUE self)
359{
360 return rb_ivar_get(self, rb_intern("fields"));
361}
362
363/*
364 * call-seq:
365 * WIN32OLE_RECORD#typename #=> String object
366 *
367 * Returns the type name of VT_RECORD OLE variable.
368 *
369 * If COM server in VB.NET ComServer project is the following:
370 *
371 * Imports System.Runtime.InteropServices
372 * Public Class ComClass
373 * Public Structure Book
374 * <MarshalAs(UnmanagedType.BStr)> _
375 * Public title As String
376 * Public cost As Integer
377 * End Structure
378 * Public Function getBook() As Book
379 * Dim book As New Book
380 * book.title = "The Ruby Book"
381 * book.cost = 20
382 * Return book
383 * End Function
384 * End Class
385 *
386 * then, the result of WIN32OLE_RECORD#typename is the following:
387 *
388 * require 'win32ole'
389 * obj = WIN32OLE.new('ComServer.ComClass')
390 * book = obj.getBook
391 * book.typename # => "Book"
392 *
393 */
394static VALUE
395folerecord_typename(VALUE self)
396{
397 return rb_ivar_get(self, rb_intern("typename"));
398}
399
400static VALUE
401olerecord_ivar_get(VALUE self, VALUE name)
402{
403 VALUE fields;
404 fields = rb_ivar_get(self, rb_intern("fields"));
405 return rb_hash_fetch(fields, name);
406}
407
408static VALUE
409olerecord_ivar_set(VALUE self, VALUE name, VALUE val)
410{
411 long len;
412 char *p;
413 VALUE fields;
415 p = RSTRING_PTR(name);
416 if (p[len-1] == '=') {
417 name = rb_str_subseq(name, 0, len-1);
418 }
419 fields = rb_ivar_get(self, rb_intern("fields"));
420 rb_hash_fetch(fields, name);
421 return rb_hash_aset(fields, name, val);
422}
423
424/*
425 * call-seq:
426 * WIN32OLE_RECORD#method_missing(name)
427 *
428 * Returns value specified by the member name of VT_RECORD OLE variable.
429 * Or sets value specified by the member name of VT_RECORD OLE variable.
430 * If the member name is not correct, KeyError exception is raised.
431 *
432 * If COM server in VB.NET ComServer project is the following:
433 *
434 * Imports System.Runtime.InteropServices
435 * Public Class ComClass
436 * Public Structure Book
437 * <MarshalAs(UnmanagedType.BStr)> _
438 * Public title As String
439 * Public cost As Integer
440 * End Structure
441 * End Class
442 *
443 * Then getting/setting value from Ruby is as the following:
444 *
445 * obj = WIN32OLE.new('ComServer.ComClass')
446 * book = WIN32OLE_RECORD.new('Book', obj)
447 * book.title # => nil ( book.method_missing(:title) is invoked. )
448 * book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. )
449 */
450static VALUE
451folerecord_method_missing(int argc, VALUE *argv, VALUE self)
452{
453 VALUE name;
454 rb_check_arity(argc, 1, 2);
455 name = rb_sym2str(argv[0]);
456
457#if SIZEOF_SIZE_T > SIZEOF_LONG
458 {
459 size_t n = strlen(StringValueCStr(name));
460 if (n >= LONG_MAX) {
461 rb_raise(rb_eRuntimeError, "too long member name");
462 }
463 }
464#endif
465
466 if (argc == 1) {
467 return olerecord_ivar_get(self, name);
468 } else if (argc == 2) {
469 return olerecord_ivar_set(self, name, argv[1]);
470 }
471 return Qnil;
472}
473
474/*
475 * call-seq:
476 * WIN32OLE_RECORD#ole_instance_variable_get(name)
477 *
478 * Returns value specified by the member name of VT_RECORD OLE object.
479 * If the member name is not correct, KeyError exception is raised.
480 * If you can't access member variable of VT_RECORD OLE object directly,
481 * use this method.
482 *
483 * If COM server in VB.NET ComServer project is the following:
484 *
485 * Imports System.Runtime.InteropServices
486 * Public Class ComClass
487 * Public Structure ComObject
488 * Public object_id As Ineger
489 * End Structure
490 * End Class
491 *
492 * and Ruby Object class has title attribute:
493 *
494 * then accessing object_id of ComObject from Ruby is as the following:
495 *
496 * srver = WIN32OLE.new('ComServer.ComClass')
497 * obj = WIN32OLE_RECORD.new('ComObject', server)
498 * # obj.object_id returns Ruby Object#object_id
499 * obj.ole_instance_variable_get(:object_id) # => nil
500 *
501 */
502static VALUE
503folerecord_ole_instance_variable_get(VALUE self, VALUE name)
504{
505 VALUE sname;
507 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
508 }
509 sname = name;
510 if (RB_TYPE_P(name, T_SYMBOL)) {
511 sname = rb_sym2str(name);
512 }
513 return olerecord_ivar_get(self, sname);
514}
515
516/*
517 * call-seq:
518 * WIN32OLE_RECORD#ole_instance_variable_set(name, val)
519 *
520 * Sets value specified by the member name of VT_RECORD OLE object.
521 * If the member name is not correct, KeyError exception is raised.
522 * If you can't set value of member of VT_RECORD OLE object directly,
523 * use this method.
524 *
525 * If COM server in VB.NET ComServer project is the following:
526 *
527 * Imports System.Runtime.InteropServices
528 * Public Class ComClass
529 * <MarshalAs(UnmanagedType.BStr)> _
530 * Public title As String
531 * Public cost As Integer
532 * End Class
533 *
534 * then setting value of the `title' member is as following:
535 *
536 * srver = WIN32OLE.new('ComServer.ComClass')
537 * obj = WIN32OLE_RECORD.new('Book', server)
538 * obj.ole_instance_variable_set(:title, "The Ruby Book")
539 *
540 */
541static VALUE
542folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val)
543{
544 VALUE sname;
546 rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
547 }
548 sname = name;
549 if (RB_TYPE_P(name, T_SYMBOL)) {
550 sname = rb_sym2str(name);
551 }
552 return olerecord_ivar_set(self, sname, val);
553}
554
555/*
556 * call-seq:
557 * WIN32OLE_RECORD#inspect -> String
558 *
559 * Returns the OLE struct name and member name and the value of member
560 *
561 * If COM server in VB.NET ComServer project is the following:
562 *
563 * Imports System.Runtime.InteropServices
564 * Public Class ComClass
565 * <MarshalAs(UnmanagedType.BStr)> _
566 * Public title As String
567 * Public cost As Integer
568 * End Class
569 *
570 * then
571 *
572 * srver = WIN32OLE.new('ComServer.ComClass')
573 * obj = WIN32OLE_RECORD.new('Book', server)
574 * obj.inspect # => <WIN32OLE_RECORD(ComClass) {"title" => nil, "cost" => nil}>
575 *
576 */
577static VALUE
578folerecord_inspect(VALUE self)
579{
580 VALUE tname;
581 VALUE field;
582 tname = folerecord_typename(self);
583 if (tname == Qnil) {
584 tname = rb_inspect(tname);
585 }
586 field = rb_inspect(folerecord_to_h(self));
587 return rb_sprintf("#<WIN32OLE_RECORD(%"PRIsVALUE") %"PRIsVALUE">",
588 tname,
589 field);
590}
591
593
594void
596{
597 cWIN32OLE_RECORD = rb_define_class("WIN32OLE_RECORD", rb_cObject);
598 rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate);
599 rb_define_method(cWIN32OLE_RECORD, "initialize", folerecord_initialize, 2);
600 rb_define_method(cWIN32OLE_RECORD, "to_h", folerecord_to_h, 0);
601 rb_define_method(cWIN32OLE_RECORD, "typename", folerecord_typename, 0);
602 rb_define_method(cWIN32OLE_RECORD, "method_missing", folerecord_method_missing, -1);
603 rb_define_method(cWIN32OLE_RECORD, "ole_instance_variable_get", folerecord_ole_instance_variable_get, 1);
604 rb_define_method(cWIN32OLE_RECORD, "ole_instance_variable_set", folerecord_ole_instance_variable_set, 2);
605 rb_define_method(cWIN32OLE_RECORD, "inspect", folerecord_inspect, 0);
606}
struct RIMemo * ptr
Definition: debug.c:65
#define free(x)
Definition: dln.c:52
int count
Definition: encoding.c:57
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
VALUE rb_eTypeError
Definition: error.c:924
VALUE rb_eRuntimeError
Definition: error.c:922
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
const char * name
Definition: nkf.c:208
void rb_hash_foreach(VALUE, int(*)(VALUE, VALUE, VALUE), VALUE)
#define NULL
#define RSTRING_LEN(str)
#define ALLOCA_N(type, n)
size_t strlen(const char *)
#define T_STRING
#define StringValuePtr(v)
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
const VALUE VALUE obj
#define RSTRING_PTR(str)
#define LONG_MAX
const char size_t n
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
__inline__ const void *__restrict__ size_t len
#define ALLOC_N(type, n)
#define RUBY_TYPED_FREE_IMMEDIATELY
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define PRIsVALUE
#define rb_intern(str)
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3228
unsigned int size
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
#define Qnil
#define RB_TYPE_P(obj, type)
VALUE rb_hash_fetch(VALUE, VALUE)
Definition: hash.c:2134
#define T_SYMBOL
#define TypedData_Make_Struct(klass, type, data_type, sval)
const VALUE * argv
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
#define rb_check_arity
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
VALUE rb_hash_new(void)
Definition: hash.c:1523
#define StringValueCStr(v)
unsigned long VALUE
Definition: ruby.h:102
IRecordInfo * pri
LPWSTR ole_vstr2wc(VALUE vstr)
Definition: win32ole.c:865
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1418
VALUE cWIN32OLE
Definition: win32ole.c:38
void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1249
HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib)
Definition: win32ole.c:3908
#define OLE_RELEASE(X)
Definition: win32ole.h:98
#define OLE_FREE(x)
Definition: win32ole.h:99
#define OLE_ADDREF(X)
Definition: win32ole.h:97
#define WC2VSTR(x)
Definition: win32ole.h:130
VALUE eWIN32OLERuntimeError
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
VALUE cWIN32OLE_RECORD
void Init_win32ole_record(void)
void ole_rec2variant(VALUE rec, VARIANT *var)
void olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec)
VALUE create_win32ole_record(IRecordInfo *pri, void *prec)
VALUE cWIN32OLE_TYPELIB
ITypeLib * itypelib(VALUE self)