windows-api 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +5 -0
- data/MANIFEST +2 -1
- data/README +5 -1
- data/Rakefile +16 -19
- data/lib/windows/api.rb +483 -483
- data/test/test_wide_string.rb +16 -15
- data/test/test_windows_api.rb +10 -10
- data/windows-api.gemspec +19 -20
- metadata +28 -12
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
== 0.4.1 - 27-Jan-2012
|
2
|
+
* Switched Config to RbConfig to silence 1.9 warnings. Thanks go to
|
3
|
+
Cameron Cox for the patch.
|
4
|
+
* Some updates to the README, Rakefile, gemspec and test files.
|
5
|
+
|
1
6
|
== 0.4.0 - 18-Oct-2009
|
2
7
|
* Methods that begin with an underscore, such as _umask(), are now preserved.
|
3
8
|
A method alias is also created without an underscore, e.g. umask().
|
data/MANIFEST
CHANGED
data/README
CHANGED
@@ -73,12 +73,16 @@
|
|
73
73
|
See the RDoc documentation, which should have been automatically generated
|
74
74
|
if you installed this as a gem.
|
75
75
|
|
76
|
+
== Future Plans
|
77
|
+
Add an auto_private method that is true by default.
|
78
|
+
Replace or drop this library in favor of FFI.
|
79
|
+
|
76
80
|
== Bugs
|
77
81
|
None that I'm aware of. Please submit any bugs to the project page at
|
78
82
|
http://www.rubyforge.org/projects/win32utils.
|
79
83
|
|
80
84
|
== Copyright
|
81
|
-
(C) 2007-
|
85
|
+
(C) 2007-2012, Daniel J. Berger
|
82
86
|
|
83
87
|
== License
|
84
88
|
Artistic 2.0
|
data/Rakefile
CHANGED
@@ -1,29 +1,26 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/clean'
|
3
3
|
require 'rake/testtask'
|
4
|
-
require 'rbconfig'
|
5
|
-
include Config
|
6
4
|
|
7
|
-
|
8
|
-
task :install do
|
9
|
-
sitelibdir = CONFIG["sitelibdir"]
|
10
|
-
installdir = File.join(sitelibdir, 'windows')
|
11
|
-
Dir.mkdir(installdir) unless File.exists?(installdir)
|
12
|
-
file = "lib/windows/api.rb"
|
13
|
-
FileUtils.cp(file, installdir, :verbose => true)
|
14
|
-
end
|
5
|
+
CLEAN.include("**/*.gem", "**/*.rbc")
|
15
6
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
namespace :gem do
|
8
|
+
desc 'Create the windows-api gem'
|
9
|
+
task :create => [:clean] do
|
10
|
+
spec = eval(IO.read('windows-api.gemspec'))
|
11
|
+
Gem::Builder.new(spec).build
|
12
|
+
end
|
20
13
|
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
desc 'Install the windows-api gem'
|
15
|
+
task :install => [:create] do
|
16
|
+
file = Dir["*.gem"].first
|
17
|
+
sh "gem install #{file}"
|
18
|
+
end
|
24
19
|
end
|
25
20
|
|
26
21
|
Rake::TestTask.new do |test|
|
27
|
-
|
28
|
-
|
22
|
+
test.warning = true
|
23
|
+
test.verbose = true
|
29
24
|
end
|
25
|
+
|
26
|
+
task :default => :test
|
data/lib/windows/api.rb
CHANGED
@@ -1,506 +1,506 @@
|
|
1
1
|
require 'win32/api'
|
2
2
|
require 'rbconfig'
|
3
3
|
require 'forwardable'
|
4
|
-
include
|
4
|
+
include RbConfig
|
5
5
|
|
6
6
|
# The Windows module serves as a namespace only
|
7
7
|
module Windows
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
MSVCRT_DLL = 'msvcrt'
|
18
|
-
end
|
19
|
-
else
|
9
|
+
# With Microsoft Visual C++ 8 and later users should use the associated
|
10
|
+
# DLL instead of msvcrt directly, if possible.
|
11
|
+
if CONFIG['host_os'].split('_')[1]
|
12
|
+
if CONFIG['host_os'].split('_')[1].to_i >= 80 &&
|
13
|
+
File.exists?(File.join(CONFIG['bindir'], 'ruby.exe.manifest'))
|
14
|
+
then
|
15
|
+
MSVCRT_DLL = 'msvcr' + CONFIG['host_os'].split('_')[1]
|
16
|
+
else
|
20
17
|
MSVCRT_DLL = 'msvcrt'
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
extend Forwardable
|
26
|
-
|
27
|
-
# The version of the windows-api library
|
28
|
-
VERSION = '0.4.0'
|
29
|
-
|
30
|
-
# The methods from Win32::API are delegated to the appropriate object
|
31
|
-
def_delegators(:@api, :function_name, :dll_name, :prototype)
|
32
|
-
def_delegators(:@api, :return_type, :effective_function_name)
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
# Verbose data types that can be used instead of single letters
|
37
|
-
DATA_TYPES = {
|
38
|
-
'ATOM' => 'I',
|
39
|
-
'BOOL' => 'B',
|
40
|
-
'BOOLEAN' => 'B',
|
41
|
-
'BYTE' => 'I',
|
42
|
-
'CALLBACK' => 'K',
|
43
|
-
'CHAR' => 'I',
|
44
|
-
'COLORREF' => 'L',
|
45
|
-
'DWORD' => 'L',
|
46
|
-
'DWORDLONG' => 'L',
|
47
|
-
'DWORD_PTR' => 'P',
|
48
|
-
'DWORD32' => 'I',
|
49
|
-
'DWORD64' => 'L',
|
50
|
-
'HACCEL' => 'L',
|
51
|
-
'HANDLE' => 'L',
|
52
|
-
'HBITMAP' => 'L',
|
53
|
-
'HBRUSH' => 'L',
|
54
|
-
'HCOLORSPACE' => 'L',
|
55
|
-
'HCONV' => 'L',
|
56
|
-
'HDC' => 'L',
|
57
|
-
'HFILE' => 'I',
|
58
|
-
'HKEY' => 'L',
|
59
|
-
'HFONT' => 'L',
|
60
|
-
'HINSTANCE' => 'L',
|
61
|
-
'HKEY' => 'L',
|
62
|
-
'HLOCAL' => 'L',
|
63
|
-
'HMENU' => 'L',
|
64
|
-
'HMODULE' => 'L',
|
65
|
-
'HRESULT' => 'L',
|
66
|
-
'HWND' => 'L',
|
67
|
-
'INT' => 'I',
|
68
|
-
'INT_PTR' => 'P',
|
69
|
-
'INT32' => 'I',
|
70
|
-
'INT64' => 'L',
|
71
|
-
'LANGID' => 'I',
|
72
|
-
'LCID' => 'L',
|
73
|
-
'LCTYPE' => 'L',
|
74
|
-
'LONG' => 'L',
|
75
|
-
'LONGLONG' => 'L',
|
76
|
-
'LONG_PTR' => 'P',
|
77
|
-
'LONG32' => 'L',
|
78
|
-
'LONG64' => 'L',
|
79
|
-
'LPARAM' => 'P',
|
80
|
-
'LPBOOL' => 'P',
|
81
|
-
'LPBYTE' => 'P',
|
82
|
-
'LPCOLORREF' => 'P',
|
83
|
-
'LPCSTR' => 'P',
|
84
|
-
'LPCTSTR' => 'P',
|
85
|
-
'LPCVOID' => 'L',
|
86
|
-
'LPCWSTR' => 'P',
|
87
|
-
'LPDWORD' => 'P',
|
88
|
-
'LPHANDLE' => 'P',
|
89
|
-
'LPINT' => 'P',
|
90
|
-
'LPLONG' => 'P',
|
91
|
-
'LPSTR' => 'P',
|
92
|
-
'LPTSTR' => 'P',
|
93
|
-
'LPVOID' => 'L',
|
94
|
-
'LPWORD' => 'P',
|
95
|
-
'LPWSTR' => 'P',
|
96
|
-
'LRESULT' => 'P',
|
97
|
-
'PBOOL' => 'P',
|
98
|
-
'PBOOLEAN' => 'P',
|
99
|
-
'PBYTE' => 'P',
|
100
|
-
'PHKEY' => 'P',
|
101
|
-
'SC_HANDLE' => 'L',
|
102
|
-
'SC_LOCK' => 'L',
|
103
|
-
'SERVICE_STATUS_HANDLE' => 'L',
|
104
|
-
'SHORT' => 'I',
|
105
|
-
'SIZE_T' => 'P',
|
106
|
-
'TCHAR' => 'L',
|
107
|
-
'UINT' => 'I',
|
108
|
-
'UINT_PTR' => 'P',
|
109
|
-
'UINT32' => 'I',
|
110
|
-
'UINT64' => 'L',
|
111
|
-
'ULONG' => 'L',
|
112
|
-
'ULONGLONG' => 'L',
|
113
|
-
'ULONG_PTR' => 'P',
|
114
|
-
'ULONG32' => 'L',
|
115
|
-
'ULONG64' => 'L',
|
116
|
-
'USHORT' => 'I',
|
117
|
-
'USN' => 'L',
|
118
|
-
'WINAPI' => 'L',
|
119
|
-
'WORD' => 'I'
|
120
|
-
}
|
121
|
-
|
122
|
-
public
|
123
|
-
|
124
|
-
@auto_constant = false
|
125
|
-
@auto_method = false
|
126
|
-
@auto_unicode = false
|
127
|
-
@auto_namespace = nil
|
128
|
-
|
129
|
-
# Returns the value of the @auto_constant class instance variable. The
|
130
|
-
# default is nil, i.e. none. See the Windows::API.auto_constant=
|
131
|
-
# documentation for more information.
|
132
|
-
#
|
133
|
-
def self.auto_constant
|
134
|
-
@auto_constant
|
135
|
-
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
MSVCRT_DLL = 'msvcrt'
|
21
|
+
end
|
136
22
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
23
|
+
# Wrapper around the Win32::API class
|
24
|
+
class API
|
25
|
+
extend Forwardable
|
26
|
+
|
27
|
+
# The version of the windows-api library
|
28
|
+
VERSION = '0.4.1'
|
29
|
+
|
30
|
+
# The methods from Win32::API are delegated to the appropriate object
|
31
|
+
def_delegators(:@api, :function_name, :dll_name, :prototype)
|
32
|
+
def_delegators(:@api, :return_type, :effective_function_name)
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Verbose data types that can be used instead of single letters
|
37
|
+
DATA_TYPES = {
|
38
|
+
'ATOM' => 'I',
|
39
|
+
'BOOL' => 'B',
|
40
|
+
'BOOLEAN' => 'B',
|
41
|
+
'BYTE' => 'I',
|
42
|
+
'CALLBACK' => 'K',
|
43
|
+
'CHAR' => 'I',
|
44
|
+
'COLORREF' => 'L',
|
45
|
+
'DWORD' => 'L',
|
46
|
+
'DWORDLONG' => 'L',
|
47
|
+
'DWORD_PTR' => 'P',
|
48
|
+
'DWORD32' => 'I',
|
49
|
+
'DWORD64' => 'L',
|
50
|
+
'HACCEL' => 'L',
|
51
|
+
'HANDLE' => 'L',
|
52
|
+
'HBITMAP' => 'L',
|
53
|
+
'HBRUSH' => 'L',
|
54
|
+
'HCOLORSPACE' => 'L',
|
55
|
+
'HCONV' => 'L',
|
56
|
+
'HDC' => 'L',
|
57
|
+
'HFILE' => 'I',
|
58
|
+
'HKEY' => 'L',
|
59
|
+
'HFONT' => 'L',
|
60
|
+
'HINSTANCE' => 'L',
|
61
|
+
'HKEY' => 'L',
|
62
|
+
'HLOCAL' => 'L',
|
63
|
+
'HMENU' => 'L',
|
64
|
+
'HMODULE' => 'L',
|
65
|
+
'HRESULT' => 'L',
|
66
|
+
'HWND' => 'L',
|
67
|
+
'INT' => 'I',
|
68
|
+
'INT_PTR' => 'P',
|
69
|
+
'INT32' => 'I',
|
70
|
+
'INT64' => 'L',
|
71
|
+
'LANGID' => 'I',
|
72
|
+
'LCID' => 'L',
|
73
|
+
'LCTYPE' => 'L',
|
74
|
+
'LONG' => 'L',
|
75
|
+
'LONGLONG' => 'L',
|
76
|
+
'LONG_PTR' => 'P',
|
77
|
+
'LONG32' => 'L',
|
78
|
+
'LONG64' => 'L',
|
79
|
+
'LPARAM' => 'P',
|
80
|
+
'LPBOOL' => 'P',
|
81
|
+
'LPBYTE' => 'P',
|
82
|
+
'LPCOLORREF' => 'P',
|
83
|
+
'LPCSTR' => 'P',
|
84
|
+
'LPCTSTR' => 'P',
|
85
|
+
'LPCVOID' => 'L',
|
86
|
+
'LPCWSTR' => 'P',
|
87
|
+
'LPDWORD' => 'P',
|
88
|
+
'LPHANDLE' => 'P',
|
89
|
+
'LPINT' => 'P',
|
90
|
+
'LPLONG' => 'P',
|
91
|
+
'LPSTR' => 'P',
|
92
|
+
'LPTSTR' => 'P',
|
93
|
+
'LPVOID' => 'L',
|
94
|
+
'LPWORD' => 'P',
|
95
|
+
'LPWSTR' => 'P',
|
96
|
+
'LRESULT' => 'P',
|
97
|
+
'PBOOL' => 'P',
|
98
|
+
'PBOOLEAN' => 'P',
|
99
|
+
'PBYTE' => 'P',
|
100
|
+
'PHKEY' => 'P',
|
101
|
+
'SC_HANDLE' => 'L',
|
102
|
+
'SC_LOCK' => 'L',
|
103
|
+
'SERVICE_STATUS_HANDLE' => 'L',
|
104
|
+
'SHORT' => 'I',
|
105
|
+
'SIZE_T' => 'P',
|
106
|
+
'TCHAR' => 'L',
|
107
|
+
'UINT' => 'I',
|
108
|
+
'UINT_PTR' => 'P',
|
109
|
+
'UINT32' => 'I',
|
110
|
+
'UINT64' => 'L',
|
111
|
+
'ULONG' => 'L',
|
112
|
+
'ULONGLONG' => 'L',
|
113
|
+
'ULONG_PTR' => 'P',
|
114
|
+
'ULONG32' => 'L',
|
115
|
+
'ULONG64' => 'L',
|
116
|
+
'USHORT' => 'I',
|
117
|
+
'USN' => 'L',
|
118
|
+
'WINAPI' => 'L',
|
119
|
+
'WORD' => 'I'
|
120
|
+
}
|
121
|
+
|
122
|
+
public
|
123
|
+
|
124
|
+
@auto_constant = false
|
125
|
+
@auto_method = false
|
126
|
+
@auto_unicode = false
|
127
|
+
@auto_namespace = nil
|
128
|
+
|
129
|
+
# Returns the value of the @auto_constant class instance variable. The
|
130
|
+
# default is nil, i.e. none. See the Windows::API.auto_constant=
|
131
|
+
# documentation for more information.
|
132
|
+
#
|
133
|
+
def self.auto_constant
|
134
|
+
@auto_constant
|
135
|
+
end
|
136
|
+
|
137
|
+
# Automatically sets a constant to match the function name.
|
138
|
+
#
|
139
|
+
# The standard practice for defining Windows::API objects is to use
|
140
|
+
# a constant that matches the function name. For example, this is a
|
141
|
+
# typical idiom:
|
142
|
+
#
|
143
|
+
# module Windows
|
144
|
+
# module File
|
145
|
+
# GetFileAttributes = API.new('GetFileAttributes', 'P','L')
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# With the API.auto_constant value set to true you can avoid the
|
150
|
+
# assignment step and the matching constant name will be automatically
|
151
|
+
# set for you in the namespace defined in API.auto_namespace. In other
|
152
|
+
# words, this example is identical to the one above:
|
153
|
+
#
|
154
|
+
# module Windows
|
155
|
+
# module File
|
156
|
+
# API.auto_constant = true
|
157
|
+
# API.auto_namespace = 'Windows::File'
|
158
|
+
# API.new('GetFileAttributes', 'P', 'L')
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# If the auto_constant class variable is set to true, but no
|
163
|
+
# auto_namespace is set, an error will be raised. Note that the
|
164
|
+
# namespace must refer to an existing module (not a class).
|
165
|
+
#--
|
166
|
+
# TODO: If there's a way to automatically grab the namespace internally,
|
167
|
+
# nesting and all, I'd love to know the solution.
|
168
|
+
#
|
169
|
+
def self.auto_constant=(bool)
|
170
|
+
@auto_constant = bool
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns the value of the auto_namespace class instance variable. Used
|
174
|
+
# in conjunction with API.auto_constant and/or API.auto_method.
|
175
|
+
#
|
176
|
+
def self.auto_namespace
|
177
|
+
@auto_namespace
|
178
|
+
end
|
179
|
+
|
180
|
+
# Sets the value of the auto_namespace class nstance variable. The
|
181
|
+
# default is nil, i.e. none. Use in conjunction with the auto_constant
|
182
|
+
# and/or auto_method class variables, this method will automatically set
|
183
|
+
# a constant and/or method in +namespace+ equal to the function name set
|
184
|
+
# in the constructor.
|
185
|
+
#
|
186
|
+
# The +namespace+ must refer to an existing module, not a class.
|
187
|
+
#
|
188
|
+
def self.auto_namespace=(namespace)
|
189
|
+
@auto_namespace = namespace
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns the value of the auto_method class instance variable. Used in
|
193
|
+
# conjunction with auto_unicode. See API.auto_method= for more
|
194
|
+
# information.
|
195
|
+
#
|
196
|
+
def self.auto_method
|
197
|
+
@auto_method
|
198
|
+
end
|
199
|
+
|
200
|
+
# If this option is set to true then a corresponding method is
|
201
|
+
# automatically generated when you create a new Windows::API object.
|
202
|
+
#
|
203
|
+
# For example, instead of doing this:
|
204
|
+
#
|
205
|
+
# module Windows
|
206
|
+
# module File
|
207
|
+
# GetFileAttributes = API.new('GetFileAttributes', 'P', 'L')
|
208
|
+
#
|
209
|
+
# def GetFileAttributes(x)
|
210
|
+
# GetFileAttributes.call(x)
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
# end
|
214
|
+
#
|
215
|
+
# You can do this, and have the method autogenerated for you.
|
216
|
+
#
|
217
|
+
# module Windows
|
218
|
+
# module File
|
219
|
+
# API.auto_namespace = 'Windows::File'
|
220
|
+
# API.auto_constant = true
|
221
|
+
# API.auto_method = true
|
222
|
+
# API.new('GetFileAttributes', 'P', 'L')
|
223
|
+
# end
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# include Windows::File
|
227
|
+
# GetFileAttributes('C:/test.txt') # vs. GetFileAttributes.call
|
228
|
+
#
|
229
|
+
# If the Windows::API object is declared to be a boolean in the
|
230
|
+
# constructor, then the method definition automatically includes a
|
231
|
+
# '!= 0' clause at the end of the call. That way, you can do
|
232
|
+
# 'if SomeMethod(x)' instead of having to do 'if SomeMethod(x) != 0',
|
233
|
+
# and it will do the right thing.
|
234
|
+
#
|
235
|
+
# If the API.auto_unicode option is also set to true, then you will
|
236
|
+
# get three method definitions. The standard function name, the explicit
|
237
|
+
# ANSI ('A') version and the explicit Unicode/wide version ('W'). The
|
238
|
+
# exception to this rule is that the explicit ANSI and Unicode methods
|
239
|
+
# will NOT be generated if the function passed to the constructor
|
240
|
+
# already ends with 'A' or 'W'.
|
241
|
+
#
|
242
|
+
def self.auto_method=(bool)
|
243
|
+
@auto_method = bool
|
244
|
+
end
|
245
|
+
|
246
|
+
# Returns the value of the auto_unicode class instance variable. This
|
247
|
+
# is used in conjunction with the auto_method and/or auto_constant class
|
248
|
+
# variables. Not significant if neither of those variables are set.
|
249
|
+
#
|
250
|
+
def self.auto_unicode
|
251
|
+
@auto_unicode
|
252
|
+
end
|
253
|
+
|
254
|
+
# If set to true, and the auto_constant variable is set, then the
|
255
|
+
# automatic constant generation will generate the explicit ANSI ('A')
|
256
|
+
# and Unicode/wide ('W') versions of the function passed to the
|
257
|
+
# constructor, if such versions exist. Likewise, if the the
|
258
|
+
# auto_method variable is set, then explicit ANSI and Unicode methods
|
259
|
+
# are generated.
|
260
|
+
#
|
261
|
+
# Here's a typical idiom:
|
262
|
+
#
|
263
|
+
# module Windows
|
264
|
+
# module Path
|
265
|
+
# API.auto_namespace = Windows::Path
|
266
|
+
# API.auto_constant = true
|
267
|
+
# API.new('shlwapi', 'PathAddBackslash', 'P', 'P')
|
268
|
+
# API.new('shlwapi', 'PathAddBackslashA', 'P', 'P')
|
269
|
+
# API.new('shlwapi', 'PathAddBackslashW', 'P', 'P')
|
270
|
+
# end
|
271
|
+
# end
|
272
|
+
#
|
273
|
+
# That can be reduced to this:
|
274
|
+
#
|
275
|
+
# module Windows
|
276
|
+
# module Path
|
277
|
+
# API.auto_namespace = Windows::Path
|
278
|
+
# API.auto_constant = true
|
279
|
+
# API.auto_unicode = true
|
280
|
+
# API.new('shlwapi', 'PathAddBackslash', 'P', 'P')
|
281
|
+
# end
|
282
|
+
# end
|
283
|
+
#
|
284
|
+
# This value is ignored if the function passed to the constructor
|
285
|
+
# already ends with an 'A' or 'W'.
|
286
|
+
#
|
287
|
+
def self.auto_unicode=(bool)
|
288
|
+
@auto_unicode = bool
|
289
|
+
end
|
290
|
+
|
291
|
+
# call-seq:
|
292
|
+
# API.new(func, proto='V', rtype='L', dll='kernel32')
|
293
|
+
#
|
294
|
+
# Creates and returns a new Windows::API object. The +func+ is the
|
295
|
+
# name of the Windows function.
|
296
|
+
#
|
297
|
+
# The +proto+ is the function prototype for +func+. This can be a
|
298
|
+
# string or an array of characters. The possible valid characters
|
299
|
+
# are 'I' (integer), 'B' (BOOL), 'L' (long), 'V' (void), or 'P' (pointer).
|
300
|
+
# The default is void ('V').
|
301
|
+
#
|
302
|
+
# The +rtype+ argument is the return type for the function. The valid
|
303
|
+
# characters are the same as for the +proto+. The default is long ('L').
|
304
|
+
#
|
305
|
+
# The 'B' (BOOL) return type is the same as 'I' (Integer). This is
|
306
|
+
# significant only if the API.auto_method option is set to true, in which
|
307
|
+
# case it alters the generated method definition slightly. See the
|
308
|
+
# API.auto_method= class method for more information.
|
309
|
+
#
|
310
|
+
# The +dll+ is the name of the DLL file that the function is exported
|
311
|
+
# from. The default is 'kernel32'.
|
312
|
+
#
|
313
|
+
# If the function cannot be found then an API::Error is raised (a subclass
|
314
|
+
# of RuntimeError).
|
315
|
+
#
|
316
|
+
def initialize(func, proto='V', rtype='L', dll='kernel32')
|
317
|
+
# Convert literal data types to values that win32-api understands
|
318
|
+
if proto.is_a?(Array)
|
319
|
+
proto.each_with_index{ |pt, index|
|
320
|
+
if pt.length > 1
|
321
|
+
proto[index].replace(DATA_TYPES[pt])
|
322
|
+
end
|
323
|
+
}
|
190
324
|
end
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
# information.
|
195
|
-
#
|
196
|
-
def self.auto_method
|
197
|
-
@auto_method
|
325
|
+
|
326
|
+
if rtype.length > 1
|
327
|
+
rtype.replace(DATA_TYPES[rtype])
|
198
328
|
end
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
215
|
-
# You can do this, and have the method autogenerated for you.
|
216
|
-
#
|
217
|
-
# module Windows
|
218
|
-
# module File
|
219
|
-
# API.auto_namespace = 'Windows::File'
|
220
|
-
# API.auto_constant = true
|
221
|
-
# API.auto_method = true
|
222
|
-
# API.new('GetFileAttributes', 'P', 'L')
|
223
|
-
# end
|
224
|
-
# end
|
329
|
+
|
330
|
+
@function_name = func
|
331
|
+
@prototype = proto
|
332
|
+
@return_type = rtype == 'B' ? 'I' : rtype
|
333
|
+
@dll_name = dll
|
334
|
+
@boolean = rtype == 'B' ? true : false
|
335
|
+
|
336
|
+
@api = Win32::API.new(func, proto, rtype, dll)
|
337
|
+
|
338
|
+
api_a = nil
|
339
|
+
api_w = nil
|
340
|
+
|
341
|
+
# If the auto_unicode option is set, and the func is not already
|
342
|
+
# an explicit ANSI or Wide function name, generate Win32::API
|
343
|
+
# objects for those functions as well. Ignore errors because not
|
344
|
+
# all functions have explicit ANSI or Wide character implementations.
|
225
345
|
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
#
|
229
|
-
# If the Windows::API object is declared to be a boolean in the
|
230
|
-
# constructor, then the method definition automatically includes a
|
231
|
-
# '!= 0' clause at the end of the call. That way, you can do
|
232
|
-
# 'if SomeMethod(x)' instead of having to do 'if SomeMethod(x) != 0',
|
233
|
-
# and it will do the right thing.
|
234
|
-
#
|
235
|
-
# If the API.auto_unicode option is also set to true, then you will
|
236
|
-
# get three method definitions. The standard function name, the explicit
|
237
|
-
# ANSI ('A') version and the explicit Unicode/wide version ('W'). The
|
238
|
-
# exception to this rule is that the explicit ANSI and Unicode methods
|
239
|
-
# will NOT be generated if the function passed to the constructor
|
240
|
-
# already ends with 'A' or 'W'.
|
346
|
+
# This entire bit of logic is skipped if the DLL is msvcrt, since
|
347
|
+
# msvcrt functions never have explicit ANSI or Wide character
|
348
|
+
# versions.
|
241
349
|
#
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
350
|
+
if Windows::API.auto_unicode && dll !~ /msvcr/i
|
351
|
+
begin
|
352
|
+
unless ['A', 'W'].include?(func[-1].chr)
|
353
|
+
api_a = Win32::API.new("#{func}A", proto, rtype, dll)
|
354
|
+
end
|
355
|
+
rescue RuntimeError
|
356
|
+
end
|
357
|
+
|
358
|
+
begin
|
359
|
+
unless ['W', 'A'].include?(func[-1].chr)
|
360
|
+
api_w = Win32::API.new("#{func}W", proto, rtype, dll)
|
361
|
+
end
|
362
|
+
rescue RuntimeError
|
363
|
+
end
|
252
364
|
end
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
#
|
257
|
-
#
|
258
|
-
#
|
259
|
-
# are generated.
|
260
|
-
#
|
261
|
-
# Here's a typical idiom:
|
262
|
-
#
|
263
|
-
# module Windows
|
264
|
-
# module Path
|
265
|
-
# API.auto_namespace = Windows::Path
|
266
|
-
# API.auto_constant = true
|
267
|
-
# API.new('shlwapi', 'PathAddBackslash', 'P', 'P')
|
268
|
-
# API.new('shlwapi', 'PathAddBackslashA', 'P', 'P')
|
269
|
-
# API.new('shlwapi', 'PathAddBackslashW', 'P', 'P')
|
270
|
-
# end
|
271
|
-
# end
|
365
|
+
|
366
|
+
func_upper = nil
|
367
|
+
|
368
|
+
# Automatically define a constant matching the function name if the
|
369
|
+
# auto_constant option is set. Lower case method names will have a
|
370
|
+
# capitalized equivalent created, e.g. Memcpy for memcpy, etc.
|
272
371
|
#
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
372
|
+
if Windows::API.auto_constant && Windows::API.auto_namespace
|
373
|
+
if Windows::API.auto_namespace != 'Windows'
|
374
|
+
namespace = class_for(Windows::API.auto_namespace)
|
375
|
+
else
|
376
|
+
namespace = Windows::API.auto_namespace
|
377
|
+
end
|
378
|
+
|
379
|
+
# Convert e.g. 'strstr' to 'Strstr' as an equivalent constant
|
380
|
+
if ('A'..'Z').include?(func[0].chr)
|
381
|
+
namespace.const_set(func, @api)
|
382
|
+
else
|
383
|
+
func_upper = func.dup
|
384
|
+
if func_upper[0].chr == '_'
|
385
|
+
func_upper = func_upper[1, func_upper.length]
|
386
|
+
end
|
387
|
+
func_upper[0, 1] = func_upper[0].chr.capitalize
|
388
|
+
namespace.const_set(func_upper, @api)
|
389
|
+
end
|
390
|
+
|
391
|
+
# Automatically define the explicit ANSI and Unicode functions
|
392
|
+
# as constants as well, if appropriate.
|
393
|
+
#
|
394
|
+
if Windows::API.auto_unicode
|
395
|
+
namespace.const_set("#{func}A", api_a) if api_a
|
396
|
+
namespace.const_set("#{func}W", api_w) if api_w
|
397
|
+
end
|
289
398
|
end
|
290
399
|
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
# Creates and returns a new Windows::API object. The +func+ is the
|
295
|
-
# name of the Windows function.
|
296
|
-
#
|
297
|
-
# The +proto+ is the function prototype for +func+. This can be a
|
298
|
-
# string or an array of characters. The possible valid characters
|
299
|
-
# are 'I' (integer), 'B' (BOOL), 'L' (long), 'V' (void), or 'P' (pointer).
|
300
|
-
# The default is void ('V').
|
301
|
-
#
|
302
|
-
# The +rtype+ argument is the return type for the function. The valid
|
303
|
-
# characters are the same as for the +proto+. The default is long ('L').
|
400
|
+
# Automatically define a method in the auto_namespace if the
|
401
|
+
# auto_method option is set. The explicit ANSI and Unicode methods
|
402
|
+
# are added as well if the auto_unicode option is set to true.
|
304
403
|
#
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
404
|
+
if Windows::API.auto_method && Windows::API.auto_namespace
|
405
|
+
if proto == 'V'
|
406
|
+
proto = ''
|
407
|
+
else
|
408
|
+
n = 0
|
409
|
+
if proto.is_a?(String)
|
410
|
+
proto = proto.split('').map{ |e|
|
411
|
+
n += 1
|
412
|
+
e.downcase + n.to_s
|
413
|
+
}.join(', ')
|
414
|
+
else
|
415
|
+
proto = proto.map{ |e|
|
416
|
+
n += 1
|
417
|
+
e.downcase + n.to_s
|
418
|
+
}.join(', ')
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# Use the upper case function equivalent if defined
|
423
|
+
call_func = func_upper || func
|
424
|
+
|
425
|
+
if @boolean
|
426
|
+
string = <<-EOC
|
427
|
+
module #{Windows::API.auto_namespace}
|
428
|
+
def #{func}(#{proto})
|
429
|
+
#{call_func}.call(#{proto}) != 0
|
430
|
+
end
|
431
|
+
EOC
|
432
|
+
|
433
|
+
if api_a
|
434
|
+
string << %Q{
|
435
|
+
def #{func}A(#{proto})
|
436
|
+
#{call_func}A.call(#{proto}) != 0
|
437
|
+
end
|
323
438
|
}
|
324
|
-
|
325
|
-
|
326
|
-
if rtype.length > 1
|
327
|
-
rtype.replace(DATA_TYPES[rtype])
|
328
|
-
end
|
329
|
-
|
330
|
-
@function_name = func
|
331
|
-
@prototype = proto
|
332
|
-
@return_type = rtype == 'B' ? 'I' : rtype
|
333
|
-
@dll_name = dll
|
334
|
-
@boolean = rtype == 'B' ? true : false
|
335
|
-
|
336
|
-
@api = Win32::API.new(func, proto, rtype, dll)
|
337
|
-
|
338
|
-
api_a = nil
|
339
|
-
api_w = nil
|
340
|
-
|
341
|
-
# If the auto_unicode option is set, and the func is not already
|
342
|
-
# an explicit ANSI or Wide function name, generate Win32::API
|
343
|
-
# objects for those functions as well. Ignore errors because not
|
344
|
-
# all functions have explicit ANSI or Wide character implementations.
|
345
|
-
#
|
346
|
-
# This entire bit of logic is skipped if the DLL is msvcrt, since
|
347
|
-
# msvcrt functions never have explicit ANSI or Wide character
|
348
|
-
# versions.
|
349
|
-
#
|
350
|
-
if Windows::API.auto_unicode && dll !~ /msvcr/i
|
351
|
-
begin
|
352
|
-
unless ['A', 'W'].include?(func[-1].chr)
|
353
|
-
api_a = Win32::API.new("#{func}A", proto, rtype, dll)
|
354
|
-
end
|
355
|
-
rescue RuntimeError
|
356
|
-
end
|
357
|
-
|
358
|
-
begin
|
359
|
-
unless ['W', 'A'].include?(func[-1].chr)
|
360
|
-
api_w = Win32::API.new("#{func}W", proto, rtype, dll)
|
361
|
-
end
|
362
|
-
rescue RuntimeError
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
func_upper = nil
|
367
|
-
|
368
|
-
# Automatically define a constant matching the function name if the
|
369
|
-
# auto_constant option is set. Lower case method names will have a
|
370
|
-
# capitalized equivalent created, e.g. Memcpy for memcpy, etc.
|
371
|
-
#
|
372
|
-
if Windows::API.auto_constant && Windows::API.auto_namespace
|
373
|
-
if Windows::API.auto_namespace != 'Windows'
|
374
|
-
namespace = class_for(Windows::API.auto_namespace)
|
375
|
-
else
|
376
|
-
namespace = Windows::API.auto_namespace
|
377
|
-
end
|
378
|
-
|
379
|
-
# Convert e.g. 'strstr' to 'Strstr' as an equivalent constant
|
380
|
-
if ('A'..'Z').include?(func[0].chr)
|
381
|
-
namespace.const_set(func, @api)
|
382
|
-
else
|
383
|
-
func_upper = func.dup
|
384
|
-
if func_upper[0].chr == '_'
|
385
|
-
func_upper = func_upper[1, func_upper.length]
|
386
|
-
end
|
387
|
-
func_upper[0, 1] = func_upper[0].chr.capitalize
|
388
|
-
namespace.const_set(func_upper, @api)
|
389
|
-
end
|
390
|
-
|
391
|
-
# Automatically define the explicit ANSI and Unicode functions
|
392
|
-
# as constants as well, if appropriate.
|
393
|
-
#
|
394
|
-
if Windows::API.auto_unicode
|
395
|
-
namespace.const_set("#{func}A", api_a) if api_a
|
396
|
-
namespace.const_set("#{func}W", api_w) if api_w
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
# Automatically define a method in the auto_namespace if the
|
401
|
-
# auto_method option is set. The explicit ANSI and Unicode methods
|
402
|
-
# are added as well if the auto_unicode option is set to true.
|
403
|
-
#
|
404
|
-
if Windows::API.auto_method && Windows::API.auto_namespace
|
405
|
-
if proto == 'V'
|
406
|
-
proto = ''
|
407
|
-
else
|
408
|
-
n = 0
|
409
|
-
if proto.is_a?(String)
|
410
|
-
proto = proto.split('').map{ |e|
|
411
|
-
n += 1
|
412
|
-
e.downcase + n.to_s
|
413
|
-
}.join(', ')
|
414
|
-
else
|
415
|
-
proto = proto.map{ |e|
|
416
|
-
n += 1
|
417
|
-
e.downcase + n.to_s
|
418
|
-
}.join(', ')
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
# Use the upper case function equivalent if defined
|
423
|
-
call_func = func_upper || func
|
424
|
-
|
425
|
-
if @boolean
|
426
|
-
string = <<-EOC
|
427
|
-
module #{Windows::API.auto_namespace}
|
428
|
-
def #{func}(#{proto})
|
429
|
-
#{call_func}.call(#{proto}) != 0
|
430
|
-
end
|
431
|
-
EOC
|
432
|
-
|
433
|
-
if api_a
|
434
|
-
string << %Q{
|
435
|
-
def #{func}A(#{proto})
|
436
|
-
#{call_func}A.call(#{proto}) != 0
|
437
|
-
end
|
438
|
-
}
|
439
|
-
end
|
440
|
-
|
441
|
-
if api_w
|
442
|
-
string << %Q{
|
443
|
-
def #{func}W(#{proto})
|
444
|
-
#{call_func}W.call(#{proto}) != 0
|
445
|
-
end
|
446
|
-
}
|
447
|
-
end
|
448
|
-
|
449
|
-
string << 'end'
|
450
|
-
else
|
451
|
-
string = <<-EOC
|
452
|
-
module #{Windows::API.auto_namespace}
|
453
|
-
def #{func}(#{proto})
|
454
|
-
#{call_func}.call(#{proto})
|
455
|
-
end
|
456
|
-
EOC
|
457
|
-
|
458
|
-
if api_a
|
459
|
-
string << %Q{
|
460
|
-
def #{func}A(#{proto})
|
461
|
-
#{call_func}A.call(#{proto})
|
462
|
-
end
|
463
|
-
}
|
464
|
-
end
|
465
|
-
|
466
|
-
if api_w
|
467
|
-
string << %Q{
|
468
|
-
def #{func}W(#{proto})
|
469
|
-
#{call_func}W.call(#{proto})
|
470
|
-
end
|
471
|
-
}
|
472
|
-
end
|
473
|
-
|
474
|
-
# Create aliases for methods with an underscore that do not
|
475
|
-
# require an underscore, e.g. umask and _umask.
|
476
|
-
if func[0].chr == '_'
|
477
|
-
func_alias = func[1, func.length]
|
478
|
-
string << "alias #{func_alias} #{func}\n"
|
479
|
-
end
|
480
|
-
|
481
|
-
string << 'end'
|
482
|
-
end
|
483
|
-
|
484
|
-
eval(string)
|
485
|
-
end
|
486
|
-
end
|
439
|
+
end
|
487
440
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
441
|
+
if api_w
|
442
|
+
string << %Q{
|
443
|
+
def #{func}W(#{proto})
|
444
|
+
#{call_func}W.call(#{proto}) != 0
|
445
|
+
end
|
446
|
+
}
|
447
|
+
end
|
448
|
+
|
449
|
+
string << 'end'
|
450
|
+
else
|
451
|
+
string = <<-EOC
|
452
|
+
module #{Windows::API.auto_namespace}
|
453
|
+
def #{func}(#{proto})
|
454
|
+
#{call_func}.call(#{proto})
|
455
|
+
end
|
456
|
+
EOC
|
457
|
+
|
458
|
+
if api_a
|
459
|
+
string << %Q{
|
460
|
+
def #{func}A(#{proto})
|
461
|
+
#{call_func}A.call(#{proto})
|
462
|
+
end
|
463
|
+
}
|
464
|
+
end
|
465
|
+
|
466
|
+
if api_w
|
467
|
+
string << %Q{
|
468
|
+
def #{func}W(#{proto})
|
469
|
+
#{call_func}W.call(#{proto})
|
470
|
+
end
|
471
|
+
}
|
472
|
+
end
|
473
|
+
|
474
|
+
# Create aliases for methods with an underscore that do not
|
475
|
+
# require an underscore, e.g. umask and _umask.
|
476
|
+
if func[0].chr == '_'
|
477
|
+
func_alias = func[1, func.length]
|
478
|
+
string << "alias #{func_alias} #{func}\n"
|
479
|
+
end
|
480
|
+
|
481
|
+
string << 'end'
|
482
|
+
end
|
493
483
|
|
494
|
-
|
495
|
-
|
496
|
-
# Get a module's namespace. This is basically the equivalent of
|
497
|
-
# the rb_path2class() function from intern.h
|
498
|
-
#
|
499
|
-
def class_for(class_name)
|
500
|
-
names = class_name.split("::")
|
501
|
-
result = Object
|
502
|
-
names.each{ |n| result = result.const_get(n) }
|
503
|
-
result
|
484
|
+
eval(string)
|
504
485
|
end
|
505
|
-
|
486
|
+
end
|
487
|
+
|
488
|
+
# Calls the function name set in the constructor.
|
489
|
+
#
|
490
|
+
def call(*args)
|
491
|
+
@api.call(*args)
|
492
|
+
end
|
493
|
+
|
494
|
+
private
|
495
|
+
|
496
|
+
# Get a module's namespace. This is basically the equivalent of
|
497
|
+
# the rb_path2class() function from intern.h
|
498
|
+
#
|
499
|
+
def class_for(class_name)
|
500
|
+
names = class_name.split("::")
|
501
|
+
result = Object
|
502
|
+
names.each{ |n| result = result.const_get(n) }
|
503
|
+
result
|
504
|
+
end
|
505
|
+
end
|
506
506
|
end
|