windows_com 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +11 -0
- data/RELNOTES.md +9 -0
- data/examples/DesktopGadget.rbw +21 -0
- data/lib/windows_com.rb +4 -0
- data/lib/windows_com/common.rb +175 -0
- data/lib/windows_com/cruft.rb +173 -0
- data/lib/windows_com/libc.rb +14 -0
- data/lib/windows_com/ole.rb +367 -0
- data/lib/windows_com/oleaut.rb +204 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: '0194380637c6543160a0be00e072f4806e0cdd65'
|
4
|
+
data.tar.gz: 935c162da6720ad0ba281f0bc7d8d6573f82fcca
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ed3ab8238d527d4fd4b6770a70b39d0cf6690c1036ba4702d162ef230954bf293051bab645200dd0e6e69c5f091a45aec62e903a0c8d699c32f96294e952e1bb
|
7
|
+
data.tar.gz: 0e6994e3718acc2292accf0dca730484428dd2c22816580d07169c1d7926311108b209b192196b773af6de539647f629f6fdefc74789d790829e6b7e658ff6a2
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Radoslav Peev <rpeev@ymail.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
data/RELNOTES.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'windows_com'
|
2
|
+
|
3
|
+
include WindowsCOM
|
4
|
+
|
5
|
+
IDesktopGadget = COMInterface[IUnknown,
|
6
|
+
'c1646bc4-f298-4f91-a204-eb2dd1709d1a',
|
7
|
+
|
8
|
+
RunGadget: [[:buffer_in], :long]
|
9
|
+
]
|
10
|
+
|
11
|
+
DesktopGadget = COMFactory[IDesktopGadget, '924ccc1b-6562-4c85-8657-d177925222b6']
|
12
|
+
|
13
|
+
dg = DesktopGadget.new
|
14
|
+
|
15
|
+
begin
|
16
|
+
dg.RunGadget(
|
17
|
+
"#{ENV['ProgramFiles']}\\Windows Sidebar\\Gadgets\\Clock.Gadget\0".encode('utf-16le')
|
18
|
+
)
|
19
|
+
ensure
|
20
|
+
dg.Release
|
21
|
+
end
|
data/lib/windows_com.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
WINDOWS_COM_VERSION = '1.0.0'
|
4
|
+
|
5
|
+
WINDOWS_COM_OLE_INIT = true unless defined?(WINDOWS_COM_OLE_INIT)
|
6
|
+
|
7
|
+
module WindowsCOM
|
8
|
+
extend FFI::Library
|
9
|
+
|
10
|
+
def DetonateHresult(name, *args)
|
11
|
+
hresult = send(name, *args)
|
12
|
+
failed = FAILED(hresult)
|
13
|
+
|
14
|
+
raise "#{name} failed (hresult: #{format('%#08x', hresult)})" if failed
|
15
|
+
|
16
|
+
hresult
|
17
|
+
ensure
|
18
|
+
yield hresult if failed && block_given?
|
19
|
+
end
|
20
|
+
|
21
|
+
module_function \
|
22
|
+
:DetonateHresult
|
23
|
+
|
24
|
+
S_OK = 0
|
25
|
+
S_FALSE = 1
|
26
|
+
|
27
|
+
E_UNEXPECTED = 0x8000FFFF - 0x1_0000_0000
|
28
|
+
E_NOTIMPL = 0x80004001 - 0x1_0000_0000
|
29
|
+
E_OUTOFMEMORY = 0x8007000E - 0x1_0000_0000
|
30
|
+
E_INVALIDARG = 0x80070057 - 0x1_0000_0000
|
31
|
+
E_NOINTERFACE = 0x80004002 - 0x1_0000_0000
|
32
|
+
E_POINTER = 0x80004003 - 0x1_0000_0000
|
33
|
+
E_HANDLE = 0x80070006 - 0x1_0000_0000
|
34
|
+
E_ABORT = 0x80004004 - 0x1_0000_0000
|
35
|
+
E_FAIL = 0x80004005 - 0x1_0000_0000
|
36
|
+
E_ACCESSDENIED = 0x80070005 - 0x1_0000_0000
|
37
|
+
E_PENDING = 0x8000000A - 0x1_0000_0000
|
38
|
+
|
39
|
+
FACILITY_WIN32 = 7
|
40
|
+
|
41
|
+
ERROR_CANCELLED = 1223
|
42
|
+
|
43
|
+
def SUCCEEDED(hr)
|
44
|
+
hr >= 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def FAILED(hr)
|
48
|
+
hr < 0
|
49
|
+
end
|
50
|
+
|
51
|
+
def HRESULT_FROM_WIN32(x)
|
52
|
+
(x <= 0) ?
|
53
|
+
x :
|
54
|
+
(x & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000
|
55
|
+
end
|
56
|
+
|
57
|
+
module_function \
|
58
|
+
:SUCCEEDED,
|
59
|
+
:FAILED,
|
60
|
+
:HRESULT_FROM_WIN32
|
61
|
+
|
62
|
+
class GUID < FFI::Struct
|
63
|
+
layout \
|
64
|
+
:Data1, :ulong,
|
65
|
+
:Data2, :ushort,
|
66
|
+
:Data3, :ushort,
|
67
|
+
:Data4, [:uchar, 8]
|
68
|
+
end
|
69
|
+
|
70
|
+
def GUIDFromString(str)
|
71
|
+
raise 'Bad GUID format' unless str =~ /^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
|
72
|
+
|
73
|
+
guid = GUID.new
|
74
|
+
|
75
|
+
guid[:Data1] = str[0, 8].to_i(16)
|
76
|
+
guid[:Data2] = str[9, 4].to_i(16)
|
77
|
+
guid[:Data3] = str[14, 4].to_i(16)
|
78
|
+
guid[:Data4][0] = str[19, 2].to_i(16)
|
79
|
+
guid[:Data4][1] = str[21, 2].to_i(16)
|
80
|
+
str[24, 12].split('').each_slice(2).with_index { |a, i|
|
81
|
+
guid[:Data4][i + 2] = a.join('').to_i(16)
|
82
|
+
}
|
83
|
+
|
84
|
+
guid
|
85
|
+
end
|
86
|
+
|
87
|
+
def GUIDEqual(guid1, guid2)
|
88
|
+
windows_com_memcmp(guid1, guid2, GUID.size) == 0
|
89
|
+
end
|
90
|
+
|
91
|
+
module_function \
|
92
|
+
:GUIDFromString,
|
93
|
+
:GUIDEqual
|
94
|
+
|
95
|
+
class COMVptr_ < FFI::Struct
|
96
|
+
layout \
|
97
|
+
:lpVtbl, :pointer
|
98
|
+
end
|
99
|
+
|
100
|
+
module COMVtbl_
|
101
|
+
def self.[](parent_vtbl, spec)
|
102
|
+
spec.each { |name, sig|
|
103
|
+
sig[0].unshift(:pointer) # prepend *this* pointer
|
104
|
+
}
|
105
|
+
|
106
|
+
Class.new(FFI::Struct) {
|
107
|
+
const_set :ParentVtbl, parent_vtbl
|
108
|
+
|
109
|
+
const_set :Spec, {}
|
110
|
+
self::Spec.merge!(self::ParentVtbl::Spec) if self::ParentVtbl
|
111
|
+
self::Spec.merge!(spec)
|
112
|
+
|
113
|
+
layout_args = self::Spec.map { |name, sig|
|
114
|
+
params, ret = sig
|
115
|
+
[name, callback(params, ret)]
|
116
|
+
}
|
117
|
+
layout_args.flatten!
|
118
|
+
layout(*layout_args)
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
module COMInterface_
|
124
|
+
def self.[](vtbl, siid)
|
125
|
+
Class.new {
|
126
|
+
const_set :Vtbl, vtbl
|
127
|
+
const_set :IID, WindowsCOM::GUIDFromString(siid)
|
128
|
+
|
129
|
+
def initialize(pointer)
|
130
|
+
@vptr = COMVptr_.new(pointer)
|
131
|
+
@vtbl = self.class::Vtbl.new(@vptr[:lpVtbl])
|
132
|
+
end
|
133
|
+
|
134
|
+
attr_reader :vptr, :vtbl
|
135
|
+
|
136
|
+
self::Vtbl.members.each { |name, sig|
|
137
|
+
define_method(name) { |*args|
|
138
|
+
hresult = @vtbl[name].call(@vptr, *args)
|
139
|
+
|
140
|
+
raise "#{self}.#{name} failed (hresult: #{format('%#08x', hresult)})" if
|
141
|
+
WindowsCOM::FAILED(hresult)
|
142
|
+
|
143
|
+
hresult
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module COMInterface
|
151
|
+
def self.[](parent_iface, siid, spec)
|
152
|
+
vtbl = COMVtbl_[(parent_iface) ? parent_iface::Vtbl : nil, spec]
|
153
|
+
|
154
|
+
COMInterface_[vtbl, siid]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
module COMFactory
|
159
|
+
def self.[](iface, sclsid)
|
160
|
+
Class.new(iface) {
|
161
|
+
const_set :CLSID, WindowsCOM::GUIDFromString(sclsid)
|
162
|
+
|
163
|
+
def initialize(clsctx = CLSCTX_INPROC)
|
164
|
+
FFI::MemoryPointer.new(:pointer) { |ppv|
|
165
|
+
DetonateHresult(:CoCreateInstance,
|
166
|
+
self.class::CLSID, nil, clsctx, self.class::IID, ppv
|
167
|
+
)
|
168
|
+
|
169
|
+
super(ppv.read_pointer)
|
170
|
+
}
|
171
|
+
end
|
172
|
+
}
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
__END__
|
2
|
+
module COMHelpers
|
3
|
+
def QueryInstance(klass)
|
4
|
+
instance = nil
|
5
|
+
|
6
|
+
FFI::MemoryPointer.new(:pointer) { |ppv|
|
7
|
+
QueryInterface(klass::IID, ppv)
|
8
|
+
|
9
|
+
instance = klass.new(ppv.read_pointer)
|
10
|
+
}
|
11
|
+
|
12
|
+
begin
|
13
|
+
yield instance; return self
|
14
|
+
ensure
|
15
|
+
instance.Release
|
16
|
+
end if block_given?
|
17
|
+
|
18
|
+
instance
|
19
|
+
end
|
20
|
+
|
21
|
+
def UseInstance(klass, name, *args)
|
22
|
+
instance = nil
|
23
|
+
|
24
|
+
FFI::MemoryPointer.new(:pointer) { |ppv|
|
25
|
+
send(name, *args, klass::IID, ppv)
|
26
|
+
|
27
|
+
yield instance = klass.new(ppv.read_pointer)
|
28
|
+
}
|
29
|
+
|
30
|
+
self
|
31
|
+
ensure
|
32
|
+
instance.Release if instance
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module COMCallback
|
37
|
+
def self.[](iface)
|
38
|
+
Class.new(FFI::Struct) {
|
39
|
+
send(:include, COMHelpers)
|
40
|
+
|
41
|
+
layout \
|
42
|
+
:lpVtbl, :pointer
|
43
|
+
|
44
|
+
def initialize(opts = {})
|
45
|
+
@vtbl, @refc = iface::VTBL.new, 1
|
46
|
+
|
47
|
+
@vtbl.members.each { |name|
|
48
|
+
@vtbl[name] = instance_variable_set("@fn#{name}",
|
49
|
+
FFI::Function.new(*@vtbl.class::SPEC[name].reverse, convention: :stdcall) { |*args|
|
50
|
+
send(name, *args[1..-1])
|
51
|
+
}
|
52
|
+
)
|
53
|
+
}
|
54
|
+
|
55
|
+
self[:lpVtbl] = @vtbl
|
56
|
+
|
57
|
+
begin
|
58
|
+
yield self
|
59
|
+
ensure
|
60
|
+
Release()
|
61
|
+
end if block_given?
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_reader :vtbl, :refc
|
65
|
+
|
66
|
+
def QueryInterface(riid, ppv)
|
67
|
+
if [IUnknown::IID, iface::IID].any? { |iid| windows_com_memcmp(riid, iid, iid.size) == 0 }
|
68
|
+
ppv.write_pointer(self)
|
69
|
+
else
|
70
|
+
ppv.write_pointer(0); return E_NOINTERFACE
|
71
|
+
end
|
72
|
+
|
73
|
+
AddRef(); S_OK
|
74
|
+
end
|
75
|
+
|
76
|
+
def AddRef
|
77
|
+
@refc += 1
|
78
|
+
end
|
79
|
+
|
80
|
+
def Release
|
81
|
+
@refc -= 1
|
82
|
+
end
|
83
|
+
|
84
|
+
(iface::VTBL.members - IUnknown::VTBL.members).each { |name|
|
85
|
+
define_method(name) { |*args|
|
86
|
+
E_NOTIMPL
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
module AnonymousFFIStructSupport
|
94
|
+
def [](k)
|
95
|
+
if members.include?(k)
|
96
|
+
super
|
97
|
+
elsif self[:_].members.include?(k)
|
98
|
+
self[:_][k]
|
99
|
+
else
|
100
|
+
self[:_][:_][k]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def []=(k, v)
|
105
|
+
if members.include?(k)
|
106
|
+
super
|
107
|
+
elsif self[:_].members.include?(k)
|
108
|
+
self[:_][k] = v
|
109
|
+
else
|
110
|
+
self[:_][:_][k] = v
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# PROPERTYKEY
|
116
|
+
def self.[](type, index)
|
117
|
+
new.tap { |key|
|
118
|
+
key[:fmtid].tap { |guid|
|
119
|
+
guid[:Data1] = 0x00000000 + index
|
120
|
+
guid[:Data2] = 0x7363
|
121
|
+
guid[:Data3] = 0x696e
|
122
|
+
[0x84, 0x41, 0x79, 0x8a, 0xcf, 0x5a, 0xeb, 0xb7].each_with_index { |part, i|
|
123
|
+
guid[:Data4][i] = part
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
key[:pid] = type
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
# PROPVARIANT
|
132
|
+
def ==(other) windows_com_memcmp(other, self, size) == 0 end
|
133
|
+
|
134
|
+
def self.[](t, *v) new.tap { |var| var.send("#{t}=", *v) } end
|
135
|
+
|
136
|
+
def bool; raise 'Wrong type tag.' unless self[:vt] == VT_BOOL; self[:boolVal] != 0 end
|
137
|
+
def bool=(bool) self[:vt] = VT_BOOL; self[:boolVal] = (bool) ? -1 : 0 end
|
138
|
+
|
139
|
+
def int; raise 'Wrong type tag.' unless self[:vt] == VT_I4; self[:intVal] end
|
140
|
+
def int=(int) self[:vt] = VT_I4; self[:intVal] = int end
|
141
|
+
|
142
|
+
def uint; raise 'Wrong type tag.' unless self[:vt] == VT_UI4; self[:uintVal] end
|
143
|
+
def uint=(uint) self[:vt] = VT_UI4; self[:uintVal] = uint end
|
144
|
+
|
145
|
+
def unknown
|
146
|
+
raise 'Wrong type tag.' unless self[:vt] == VT_UNKNOWN
|
147
|
+
|
148
|
+
yield Unknown.new(self[:punkVal])
|
149
|
+
ensure
|
150
|
+
Windows.PropVariantClear(self)
|
151
|
+
end
|
152
|
+
|
153
|
+
def unknown=(unknown) self[:vt] = VT_UNKNOWN; self[:punkVal] = unknown.pointer; unknown.AddRef end
|
154
|
+
|
155
|
+
def wstring; raise 'Wrong type tag.' unless self[:vt] == VT_LPWSTR; Windows.WCSTOMBS(self[:pwszVal]) end
|
156
|
+
|
157
|
+
def wstring=(string)
|
158
|
+
self[:vt] = VT_LPWSTR
|
159
|
+
|
160
|
+
FFI::MemoryPointer.new(:pointer) { |p|
|
161
|
+
Windows.DetonateHresult(:SHStrDup, string, p)
|
162
|
+
|
163
|
+
self[:pwszVal] = p.read_pointer
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
def decimal
|
168
|
+
raise 'Wrong type tag.' unless self[:vt] == VT_DECIMAL
|
169
|
+
|
170
|
+
Rational(self[:decVal][:Lo64], 10 ** self[:decVal][:scale]) + self[:decVal][:Hi32]
|
171
|
+
end
|
172
|
+
|
173
|
+
def decimal=(decimal) self[:vt] = VT_DECIMAL; self[:decVal][:Lo64] = decimal end
|
@@ -0,0 +1,367 @@
|
|
1
|
+
if __FILE__ == $0
|
2
|
+
require_relative 'common'
|
3
|
+
require_relative 'libc'
|
4
|
+
end
|
5
|
+
|
6
|
+
module WindowsCOM
|
7
|
+
ffi_lib 'ole32'
|
8
|
+
ffi_convention :stdcall
|
9
|
+
|
10
|
+
attach_function :OleInitialize, [:pointer], :long
|
11
|
+
attach_function :OleUninitialize, [], :void
|
12
|
+
|
13
|
+
def InitializeOle
|
14
|
+
DetonateHresult(:OleInitialize, nil)
|
15
|
+
|
16
|
+
STDERR.puts "OLE initialized" if $DEBUG
|
17
|
+
|
18
|
+
at_exit {
|
19
|
+
OleUninitialize()
|
20
|
+
|
21
|
+
STDERR.puts "OLE uninitialized" if $DEBUG
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
module_function \
|
26
|
+
:InitializeOle
|
27
|
+
|
28
|
+
InitializeOle() if WINDOWS_COM_OLE_INIT
|
29
|
+
|
30
|
+
attach_function :CoTaskMemAlloc, [:ulong], :pointer
|
31
|
+
attach_function :CoTaskMemFree, [:pointer], :void
|
32
|
+
|
33
|
+
class LARGE_INTEGER < FFI::Union
|
34
|
+
layout \
|
35
|
+
:_, Class.new(FFI::Struct) {
|
36
|
+
layout \
|
37
|
+
:LowPart, :ulong,
|
38
|
+
:HighPart, :long
|
39
|
+
},
|
40
|
+
|
41
|
+
:QuadPart, :long_long
|
42
|
+
end
|
43
|
+
|
44
|
+
class ULARGE_INTEGER < FFI::Union
|
45
|
+
layout \
|
46
|
+
:_, Class.new(FFI::Struct) {
|
47
|
+
layout \
|
48
|
+
:LowPart, :ulong,
|
49
|
+
:HighPart, :ulong
|
50
|
+
},
|
51
|
+
|
52
|
+
:QuadPart, :ulong_long
|
53
|
+
end
|
54
|
+
|
55
|
+
class DECIMAL < FFI::Struct
|
56
|
+
layout \
|
57
|
+
:wReserved, :ushort,
|
58
|
+
:scale, :uchar,
|
59
|
+
:sign, :uchar,
|
60
|
+
:Hi32, :ulong,
|
61
|
+
:Lo64, :ulong_long
|
62
|
+
end
|
63
|
+
|
64
|
+
class BLOB < FFI::Struct
|
65
|
+
layout \
|
66
|
+
:cbSize, :ulong,
|
67
|
+
:pBlobData, :pointer
|
68
|
+
end
|
69
|
+
|
70
|
+
class BSTRBLOB < FFI::Struct
|
71
|
+
layout \
|
72
|
+
:cbSize, :ulong,
|
73
|
+
:pData, :pointer
|
74
|
+
end
|
75
|
+
|
76
|
+
class FILETIME < FFI::Struct
|
77
|
+
layout \
|
78
|
+
:dwLowDateTime, :ulong,
|
79
|
+
:dwHighDateTime, :ulong
|
80
|
+
end
|
81
|
+
|
82
|
+
class CA < FFI::Struct
|
83
|
+
layout \
|
84
|
+
:cElems, :ulong,
|
85
|
+
:pElems, :pointer
|
86
|
+
end
|
87
|
+
|
88
|
+
VT_EMPTY = 0
|
89
|
+
VT_NULL = 1
|
90
|
+
VT_I2 = 2
|
91
|
+
VT_I4 = 3
|
92
|
+
VT_R4 = 4
|
93
|
+
VT_R8 = 5
|
94
|
+
VT_CY = 6
|
95
|
+
VT_DATE = 7
|
96
|
+
VT_BSTR = 8
|
97
|
+
VT_DISPATCH = 9
|
98
|
+
VT_ERROR = 10
|
99
|
+
VT_BOOL = 11
|
100
|
+
VT_VARIANT = 12
|
101
|
+
VT_UNKNOWN = 13
|
102
|
+
VT_DECIMAL = 14
|
103
|
+
VT_I1 = 16
|
104
|
+
VT_UI1 = 17
|
105
|
+
VT_UI2 = 18
|
106
|
+
VT_UI4 = 19
|
107
|
+
VT_I8 = 20
|
108
|
+
VT_UI8 = 21
|
109
|
+
VT_INT = 22
|
110
|
+
VT_UINT = 23
|
111
|
+
VT_VOID = 24
|
112
|
+
VT_HRESULT = 25
|
113
|
+
VT_PTR = 26
|
114
|
+
VT_SAFEARRAY = 27
|
115
|
+
VT_CARRAY = 28
|
116
|
+
VT_USERDEFINED = 29
|
117
|
+
VT_LPSTR = 30
|
118
|
+
VT_LPWSTR = 31
|
119
|
+
VT_FILETIME = 64
|
120
|
+
VT_BLOB = 65
|
121
|
+
VT_STREAM = 66
|
122
|
+
VT_STORAGE = 67
|
123
|
+
VT_STREAMED_OBJECT = 68
|
124
|
+
VT_STORED_OBJECT = 69
|
125
|
+
VT_BLOB_OBJECT = 70
|
126
|
+
VT_CF = 71
|
127
|
+
VT_CLSID = 72
|
128
|
+
VT_VECTOR = 0x1000
|
129
|
+
VT_ARRAY = 0x2000
|
130
|
+
VT_BYREF = 0x4000
|
131
|
+
VT_RESERVED = 0x8000
|
132
|
+
VT_ILLEGAL = 0xffff
|
133
|
+
VT_ILLEGALMASKED = 0xfff
|
134
|
+
VT_TYPEMASK = 0xff
|
135
|
+
|
136
|
+
class VARIANT < FFI::Union
|
137
|
+
layout \
|
138
|
+
:_, Class.new(FFI::Struct) {
|
139
|
+
layout \
|
140
|
+
:vt, :ushort,
|
141
|
+
:wReserved1, :ushort,
|
142
|
+
:wReserved2, :ushort,
|
143
|
+
:wReserved3, :ushort,
|
144
|
+
:_, Class.new(FFI::Union) {
|
145
|
+
layout \
|
146
|
+
:llVal, :long_long,
|
147
|
+
:lVal, :long,
|
148
|
+
:bVal, :uchar,
|
149
|
+
:iVal, :short,
|
150
|
+
:fltVal, :float,
|
151
|
+
:dblVal, :double,
|
152
|
+
:boolVal, :short,
|
153
|
+
:bool, :short,
|
154
|
+
:scode, :long,
|
155
|
+
:cyVal, :ulong_long,
|
156
|
+
:date, :double,
|
157
|
+
:bstrVal, :pointer,
|
158
|
+
:punkVal, :pointer,
|
159
|
+
:pdispVal, :pointer,
|
160
|
+
:parray, :pointer,
|
161
|
+
:pbVal, :pointer,
|
162
|
+
:piVal, :pointer,
|
163
|
+
:plVal, :pointer,
|
164
|
+
:pllVal, :pointer,
|
165
|
+
:pfltVal, :pointer,
|
166
|
+
:pdblVal, :pointer,
|
167
|
+
:pboolVal, :pointer,
|
168
|
+
:pbool, :pointer,
|
169
|
+
:pscode, :pointer,
|
170
|
+
:pcyVal, :pointer,
|
171
|
+
:pdate, :pointer,
|
172
|
+
:pbstrVal, :pointer,
|
173
|
+
:ppunkVal, :pointer,
|
174
|
+
:ppdispVal, :pointer,
|
175
|
+
:pparrayv, :pointer,
|
176
|
+
:pvarVal, :pointer,
|
177
|
+
:byref, :pointer,
|
178
|
+
:cVal, :char,
|
179
|
+
:uiVal, :ushort,
|
180
|
+
:ulVal, :ulong,
|
181
|
+
:ullVal, :ulong_long,
|
182
|
+
:intVal, :int,
|
183
|
+
:uintVal, :uint,
|
184
|
+
:pdecVal, :pointer,
|
185
|
+
:pcVal, :pointer,
|
186
|
+
:puiVal, :pointer,
|
187
|
+
:pulVal, :pointer,
|
188
|
+
:pullVal, :pointer,
|
189
|
+
:pintVal, :pointer,
|
190
|
+
:puintVal, :pointer,
|
191
|
+
:BRECORD, Class.new(FFI::Struct) {
|
192
|
+
layout \
|
193
|
+
:pvRecord, :pointer,
|
194
|
+
:pRecInfo, :pointer
|
195
|
+
}
|
196
|
+
}
|
197
|
+
},
|
198
|
+
|
199
|
+
:decVal, DECIMAL
|
200
|
+
end
|
201
|
+
|
202
|
+
class PROPERTYKEY < FFI::Struct
|
203
|
+
layout \
|
204
|
+
:fmtid, GUID,
|
205
|
+
:pid, :ulong
|
206
|
+
end
|
207
|
+
|
208
|
+
class PROPVARIANT < FFI::Union
|
209
|
+
layout \
|
210
|
+
:_, Class.new(FFI::Struct) {
|
211
|
+
layout \
|
212
|
+
:vt, :ushort,
|
213
|
+
:wReserved1, :ushort,
|
214
|
+
:wReserved2, :ushort,
|
215
|
+
:wReserved3, :ushort,
|
216
|
+
:_, Class.new(FFI::Union) {
|
217
|
+
layout \
|
218
|
+
:cVal, :char,
|
219
|
+
:bVal, :uchar,
|
220
|
+
:iVal, :short,
|
221
|
+
:uiVal, :ushort,
|
222
|
+
:lVal, :long,
|
223
|
+
:ulVal, :ulong,
|
224
|
+
:intVal, :int,
|
225
|
+
:uintVal, :uint,
|
226
|
+
:hVal, LARGE_INTEGER,
|
227
|
+
:uhVal, ULARGE_INTEGER,
|
228
|
+
:fltVal, :float,
|
229
|
+
:dblVal, :double,
|
230
|
+
:boolVal, :short,
|
231
|
+
:bool, :short,
|
232
|
+
:scode, :long,
|
233
|
+
:cyVal, :long_long,
|
234
|
+
:date, :double,
|
235
|
+
:filetime, FILETIME,
|
236
|
+
:puuid, :pointer,
|
237
|
+
:pclipdata, :pointer,
|
238
|
+
:bstrVal, :pointer,
|
239
|
+
:bstrblobVal, BSTRBLOB,
|
240
|
+
:blob, BLOB,
|
241
|
+
:pszVal, :pointer,
|
242
|
+
:pwszVal, :pointer,
|
243
|
+
:punkVal, :pointer,
|
244
|
+
:pdispVal, :pointer,
|
245
|
+
:pStream, :pointer,
|
246
|
+
:pStorage, :pointer,
|
247
|
+
:pVersionedStream, :pointer,
|
248
|
+
:parray, :pointer,
|
249
|
+
:cac, CA,
|
250
|
+
:caub, CA,
|
251
|
+
:cai, CA,
|
252
|
+
:caui, CA,
|
253
|
+
:cal, CA,
|
254
|
+
:caul, CA,
|
255
|
+
:cah, CA,
|
256
|
+
:cauh, CA,
|
257
|
+
:caflt, CA,
|
258
|
+
:cadbl, CA,
|
259
|
+
:cabool, CA,
|
260
|
+
:cascode, CA,
|
261
|
+
:cacy, CA,
|
262
|
+
:cadate, CA,
|
263
|
+
:cafiletime, CA,
|
264
|
+
:cauuid, CA,
|
265
|
+
:caclipdata, CA,
|
266
|
+
:cabstr, CA,
|
267
|
+
:cabstrblob, CA,
|
268
|
+
:calpstr, CA,
|
269
|
+
:calpwstr, CA,
|
270
|
+
:capropvar, CA,
|
271
|
+
:pcVal, :pointer,
|
272
|
+
:pbVal, :pointer,
|
273
|
+
:piVal, :pointer,
|
274
|
+
:puiVal, :pointer,
|
275
|
+
:plVal, :pointer,
|
276
|
+
:pulVal, :pointer,
|
277
|
+
:pintVal, :pointer,
|
278
|
+
:puintVal, :pointer,
|
279
|
+
:pfltVal, :pointer,
|
280
|
+
:pdblVal, :pointer,
|
281
|
+
:pboolVal, :pointer,
|
282
|
+
:pdecVal, :pointer,
|
283
|
+
:pscode, :pointer,
|
284
|
+
:pcyVal, :pointer,
|
285
|
+
:pdate, :pointer,
|
286
|
+
:pbstrVal, :pointer,
|
287
|
+
:ppunkVal, :pointer,
|
288
|
+
:ppdispVal, :pointer,
|
289
|
+
:pparray, :pointer,
|
290
|
+
:pvarVal, :pointer
|
291
|
+
}
|
292
|
+
},
|
293
|
+
|
294
|
+
:decVal, DECIMAL
|
295
|
+
end
|
296
|
+
|
297
|
+
attach_function :PropVariantClear, [:pointer], :long
|
298
|
+
|
299
|
+
CLSCTX_INPROC_SERVER = 0x1
|
300
|
+
CLSCTX_INPROC_HANDLER = 0x2
|
301
|
+
CLSCTX_LOCAL_SERVER = 0x4
|
302
|
+
CLSCTX_INPROC_SERVER16 = 0x8
|
303
|
+
CLSCTX_REMOTE_SERVER = 0x10
|
304
|
+
CLSCTX_INPROC_HANDLER16 = 0x20
|
305
|
+
CLSCTX_RESERVED1 = 0x40
|
306
|
+
CLSCTX_RESERVED2 = 0x80
|
307
|
+
CLSCTX_RESERVED3 = 0x100
|
308
|
+
CLSCTX_RESERVED4 = 0x200
|
309
|
+
CLSCTX_NO_CODE_DOWNLOAD = 0x400
|
310
|
+
CLSCTX_RESERVED5 = 0x800
|
311
|
+
CLSCTX_NO_CUSTOM_MARSHAL = 0x1000
|
312
|
+
CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000
|
313
|
+
CLSCTX_NO_FAILURE_LOG = 0x4000
|
314
|
+
CLSCTX_DISABLE_AAA = 0x8000
|
315
|
+
CLSCTX_ENABLE_AAA = 0x10000
|
316
|
+
CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000
|
317
|
+
CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000
|
318
|
+
CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000
|
319
|
+
CLSCTX_ENABLE_CLOAKING = 0x100000
|
320
|
+
CLSCTX_PS_DLL = -0x80000000
|
321
|
+
CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER
|
322
|
+
CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
|
323
|
+
CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
|
324
|
+
|
325
|
+
attach_function :CoCreateInstance, [:pointer, :pointer, :ulong, :pointer, :pointer], :long
|
326
|
+
|
327
|
+
IUnknown = COMInterface[nil,
|
328
|
+
'00000000-0000-0000-C000-000000000046',
|
329
|
+
|
330
|
+
QueryInterface: [[:pointer, :pointer], :long],
|
331
|
+
AddRef: [[], :ulong],
|
332
|
+
Release: [[], :ulong]
|
333
|
+
]
|
334
|
+
|
335
|
+
IDispatch = COMInterface[IUnknown,
|
336
|
+
'00020400-0000-0000-C000-000000000046',
|
337
|
+
|
338
|
+
GetTypeInfoCount: [[:pointer], :long],
|
339
|
+
GetTypeInfo: [[:uint, :ulong, :pointer], :long],
|
340
|
+
GetIDsOfNames: [[:pointer, :pointer, :uint, :ulong, :pointer], :long],
|
341
|
+
Invoke: [[:long, :pointer, :ulong, :ushort, :pointer, :pointer, :pointer, :pointer], :long]
|
342
|
+
]
|
343
|
+
|
344
|
+
IConnectionPointContainer = COMInterface[IUnknown,
|
345
|
+
'B196B284-BAB4-101A-B69C-00AA00341D07',
|
346
|
+
|
347
|
+
EnumConnectionPoints: [[:pointer], :long],
|
348
|
+
FindConnectionPoint: [[:pointer, :pointer], :long]
|
349
|
+
]
|
350
|
+
|
351
|
+
IConnectionPoint = COMInterface[IUnknown,
|
352
|
+
'B196B286-BAB4-101A-B69C-00AA00341D07',
|
353
|
+
|
354
|
+
GetConnectionInterface: [[:pointer], :long],
|
355
|
+
GetConnectionPointContainer: [[:pointer], :long],
|
356
|
+
Advise: [[:pointer, :pointer], :long],
|
357
|
+
Unadvise: [[:ulong], :long],
|
358
|
+
EnumConnections: [[:pointer], :long]
|
359
|
+
]
|
360
|
+
|
361
|
+
IObjectWithSite = COMInterface[IUnknown,
|
362
|
+
'FC4801A3-2BA9-11CF-A229-00AA003D7352',
|
363
|
+
|
364
|
+
SetSite: [[:pointer], :long],
|
365
|
+
GetSite: [[:pointer, :pointer], :long]
|
366
|
+
]
|
367
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
if __FILE__ == $0
|
2
|
+
require_relative 'common'
|
3
|
+
require_relative 'libc'
|
4
|
+
require_relative 'ole'
|
5
|
+
end
|
6
|
+
|
7
|
+
module WindowsCOM
|
8
|
+
ffi_lib 'oleaut32'
|
9
|
+
ffi_convention :stdcall
|
10
|
+
|
11
|
+
attach_function :SysAllocString, [:buffer_in], :pointer
|
12
|
+
attach_function :SysFreeString, [:pointer], :void
|
13
|
+
attach_function :SysStringLen, [:pointer], :uint
|
14
|
+
|
15
|
+
class SAFEARRAYBOUND < FFI::Struct
|
16
|
+
layout \
|
17
|
+
:cElements, :ulong,
|
18
|
+
:lLbound, :long
|
19
|
+
end
|
20
|
+
|
21
|
+
class SAFEARRAY < FFI::Struct
|
22
|
+
layout \
|
23
|
+
:cDims, :ushort,
|
24
|
+
:fFeatures, :ushort,
|
25
|
+
:cbElements, :ulong,
|
26
|
+
:cLocks, :ulong,
|
27
|
+
:pvData, :pointer,
|
28
|
+
:rgsabound, [SAFEARRAYBOUND, 1]
|
29
|
+
end
|
30
|
+
|
31
|
+
attach_function :SafeArrayCreateVector, [:ushort, :long, :uint], :pointer
|
32
|
+
attach_function :SafeArrayDestroy, [:pointer], :long
|
33
|
+
attach_function :SafeArrayAccessData, [:pointer, :pointer], :long
|
34
|
+
attach_function :SafeArrayUnaccessData, [:pointer], :long
|
35
|
+
|
36
|
+
OLEIVERB_PRIMARY = 0
|
37
|
+
OLEIVERB_SHOW = -1
|
38
|
+
OLEIVERB_OPEN = -2
|
39
|
+
OLEIVERB_HIDE = -3
|
40
|
+
OLEIVERB_UIACTIVATE = -4
|
41
|
+
OLEIVERB_INPLACEACTIVATE = -5
|
42
|
+
OLEIVERB_DISCARDUNDOSTATE = -6
|
43
|
+
|
44
|
+
IOleWindow = COMInterface[IUnknown,
|
45
|
+
'00000114-0000-0000-C000-000000000046',
|
46
|
+
|
47
|
+
GetWindow: [[:pointer], :long],
|
48
|
+
ContextSensitiveHelp: [[:int], :long]
|
49
|
+
]
|
50
|
+
|
51
|
+
IOleInPlaceObject = COMInterface[IOleWindow,
|
52
|
+
'00000113-0000-0000-C000-000000000046',
|
53
|
+
|
54
|
+
InPlaceDeactivate: [[], :long],
|
55
|
+
UIDeactivate: [[], :long],
|
56
|
+
SetObjectRects: [[:pointer, :pointer], :long],
|
57
|
+
ReactivateAndUndo: [[], :long]
|
58
|
+
]
|
59
|
+
|
60
|
+
IOleInPlaceSite = COMInterface[IOleWindow,
|
61
|
+
'00000119-0000-0000-C000-000000000046',
|
62
|
+
|
63
|
+
CanInPlaceActivate: [[], :long],
|
64
|
+
OnInPlaceActivate: [[], :long],
|
65
|
+
OnUIActivate: [[], :long],
|
66
|
+
GetWindowContext: [[:pointer, :pointer, :pointer, :pointer, :pointer], :long],
|
67
|
+
Scroll: [[:long_long], :long],
|
68
|
+
OnUIDeactivate: [[:int], :long],
|
69
|
+
OnInPlaceDeactivate: [[], :long],
|
70
|
+
DiscardUndoState: [[], :long],
|
71
|
+
DeactivateAndUndo: [[], :long],
|
72
|
+
OnPosRectChange: [[:pointer], :long]
|
73
|
+
]
|
74
|
+
|
75
|
+
IOleClientSite = COMInterface[IUnknown,
|
76
|
+
'00000118-0000-0000-C000-000000000046',
|
77
|
+
|
78
|
+
SaveObject: [[], :long],
|
79
|
+
GetMoniker: [[:ulong, :ulong, :pointer], :long],
|
80
|
+
GetContainer: [[:pointer], :long],
|
81
|
+
ShowObject: [[], :long],
|
82
|
+
OnShowWindow: [[:int], :long],
|
83
|
+
RequestNewObjectLayout: [[], :long]
|
84
|
+
]
|
85
|
+
|
86
|
+
OLEGETMONIKER_ONLYIFTHERE = 1
|
87
|
+
OLEGETMONIKER_FORCEASSIGN = 2
|
88
|
+
OLEGETMONIKER_UNASSIGN = 3
|
89
|
+
OLEGETMONIKER_TEMPFORUSER = 4
|
90
|
+
|
91
|
+
OLEWHICHMK_CONTAINER = 1
|
92
|
+
OLEWHICHMK_OBJREL = 2
|
93
|
+
OLEWHICHMK_OBJFULL = 3
|
94
|
+
|
95
|
+
USERCLASSTYPE_FULL = 1
|
96
|
+
USERCLASSTYPE_SHORT = 2
|
97
|
+
USERCLASSTYPE_APPNAME = 3
|
98
|
+
|
99
|
+
OLEMISC_RECOMPOSEONRESIZE = 0x00000001
|
100
|
+
OLEMISC_ONLYICONIC = 0x00000002
|
101
|
+
OLEMISC_INSERTNOTREPLACE = 0x00000004
|
102
|
+
OLEMISC_STATIC = 0x00000008
|
103
|
+
OLEMISC_CANTLINKINSIDE = 0x00000010
|
104
|
+
OLEMISC_CANLINKBYOLE1 = 0x00000020
|
105
|
+
OLEMISC_ISLINKOBJECT = 0x00000040
|
106
|
+
OLEMISC_INSIDEOUT = 0x00000080
|
107
|
+
OLEMISC_ACTIVATEWHENVISIBLE = 0x00000100
|
108
|
+
OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x00000200
|
109
|
+
OLEMISC_INVISIBLEATRUNTIME = 0x00000400
|
110
|
+
OLEMISC_ALWAYSRUN = 0x00000800
|
111
|
+
OLEMISC_ACTSLIKEBUTTON = 0x00001000
|
112
|
+
OLEMISC_ACTSLIKELABEL = 0x00002000
|
113
|
+
OLEMISC_NOUIACTIVATE = 0x00004000
|
114
|
+
OLEMISC_ALIGNABLE = 0x00008000
|
115
|
+
OLEMISC_SIMPLEFRAME = 0x00010000
|
116
|
+
OLEMISC_SETCLIENTSITEFIRST = 0x00020000
|
117
|
+
OLEMISC_IMEMODE = 0x00040000
|
118
|
+
OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x00080000
|
119
|
+
OLEMISC_WANTSTOMENUMERGE = 0x00100000
|
120
|
+
OLEMISC_SUPPORTSMULTILEVELUNDO = 0x00200000
|
121
|
+
|
122
|
+
OLECLOSE_SAVEIFDIRTY = 0
|
123
|
+
OLECLOSE_NOSAVE = 1
|
124
|
+
OLECLOSE_PROMPTSAVE = 2
|
125
|
+
|
126
|
+
IOleObject = COMInterface[IUnknown,
|
127
|
+
'00000112-0000-0000-C000-000000000046',
|
128
|
+
|
129
|
+
SetClientSite: [[:pointer], :long],
|
130
|
+
GetClientSite: [[:pointer], :long],
|
131
|
+
SetHostNames: [[:pointer, :pointer], :long],
|
132
|
+
Close: [[:ulong], :long],
|
133
|
+
SetMoniker: [[:ulong, :pointer], :long],
|
134
|
+
GetMoniker: [[:ulong, :ulong, :pointer], :long],
|
135
|
+
InitFromData: [[:pointer, :int, :ulong], :long],
|
136
|
+
GetClipboardData: [[:ulong, :pointer], :long],
|
137
|
+
DoVerb: [[:long, :pointer, :pointer, :long, :pointer, :pointer], :long],
|
138
|
+
EnumVerbs: [[:pointer], :long],
|
139
|
+
Update: [[], :long],
|
140
|
+
IsUpToDate: [[], :long],
|
141
|
+
GetUserClassID: [[:pointer], :long],
|
142
|
+
GetUserType: [[:ulong, :pointer], :long],
|
143
|
+
SetExtent: [[:ulong, :pointer], :long],
|
144
|
+
GetExtent: [[:ulong, :pointer], :long],
|
145
|
+
Advise: [[:pointer, :pointer], :long],
|
146
|
+
Unadvise: [[:ulong], :long],
|
147
|
+
EnumAdvise: [[:pointer], :long],
|
148
|
+
GetMiscStatus: [[:ulong, :pointer], :long],
|
149
|
+
SetColorScheme: [[:pointer], :long]
|
150
|
+
]
|
151
|
+
|
152
|
+
class PARAMDATA < FFI::Struct
|
153
|
+
layout \
|
154
|
+
:szName, :pointer,
|
155
|
+
:vt, :ushort
|
156
|
+
end
|
157
|
+
|
158
|
+
CC_FASTCALL = 0
|
159
|
+
CC_CDECL = 1
|
160
|
+
CC_MSCPASCAL = CC_CDECL + 1
|
161
|
+
CC_PASCAL = CC_MSCPASCAL
|
162
|
+
CC_MACPASCAL = CC_PASCAL + 1
|
163
|
+
CC_STDCALL = CC_MACPASCAL + 1
|
164
|
+
CC_FPFASTCALL = CC_STDCALL + 1
|
165
|
+
CC_SYSCALL = CC_FPFASTCALL + 1
|
166
|
+
CC_MPWCDECL = CC_SYSCALL + 1
|
167
|
+
CC_MPWPASCAL = CC_MPWCDECL + 1
|
168
|
+
CC_MAX = CC_MPWPASCAL + 1
|
169
|
+
|
170
|
+
DISPATCH_METHOD = 0x1
|
171
|
+
DISPATCH_PROPERTYGET = 0x2
|
172
|
+
DISPATCH_PROPERTYPUT = 0x4
|
173
|
+
DISPATCH_PROPERTYPUTREF = 0x8
|
174
|
+
|
175
|
+
class METHODDATA < FFI::Struct
|
176
|
+
layout \
|
177
|
+
:szName, :pointer,
|
178
|
+
:ppdata, :pointer,
|
179
|
+
:dispid, :long,
|
180
|
+
:iMeth, :uint,
|
181
|
+
:cc, :uint,
|
182
|
+
:cArgs, :uint,
|
183
|
+
:wFlags, :ushort,
|
184
|
+
:vtReturn, :ushort
|
185
|
+
end
|
186
|
+
|
187
|
+
class INTERFACEDATA < FFI::Struct
|
188
|
+
layout \
|
189
|
+
:pmethdata, :pointer,
|
190
|
+
:cMembers, :uint
|
191
|
+
end
|
192
|
+
|
193
|
+
attach_function :CreateDispTypeInfo, [:pointer, :ulong, :pointer], :long
|
194
|
+
|
195
|
+
class DISPPARAMS < FFI::Struct
|
196
|
+
layout \
|
197
|
+
:rgvarg, :pointer,
|
198
|
+
:rgdispidNamedArgs, :pointer,
|
199
|
+
:cArgs, :uint,
|
200
|
+
:cNamedArgs, :uint
|
201
|
+
end
|
202
|
+
|
203
|
+
attach_function :DispInvoke, [:pointer, :pointer, :long, :ushort, :pointer, :pointer, :pointer, :pointer], :long
|
204
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: windows_com
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Radoslav Peev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
description: Ruby FFI (x86) bindings to essential COM related Windows APIs
|
28
|
+
email:
|
29
|
+
- rpeev@ymail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- RELNOTES.md
|
37
|
+
- examples/DesktopGadget.rbw
|
38
|
+
- lib/windows_com.rb
|
39
|
+
- lib/windows_com/common.rb
|
40
|
+
- lib/windows_com/cruft.rb
|
41
|
+
- lib/windows_com/libc.rb
|
42
|
+
- lib/windows_com/ole.rb
|
43
|
+
- lib/windows_com/oleaut.rb
|
44
|
+
homepage: https://github.com/rpeev/windows_com
|
45
|
+
licenses:
|
46
|
+
- MIT
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.5.2
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Ruby FFI (x86) bindings to essential COM related Windows APIs
|
68
|
+
test_files: []
|