win32-api 1.0.6-x86-mswin32-60 → 1.1.0-x86-mswin32-60
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 +3 -2
- data/README +97 -84
- data/ext/extconf.rb +11 -0
- data/ext/win32/api.c +196 -41
- data/lib/win32/api.so +0 -0
- data/test/{tc_win32_api.rb → test_win32_api.rb} +8 -2
- data/test/{tc_win32_api_callback.rb → test_win32_api_callback.rb} +2 -2
- data/test/test_win32_api_function.rb +48 -0
- metadata +11 -9
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
= 1.1.0 - 12-Jun-2008
|
2
|
+
* Added the Windows::API::Function class. This is a subclass of Win32::API
|
3
|
+
meant only for use with raw function pointers.
|
4
|
+
* Some documentation updates in the source and README files.
|
5
|
+
|
1
6
|
= 1.0.6 - 18-Apr-2008
|
2
7
|
* Added the effective_function_name method. This allows you to see what the
|
3
8
|
actual function name is that was defined, e.g. GetUserNameA vs GetUserNameW.
|
data/MANIFEST
CHANGED
data/README
CHANGED
@@ -1,85 +1,98 @@
|
|
1
|
-
= Description
|
2
|
-
This is a drop-in replacement for the Win32API library currently part of
|
3
|
-
Ruby's standard library.
|
4
|
-
|
5
|
-
= Synopsis
|
6
|
-
require 'win32/api'
|
7
|
-
include Win32
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
GetUserName.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
buf.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
=
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
=
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
1
|
+
= Description
|
2
|
+
This is a drop-in replacement for the Win32API library currently part of
|
3
|
+
Ruby's standard library.
|
4
|
+
|
5
|
+
= Synopsis
|
6
|
+
require 'win32/api'
|
7
|
+
include Win32
|
8
|
+
|
9
|
+
# Typical example - Get user name
|
10
|
+
buf = 0.chr * 260
|
11
|
+
len = [buf.length].pack('L')
|
12
|
+
|
13
|
+
GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
|
14
|
+
GetUserName.call(buf, len)
|
15
|
+
|
16
|
+
puts buf.strip
|
17
|
+
|
18
|
+
# Callback example - Enumerate windows
|
19
|
+
EnumWindows = API.new('EnumWindows', 'KP', 'L', 'user32')
|
20
|
+
GetWindowText = API.new('GetWindowText', 'LPI', 'I', 'user32')
|
21
|
+
EnumWindowsProc = API::Callback.new('LP', 'I'){ |handle, param|
|
22
|
+
buf = "\0" * 200
|
23
|
+
GetWindowText.call(handle, buf, 200);
|
24
|
+
puts buf.strip unless buf.strip.empty?
|
25
|
+
buf.index(param).nil? ? true : false
|
26
|
+
}
|
27
|
+
|
28
|
+
EnumWindows.call(EnumWindowsProc, 'UEDIT32')
|
29
|
+
|
30
|
+
# Raw function pointer example - System beep
|
31
|
+
LoadLibrary = API.new('LoadLibrary', 'P', 'L')
|
32
|
+
GetProcAddress = API.new('GetProcAddress', 'LP', 'L')
|
33
|
+
|
34
|
+
hlib = LoadLibrary.call('user32')
|
35
|
+
addr = GetProcAddress.call(hlib, 'MessageBeep')
|
36
|
+
func = Win32::API::Function.new(addr, 'L', 'L')
|
37
|
+
func.call(0)
|
38
|
+
|
39
|
+
= Differences between win32-api and Win32API
|
40
|
+
* This library has callback support
|
41
|
+
* This library supports raw function pointers.
|
42
|
+
* Argument order change. The DLL name is now last, not first.
|
43
|
+
* Removed the 'N' and 'n'. Always use 'L' for longs now.
|
44
|
+
* Sensible default arguments for the prototype, return type and DLL name.
|
45
|
+
* Reader methods for the function name, prototype, return type and DLL.
|
46
|
+
* Removed the support for lower case prototype and return types. Always
|
47
|
+
use capital letters.
|
48
|
+
* Resorts to wide character functions (where possible) when $KCODE is set
|
49
|
+
to UTF8.
|
50
|
+
|
51
|
+
= Developer's Notes
|
52
|
+
The current Win32API library that ships with the standard library has been
|
53
|
+
slated for removal from Ruby 2.0 and it will not receive any updates in the
|
54
|
+
Ruby 1.8.x branch. I have far too many libraries invested in it to let it
|
55
|
+
die at this point.
|
56
|
+
|
57
|
+
In addition, the current Win32API library was written in the bad old Ruby
|
58
|
+
1.6.x days, which means it doesn't use the newer allocation framework.
|
59
|
+
There were several other refactorings that I felt it needed to more closely
|
60
|
+
match how it was actually being used in practice.
|
61
|
+
|
62
|
+
The first order of business was changing the order of the arguments. By
|
63
|
+
moving the DLL name from first to last, I was able to provide reasonable
|
64
|
+
default arguments for the prototype, return type and the DLL. Only the
|
65
|
+
function name is required now.
|
66
|
+
|
67
|
+
There was a laundry list of other refactorings that were needed: sensical
|
68
|
+
instance variable names with proper accessors, removing support for lower
|
69
|
+
case prototype and return value characters that no one used in practice,
|
70
|
+
better naming conventions, the addition of RDoc ready comments and,
|
71
|
+
especially, callback support.
|
72
|
+
|
73
|
+
Most importantly, we can now add, modify and fix any features that we feel
|
74
|
+
best benefit our end users.
|
75
|
+
|
76
|
+
= Documentation
|
77
|
+
The source file contains inline RDoc documentation. If you installed
|
78
|
+
this file as a gem, then you have the docs.
|
79
|
+
|
80
|
+
= Warranty
|
81
|
+
This package is provided "as is" and without any express or
|
82
|
+
implied warranties, including, without limitation, the implied
|
83
|
+
warranties of merchantability and fitness for a particular purpose.
|
84
|
+
|
85
|
+
= Known Bugs
|
86
|
+
None that I'm aware of. Please submit any bug reports to the project page
|
87
|
+
at http://www.rubyforge.org/projects/win32utils.
|
88
|
+
|
89
|
+
= Copyright
|
90
|
+
(C) 2003-2008 Daniel J. Berger
|
91
|
+
All Rights Reserved
|
92
|
+
|
93
|
+
= License
|
94
|
+
Ruby's
|
95
|
+
|
96
|
+
= Authors
|
97
|
+
Daniel J. Berger
|
85
98
|
Park Heesob
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# extconf.rb
|
3
|
+
#
|
4
|
+
# The Windows::API binary should be built using the Rake task, i.e.
|
5
|
+
# 'rake build' or 'rake install'.
|
6
|
+
##########################################################################
|
7
|
+
require 'mkmf'
|
8
|
+
|
9
|
+
have_func('strncpy_s')
|
10
|
+
|
11
|
+
create_makefile('win32/api', 'win32')
|
data/ext/win32/api.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#include <windows.h>
|
3
3
|
|
4
4
|
#define MAX_BUF 1024
|
5
|
-
#define WINDOWS_API_VERSION "1.0
|
5
|
+
#define WINDOWS_API_VERSION "1.1.0"
|
6
6
|
|
7
7
|
#define _T_VOID 0
|
8
8
|
#define _T_LONG 1
|
@@ -12,8 +12,28 @@
|
|
12
12
|
|
13
13
|
VALUE cAPIError, cCallbackError;
|
14
14
|
|
15
|
+
typedef struct {
|
16
|
+
HANDLE library;
|
17
|
+
FARPROC function;
|
18
|
+
int return_type;
|
19
|
+
int prototype[16];
|
20
|
+
} Win32API;
|
21
|
+
|
22
|
+
static void api_free(Win32API* ptr){
|
23
|
+
if(ptr->library)
|
24
|
+
FreeLibrary(ptr->library);
|
25
|
+
|
26
|
+
if(ptr)
|
27
|
+
free(ptr);
|
28
|
+
}
|
29
|
+
|
30
|
+
static VALUE api_allocate(VALUE klass){
|
31
|
+
Win32API* ptr = malloc(sizeof(Win32API));
|
32
|
+
return Data_Wrap_Struct(klass, 0, api_free, ptr);
|
33
|
+
}
|
34
|
+
|
15
35
|
/* Helper function that converts the error number returned by GetLastError()
|
16
|
-
* into a human readable string.
|
36
|
+
* into a human readable string. Internal use only.
|
17
37
|
*/
|
18
38
|
char* StringError(DWORD dwError){
|
19
39
|
LPVOID lpMsgBuf;
|
@@ -52,10 +72,11 @@ char* StringError(DWORD dwError){
|
|
52
72
|
|
53
73
|
/*
|
54
74
|
* call-seq:
|
55
|
-
* Win32::API::Callback.new(prototype, return='L')
|
75
|
+
* Win32::API::Callback.new(prototype, return='L'){ |proto| ... }
|
56
76
|
*
|
57
|
-
* Creates and returns a new Win32::API::Callback object. The
|
58
|
-
* the
|
77
|
+
* Creates and returns a new Win32::API::Callback object. The prototype
|
78
|
+
* arguments are yielded back to the block in the same order they were
|
79
|
+
* declared.
|
59
80
|
*
|
60
81
|
* The +prototype+ is the function prototype for the callback function. This
|
61
82
|
* is a string. The possible valid characters are 'I' (integer), 'L' (long),
|
@@ -65,6 +86,21 @@ char* StringError(DWORD dwError){
|
|
65
86
|
* The +return+ argument is the return type for the callback function. The
|
66
87
|
* valid characters are the same as for the +prototype+. The default is
|
67
88
|
* 'L' (long).
|
89
|
+
*
|
90
|
+
* Example:
|
91
|
+
* require 'win32/api'
|
92
|
+
* include Win32
|
93
|
+
*
|
94
|
+
* EnumWindows = API.new('EnumWindows', 'KP', 'L', 'user32')
|
95
|
+
* GetWindowText = API.new('GetWindowText', 'LPI', 'I', 'user32')
|
96
|
+
* EnumWindowsProc = API::Callback.new('LP', 'I'){ |handle, param|
|
97
|
+
* buf = "\0" * 200
|
98
|
+
* GetWindowText.call(handle, buf, 200);
|
99
|
+
* puts buf.strip unless buf.strip.empty?
|
100
|
+
* buf.index(param).nil? ? true : false
|
101
|
+
* }
|
102
|
+
*
|
103
|
+
* EnumWindows.call(EnumWindowsProc, 'UEDIT32')
|
68
104
|
*/
|
69
105
|
static VALUE callback_init(int argc, VALUE* argv, VALUE self)
|
70
106
|
{
|
@@ -91,27 +127,7 @@ static VALUE callback_init(int argc, VALUE* argv, VALUE self)
|
|
91
127
|
rb_iv_set(self, "@prototype", v_proto);
|
92
128
|
rb_iv_set(self, "@return_type", v_return);
|
93
129
|
|
94
|
-
|
95
|
-
}
|
96
|
-
|
97
|
-
|
98
|
-
typedef struct {
|
99
|
-
HANDLE library;
|
100
|
-
FARPROC function;
|
101
|
-
int return_type;
|
102
|
-
int prototype[16];
|
103
|
-
} Win32API;
|
104
|
-
|
105
|
-
static void api_free(Win32API* ptr){
|
106
|
-
if(ptr->library)
|
107
|
-
FreeLibrary(ptr->library);
|
108
|
-
|
109
|
-
free(ptr);
|
110
|
-
}
|
111
|
-
|
112
|
-
static VALUE api_allocate(VALUE klass){
|
113
|
-
Win32API* ptr = malloc(sizeof(Win32API));
|
114
|
-
return Data_Wrap_Struct(klass, 0, api_free, ptr);
|
130
|
+
return self;
|
115
131
|
}
|
116
132
|
|
117
133
|
/*
|
@@ -134,6 +150,19 @@ static VALUE api_allocate(VALUE klass){
|
|
134
150
|
*
|
135
151
|
* If the function cannot be found then an API::Error is raised (a subclass
|
136
152
|
* of RuntimeError).
|
153
|
+
*
|
154
|
+
* Example:
|
155
|
+
*
|
156
|
+
* require 'win32/api'
|
157
|
+
* include Win32
|
158
|
+
*
|
159
|
+
* buf = 0.chr * 260
|
160
|
+
* len = [buf.length].pack('L')
|
161
|
+
*
|
162
|
+
* GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
|
163
|
+
* GetUserName.call(buf, len)
|
164
|
+
*
|
165
|
+
* puts buf.strip
|
137
166
|
*/
|
138
167
|
static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
139
168
|
{
|
@@ -149,25 +178,25 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
149
178
|
|
150
179
|
Data_Get_Struct(self, Win32API, ptr);
|
151
180
|
|
152
|
-
|
181
|
+
// Convert a string prototype to an array of characters
|
153
182
|
if(rb_respond_to(v_proto, rb_intern("split")))
|
154
183
|
v_proto = rb_str_split(v_proto, "");
|
155
184
|
|
156
|
-
|
157
|
-
if(16 < RARRAY(v_proto)->len)
|
158
|
-
rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
|
159
|
-
|
160
|
-
/* Convert a nil or empty prototype to 'V' (void) automatically */
|
185
|
+
// Convert a nil or empty prototype to 'V' (void) automatically
|
161
186
|
if(NIL_P(v_proto) || RARRAY(v_proto)->len == 0){
|
162
187
|
v_proto = rb_ary_new();
|
163
188
|
rb_ary_push(v_proto, rb_str_new2("V"));
|
164
189
|
}
|
190
|
+
|
191
|
+
// Set an arbitrary limit of 16 parameters
|
192
|
+
if(16 < RARRAY(v_proto)->len)
|
193
|
+
rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
|
165
194
|
|
166
|
-
|
195
|
+
// Set the default dll to 'kernel32'
|
167
196
|
if(NIL_P(v_dll))
|
168
197
|
v_dll = rb_str_new2("kernel32");
|
169
198
|
|
170
|
-
|
199
|
+
// Set the default return type to 'L' (DWORD)
|
171
200
|
if(NIL_P(v_return))
|
172
201
|
v_return = rb_str_new2("L");
|
173
202
|
|
@@ -176,7 +205,7 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
176
205
|
|
177
206
|
hLibrary = LoadLibrary(TEXT(RSTRING(v_dll)->ptr));
|
178
207
|
|
179
|
-
|
208
|
+
// The most likely cause of failure is a bad DLL load path
|
180
209
|
if(!hLibrary){
|
181
210
|
rb_raise(cAPIError, "LoadLibrary() function failed for '%s': %s",
|
182
211
|
RSTRING(v_dll)->ptr,
|
@@ -192,7 +221,7 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
192
221
|
*/
|
193
222
|
fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_proc)->ptr));
|
194
223
|
|
195
|
-
|
224
|
+
// The order of 'A' and 'W' is reversed if $KCODE is set to 'UTF8'.
|
196
225
|
if(!strcmp(rb_get_kcode(), "UTF8")){
|
197
226
|
first = "W";
|
198
227
|
second = "A";
|
@@ -232,7 +261,8 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
232
261
|
|
233
262
|
ptr->function = fProc;
|
234
263
|
|
235
|
-
|
264
|
+
// Push the numeric prototypes onto our int array for later use.
|
265
|
+
|
236
266
|
for(i = 0; i < RARRAY(v_proto)->len; i++){
|
237
267
|
SafeStringValue(RARRAY(v_proto)->ptr[i]);
|
238
268
|
switch(*(char*)StringValuePtr(RARRAY(v_proto)->ptr[i])){
|
@@ -256,9 +286,9 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
256
286
|
}
|
257
287
|
}
|
258
288
|
|
259
|
-
|
260
|
-
|
261
|
-
|
289
|
+
// Store the return type for later use.
|
290
|
+
|
291
|
+
// Automatically convert empty strings or nil to type void.
|
262
292
|
if(NIL_P(v_return) || RSTRING(v_return)->len == 0){
|
263
293
|
v_return = rb_str_new2("V");
|
264
294
|
ptr->return_type = _T_VOID;
|
@@ -291,6 +321,121 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
291
321
|
return self;
|
292
322
|
}
|
293
323
|
|
324
|
+
/*
|
325
|
+
* call-seq:
|
326
|
+
*
|
327
|
+
* API::Function.new(address, prototype = 'V', return_type = 'L')
|
328
|
+
*
|
329
|
+
* Creates and returns an API::Function object. This object is similar to an
|
330
|
+
* API object, except that instead of a character function name you pass a
|
331
|
+
* function pointer address as the first argument, and there's no associated
|
332
|
+
* DLL file.
|
333
|
+
*
|
334
|
+
* Once you have your API::Function object you can then call it the same way
|
335
|
+
* you would an API object.
|
336
|
+
*
|
337
|
+
* Example:
|
338
|
+
*
|
339
|
+
* require 'win32/api'
|
340
|
+
* include Win32
|
341
|
+
*
|
342
|
+
* LoadLibrary = API.new('LoadLibrary', 'P', 'L')
|
343
|
+
* GetProcAddress = API.new('GetProcAddress', 'LP', 'L')
|
344
|
+
*
|
345
|
+
* # Play a system beep
|
346
|
+
* hlib = LoadLibrary.call('user32')
|
347
|
+
* addr = GetProcAddress.call(hlib, 'MessageBeep')
|
348
|
+
* func = Win32::API::Function.new(addr, 'L', 'L')
|
349
|
+
* func.call(0)
|
350
|
+
*/
|
351
|
+
static VALUE func_init(int argc, VALUE* argv, VALUE self){
|
352
|
+
Win32API* ptr;
|
353
|
+
int i;
|
354
|
+
VALUE v_address, v_proto, v_return;
|
355
|
+
|
356
|
+
rb_scan_args(argc, argv, "12", &v_address, &v_proto, &v_return);
|
357
|
+
|
358
|
+
Data_Get_Struct(self, Win32API, ptr);
|
359
|
+
|
360
|
+
// Convert a string prototype to an array of characters
|
361
|
+
if(rb_respond_to(v_proto, rb_intern("split")))
|
362
|
+
v_proto = rb_str_split(v_proto, "");
|
363
|
+
|
364
|
+
// Convert a nil or empty prototype to 'V' (void) automatically
|
365
|
+
if(NIL_P(v_proto) || RARRAY(v_proto)->len == 0){
|
366
|
+
v_proto = rb_ary_new();
|
367
|
+
rb_ary_push(v_proto, rb_str_new2("V"));
|
368
|
+
}
|
369
|
+
|
370
|
+
// Set an arbitrary limit of 16 parameters
|
371
|
+
if(16 < RARRAY(v_proto)->len)
|
372
|
+
rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
|
373
|
+
|
374
|
+
// Set the default return type to 'L' (DWORD)
|
375
|
+
if(NIL_P(v_return))
|
376
|
+
v_return = rb_str_new2("L");
|
377
|
+
|
378
|
+
ptr->function = (FARPROC)NUM2LONG(v_address);
|
379
|
+
|
380
|
+
// Push the numeric prototypes onto our int array for later use.
|
381
|
+
|
382
|
+
for(i = 0; i < RARRAY(v_proto)->len; i++){
|
383
|
+
SafeStringValue(RARRAY(v_proto)->ptr[i]);
|
384
|
+
switch(*(char*)StringValuePtr(RARRAY(v_proto)->ptr[i])){
|
385
|
+
case 'L':
|
386
|
+
ptr->prototype[i] = _T_LONG;
|
387
|
+
break;
|
388
|
+
case 'P':
|
389
|
+
ptr->prototype[i] = _T_POINTER;
|
390
|
+
break;
|
391
|
+
case 'I': case 'B':
|
392
|
+
ptr->prototype[i] = _T_INTEGER;
|
393
|
+
break;
|
394
|
+
case 'V':
|
395
|
+
ptr->prototype[i] = _T_VOID;
|
396
|
+
break;
|
397
|
+
case 'K':
|
398
|
+
ptr->prototype[i] = _T_CALLBACK;
|
399
|
+
break;
|
400
|
+
default:
|
401
|
+
rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
|
402
|
+
}
|
403
|
+
}
|
404
|
+
|
405
|
+
// Store the return type for later use.
|
406
|
+
|
407
|
+
// Automatically convert empty strings or nil to type void.
|
408
|
+
if(NIL_P(v_return) || RSTRING(v_return)->len == 0){
|
409
|
+
v_return = rb_str_new2("V");
|
410
|
+
ptr->return_type = _T_VOID;
|
411
|
+
}
|
412
|
+
else{
|
413
|
+
SafeStringValue(v_return);
|
414
|
+
switch(*RSTRING(v_return)->ptr){
|
415
|
+
case 'L':
|
416
|
+
ptr->return_type = _T_LONG;
|
417
|
+
break;
|
418
|
+
case 'P':
|
419
|
+
ptr->return_type = _T_POINTER;
|
420
|
+
break;
|
421
|
+
case 'I': case 'B':
|
422
|
+
ptr->return_type = _T_INTEGER;
|
423
|
+
break;
|
424
|
+
case 'V':
|
425
|
+
ptr->return_type = _T_VOID;
|
426
|
+
break;
|
427
|
+
default:
|
428
|
+
rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
|
429
|
+
}
|
430
|
+
}
|
431
|
+
|
432
|
+
rb_iv_set(self, "@address", v_address);
|
433
|
+
rb_iv_set(self, "@prototype", v_proto);
|
434
|
+
rb_iv_set(self, "@return_type", v_return);
|
435
|
+
|
436
|
+
return self;
|
437
|
+
}
|
438
|
+
|
294
439
|
typedef struct {
|
295
440
|
DWORD params[1];
|
296
441
|
} PARAM;
|
@@ -481,7 +626,7 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){
|
|
481
626
|
* Wraps the Windows API functions in a Ruby interface.
|
482
627
|
*/
|
483
628
|
void Init_api(){
|
484
|
-
VALUE mWin32, cAPI, cCallback;
|
629
|
+
VALUE mWin32, cAPI, cCallback, cFunction;
|
485
630
|
|
486
631
|
/* Modules and Classes */
|
487
632
|
|
@@ -493,6 +638,9 @@ void Init_api(){
|
|
493
638
|
|
494
639
|
/* The API::Callback class encapsulates a Windows CALLBACK function */
|
495
640
|
cCallback = rb_define_class_under(cAPI, "Callback", rb_cObject);
|
641
|
+
|
642
|
+
/* The API::Function class encapsulates a raw function pointer */
|
643
|
+
cFunction = rb_define_class_under(cAPI, "Function", cAPI);
|
496
644
|
|
497
645
|
/* The API::Error class is raised if the constructor fails */
|
498
646
|
cAPIError = rb_define_class_under(cAPI, "Error", rb_eRuntimeError);
|
@@ -507,7 +655,11 @@ void Init_api(){
|
|
507
655
|
rb_define_method(cAPI, "initialize", api_init, -1);
|
508
656
|
rb_define_method(cAPI, "call", api_call, -1);
|
509
657
|
|
658
|
+
/* Win32::API::Callback Instance Methods */
|
510
659
|
rb_define_method(cCallback, "initialize", callback_init, -1);
|
660
|
+
|
661
|
+
/* Win32::API::Function Instance Methods */
|
662
|
+
rb_define_method(cFunction, "initialize", func_init, -1);
|
511
663
|
|
512
664
|
/* The name of the DLL that exports the API function */
|
513
665
|
rb_define_attr(cAPI, "dll_name", 1, 0);
|
@@ -534,6 +686,9 @@ void Init_api(){
|
|
534
686
|
|
535
687
|
/* The return type, returned as a single character, P, L, I, V or B */
|
536
688
|
rb_define_attr(cCallback, "return_type", 1, 0);
|
689
|
+
|
690
|
+
/* The numeric address of the function pointer */
|
691
|
+
rb_define_attr(cFunction, "address", 1, 0);
|
537
692
|
|
538
693
|
/* Constants */
|
539
694
|
|
data/lib/win32/api.so
CHANGED
Binary file
|
@@ -1,5 +1,5 @@
|
|
1
1
|
############################################################################
|
2
|
-
#
|
2
|
+
# test_win32_api.rb
|
3
3
|
#
|
4
4
|
# Test case for the Win32::API class. You should run this as Rake task,
|
5
5
|
# i.e. 'rake test', instead of running it directly.
|
@@ -16,7 +16,7 @@ class TC_Win32_API < Test::Unit::TestCase
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_version
|
19
|
-
assert_equal('1.0
|
19
|
+
assert_equal('1.1.0', API::VERSION)
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_call
|
@@ -43,6 +43,12 @@ class TC_Win32_API < Test::Unit::TestCase
|
|
43
43
|
def test_effective_function_name
|
44
44
|
assert_respond_to(@api, :effective_function_name)
|
45
45
|
assert_equal('GetCurrentDirectoryA', @api.effective_function_name)
|
46
|
+
|
47
|
+
@api = API.new('GetCurrentDirectoryA', 'LP')
|
48
|
+
assert_equal('GetCurrentDirectoryA', @api.effective_function_name)
|
49
|
+
|
50
|
+
@api = API.new('GetCurrentDirectoryW', 'LP')
|
51
|
+
assert_equal('GetCurrentDirectoryW', @api.effective_function_name)
|
46
52
|
end
|
47
53
|
|
48
54
|
def test_prototype
|
@@ -1,5 +1,5 @@
|
|
1
1
|
############################################################################
|
2
|
-
#
|
2
|
+
# test_win32_api_callback.rb
|
3
3
|
#
|
4
4
|
# Test case for the Win32::API::Callback class. You should run this as Rake
|
5
5
|
# task, i.e. 'rake test', instead of running it directly.
|
@@ -55,4 +55,4 @@ class TC_Win32_API_Callback < Test::Unit::TestCase
|
|
55
55
|
@api_gwt = nil
|
56
56
|
@callback = nil
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
########################################################################
|
2
|
+
# test_win32_api_function.rb
|
3
|
+
#
|
4
|
+
# Test case for the Win32::API::Function class. You should run these
|
5
|
+
# tests via the 'rake test' task.
|
6
|
+
########################################################################
|
7
|
+
require 'test/unit'
|
8
|
+
require 'win32/api'
|
9
|
+
|
10
|
+
class TC_Win32_API_Function < Test::Unit::TestCase
|
11
|
+
def setup
|
12
|
+
@func = Win32::API::Function.new(123456789, 'LP', 'L')
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_constructor
|
16
|
+
assert_nothing_raised{ Win32::API::Function.new(1) }
|
17
|
+
assert_nothing_raised{ Win32::API::Function.new(1, 'LL') }
|
18
|
+
assert_nothing_raised{ Win32::API::Function.new(1, 'LL', 'I') }
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_subclass
|
22
|
+
assert_kind_of(Win32::API, @func)
|
23
|
+
assert_respond_to(@func, :call)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_address
|
27
|
+
assert_respond_to(@func, :address)
|
28
|
+
assert_equal(123456789, @func.address)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_prototype
|
32
|
+
assert_respond_to(@func, :prototype)
|
33
|
+
assert_equal(['L', 'P'], @func.prototype)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_return_type
|
37
|
+
assert_respond_to(@func, :return_type)
|
38
|
+
assert_equal('L', @func.return_type)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_expected_errors
|
42
|
+
assert_raise(ArgumentError){ Win32::API::Function.new }
|
43
|
+
end
|
44
|
+
|
45
|
+
def teardown
|
46
|
+
@func = nil
|
47
|
+
end
|
48
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: x86-mswin32-60
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-06-12 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -25,14 +25,17 @@ extra_rdoc_files:
|
|
25
25
|
- MANIFEST
|
26
26
|
- ext/win32/api.c
|
27
27
|
files:
|
28
|
+
- ext/extconf.rb
|
29
|
+
- ext/win32
|
30
|
+
- ext/win32/api.c
|
31
|
+
- test/test_win32_api.rb
|
32
|
+
- test/test_win32_api_callback.rb
|
33
|
+
- test/test_win32_api_function.rb
|
28
34
|
- lib/win32
|
29
35
|
- lib/win32/api.so
|
30
|
-
- test/tc_win32_api.rb
|
31
|
-
- test/tc_win32_api_callback.rb
|
32
36
|
- README
|
33
37
|
- CHANGES
|
34
38
|
- MANIFEST
|
35
|
-
- ext/win32/api.c
|
36
39
|
has_rdoc: true
|
37
40
|
homepage: http://www.rubyforge.org/projects/win32utils
|
38
41
|
post_install_message:
|
@@ -44,7 +47,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
47
|
requirements:
|
45
48
|
- - ">="
|
46
49
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.8.
|
50
|
+
version: 1.8.2
|
48
51
|
version:
|
49
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
53
|
requirements:
|
@@ -59,6 +62,5 @@ rubygems_version: 1.1.1
|
|
59
62
|
signing_key:
|
60
63
|
specification_version: 2
|
61
64
|
summary: A superior replacement for Win32API
|
62
|
-
test_files:
|
63
|
-
|
64
|
-
- test/tc_win32_api_callback.rb
|
65
|
+
test_files: []
|
66
|
+
|