win32-api 1.0.6 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +5 -0
- data/MANIFEST +3 -2
- data/README +97 -84
- data/ext/win32/api.c +196 -41
- 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 +8 -17
- data/ext/Makefile +0 -181
- data/ext/api-i386-mswin32.def +0 -2
- data/ext/api-i386-mswin32.exp +0 -0
- data/ext/api-i386-mswin32.lib +0 -0
- data/ext/api-i386-mswin32.pdb +0 -0
- data/ext/api.obj +0 -0
- data/ext/mkmf.log +0 -28
- data/ext/vc60.pdb +0 -0
- data/ext/win32/api.so +0 -0
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/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
|
|
@@ -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: ruby
|
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,20 +25,12 @@ extra_rdoc_files:
|
|
25
25
|
- MANIFEST
|
26
26
|
- ext/win32/api.c
|
27
27
|
files:
|
28
|
-
- ext/api-i386-mswin32.def
|
29
|
-
- ext/api-i386-mswin32.exp
|
30
|
-
- ext/api-i386-mswin32.lib
|
31
|
-
- ext/api-i386-mswin32.pdb
|
32
|
-
- ext/api.obj
|
33
28
|
- ext/extconf.rb
|
34
|
-
- ext/Makefile
|
35
|
-
- ext/mkmf.log
|
36
|
-
- ext/vc60.pdb
|
37
29
|
- ext/win32
|
38
30
|
- ext/win32/api.c
|
39
|
-
-
|
40
|
-
- test/
|
41
|
-
- test/
|
31
|
+
- test/test_win32_api.rb
|
32
|
+
- test/test_win32_api_callback.rb
|
33
|
+
- test/test_win32_api_function.rb
|
42
34
|
- README
|
43
35
|
- CHANGES
|
44
36
|
- MANIFEST
|
@@ -53,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
45
|
requirements:
|
54
46
|
- - ">="
|
55
47
|
- !ruby/object:Gem::Version
|
56
|
-
version: 1.8.
|
48
|
+
version: 1.8.2
|
57
49
|
version:
|
58
50
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
51
|
requirements:
|
@@ -68,6 +60,5 @@ rubygems_version: 1.1.1
|
|
68
60
|
signing_key:
|
69
61
|
specification_version: 2
|
70
62
|
summary: A superior replacement for Win32API
|
71
|
-
test_files:
|
72
|
-
|
73
|
-
- test/tc_win32_api_callback.rb
|
63
|
+
test_files: []
|
64
|
+
|
data/ext/Makefile
DELETED
@@ -1,181 +0,0 @@
|
|
1
|
-
|
2
|
-
SHELL = /bin/sh
|
3
|
-
|
4
|
-
#### Start of system configuration section. ####
|
5
|
-
|
6
|
-
srcdir = win32
|
7
|
-
topdir = C:/ruby/lib/ruby/1.8/i386-mswin32
|
8
|
-
hdrdir = $(topdir)
|
9
|
-
VPATH = $(srcdir);$(topdir);$(hdrdir)
|
10
|
-
|
11
|
-
DESTDIR = C:
|
12
|
-
prefix = $(DESTDIR)/ruby
|
13
|
-
exec_prefix = $(DESTDIR)/ruby
|
14
|
-
sitedir = $(prefix)/lib/ruby/site_ruby
|
15
|
-
rubylibdir = $(libdir)/ruby/$(ruby_version)
|
16
|
-
top_srcdir = $(DESTDIR)/develop/win/ruby/ruby-1.8.5
|
17
|
-
archdir = $(rubylibdir)/$(arch)
|
18
|
-
sbindir = $(exec_prefix)/sbin
|
19
|
-
datadir = $(prefix)/share
|
20
|
-
includedir = $(prefix)/include
|
21
|
-
infodir = $(prefix)/info
|
22
|
-
sysconfdir = $(prefix)/etc
|
23
|
-
mandir = $(prefix)/man
|
24
|
-
libdir = $(DESTDIR)/ruby/lib
|
25
|
-
sharedstatedir = $(DESTDIR)/etc
|
26
|
-
oldincludedir = $(DESTDIR)/usr/include
|
27
|
-
sitearchdir = $(sitelibdir)/$(sitearch)
|
28
|
-
localstatedir = $(DESTDIR)/var
|
29
|
-
bindir = $(exec_prefix)/bin
|
30
|
-
sitelibdir = $(sitedir)/$(ruby_version)
|
31
|
-
libexecdir = $(exec_prefix)/libexec
|
32
|
-
|
33
|
-
CC = cl -nologo
|
34
|
-
LIBRUBY = $(RUBY_SO_NAME).lib
|
35
|
-
LIBRUBY_A = msvcrt-ruby18-static.lib
|
36
|
-
LIBRUBYARG_SHARED = $(LIBRUBY)
|
37
|
-
LIBRUBYARG_STATIC = $(LIBRUBY_A)
|
38
|
-
|
39
|
-
RUBY_EXTCONF_H =
|
40
|
-
CFLAGS = -MD -Zi -O2b2xg- -G6
|
41
|
-
INCFLAGS = -I. -I. -IC:/ruby/lib/ruby/1.8/i386-mswin32 -I.
|
42
|
-
CPPFLAGS =
|
43
|
-
CXXFLAGS = $(CFLAGS)
|
44
|
-
DLDFLAGS = -link -incremental:no -debug -opt:ref -opt:icf -dll $(LIBPATH) -def:$(DEFFILE) -implib:$(*F:.so=)-$(arch).lib -pdb:$(*F:.so=)-$(arch).pdb
|
45
|
-
LDSHARED = cl -nologo -LD
|
46
|
-
AR = lib -nologo
|
47
|
-
EXEEXT = .exe
|
48
|
-
|
49
|
-
RUBY_INSTALL_NAME = ruby
|
50
|
-
RUBY_SO_NAME = msvcrt-ruby18
|
51
|
-
arch = i386-mswin32
|
52
|
-
sitearch = i386-msvcrt
|
53
|
-
ruby_version = 1.8
|
54
|
-
ruby = C:/ruby/bin/ruby
|
55
|
-
RUBY = $(ruby:/=\)
|
56
|
-
RM = $(RUBY) -run -e rm -- -f
|
57
|
-
MAKEDIRS = @$(RUBY) -run -e mkdir -- -p
|
58
|
-
INSTALL = copy > nul
|
59
|
-
INSTALL_PROG = $(INSTALL)
|
60
|
-
INSTALL_DATA = $(INSTALL)
|
61
|
-
COPY = copy > nul
|
62
|
-
|
63
|
-
#### End of system configuration section. ####
|
64
|
-
|
65
|
-
preload =
|
66
|
-
|
67
|
-
libpath = $(libdir)
|
68
|
-
LIBPATH = -libpath:"$(libdir)"
|
69
|
-
DEFFILE = $(TARGET)-$(arch).def
|
70
|
-
|
71
|
-
CLEANFILES =
|
72
|
-
DISTCLEANFILES = vc*.pdb $(DEFFILE)
|
73
|
-
|
74
|
-
extout =
|
75
|
-
extout_prefix =
|
76
|
-
target_prefix = /win32
|
77
|
-
LOCAL_LIBS =
|
78
|
-
LIBS = $(LIBRUBYARG_SHARED) oldnames.lib user32.lib advapi32.lib wsock32.lib
|
79
|
-
SRCS = api.c
|
80
|
-
OBJS = api.obj
|
81
|
-
TARGET = api
|
82
|
-
DLLIB = $(TARGET).so
|
83
|
-
EXTSTATIC =
|
84
|
-
STATIC_LIB =
|
85
|
-
|
86
|
-
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
87
|
-
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
88
|
-
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
89
|
-
|
90
|
-
TARGET_SO = $(DLLIB)
|
91
|
-
CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
|
92
|
-
CLEANOBJS = *.obj *.lib *.s[ol] *.pdb *.exp *.bak
|
93
|
-
|
94
|
-
all: $(DLLIB)
|
95
|
-
static: $(STATIC_LIB)
|
96
|
-
|
97
|
-
clean:
|
98
|
-
@-$(RM) $(CLEANLIBS:/=\) $(CLEANOBJS:/=\) $(CLEANFILES:/=\)
|
99
|
-
|
100
|
-
distclean: clean
|
101
|
-
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
102
|
-
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES:/=\)
|
103
|
-
|
104
|
-
realclean: distclean
|
105
|
-
install: install-so install-rb
|
106
|
-
|
107
|
-
install-so: $(RUBYARCHDIR)
|
108
|
-
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
109
|
-
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
110
|
-
$(INSTALL_PROG) $(DLLIB:/=\) $(RUBYARCHDIR:/=\)
|
111
|
-
install-rb: pre-install-rb install-rb-default
|
112
|
-
install-rb-default: pre-install-rb-default
|
113
|
-
pre-install-rb: Makefile
|
114
|
-
pre-install-rb-default: Makefile
|
115
|
-
$(RUBYARCHDIR):
|
116
|
-
$(MAKEDIRS) $@
|
117
|
-
|
118
|
-
site-install: site-install-so site-install-rb
|
119
|
-
site-install-so: install-so
|
120
|
-
site-install-rb: install-rb
|
121
|
-
|
122
|
-
.SUFFIXES: .c .m .cc .cxx .cpp .obj
|
123
|
-
|
124
|
-
{$(srcdir)}.cc{}.obj:
|
125
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
126
|
-
|
127
|
-
{$(topdir)}.cc{}.obj:
|
128
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
129
|
-
|
130
|
-
{$(hdrdir)}.cc{}.obj:
|
131
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
132
|
-
|
133
|
-
.cc.obj:
|
134
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
135
|
-
|
136
|
-
{$(srcdir)}.cxx{}.obj:
|
137
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
138
|
-
|
139
|
-
{$(topdir)}.cxx{}.obj:
|
140
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
141
|
-
|
142
|
-
{$(hdrdir)}.cxx{}.obj:
|
143
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
144
|
-
|
145
|
-
.cxx.obj:
|
146
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
147
|
-
|
148
|
-
{$(srcdir)}.cpp{}.obj:
|
149
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
150
|
-
|
151
|
-
{$(topdir)}.cpp{}.obj:
|
152
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
153
|
-
|
154
|
-
{$(hdrdir)}.cpp{}.obj:
|
155
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
156
|
-
|
157
|
-
.cpp.obj:
|
158
|
-
$(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -Tp$(<:\=/)
|
159
|
-
|
160
|
-
{$(srcdir)}.c{}.obj:
|
161
|
-
$(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) -c -Tc$(<:\=/)
|
162
|
-
|
163
|
-
{$(topdir)}.c{}.obj:
|
164
|
-
$(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) -c -Tc$(<:\=/)
|
165
|
-
|
166
|
-
{$(hdrdir)}.c{}.obj:
|
167
|
-
$(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) -c -Tc$(<:\=/)
|
168
|
-
|
169
|
-
.c.obj:
|
170
|
-
$(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) -c -Tc$(<:\=/)
|
171
|
-
|
172
|
-
$(DLLIB): $(DEFFILE) $(OBJS)
|
173
|
-
@-$(RM) $@
|
174
|
-
$(LDSHARED) -Fe$(@) $(OBJS) $(LIBS) $(LOCAL_LIBS) $(DLDFLAGS)
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
$(DEFFILE):
|
179
|
-
$(RUBY) -e "puts 'EXPORTS', 'Init_$(TARGET)'" > $@
|
180
|
-
|
181
|
-
$(OBJS): {.;$(srcdir);$(topdir);$(hdrdir)}ruby.h {.;$(srcdir);$(topdir);$(hdrdir)}defines.h
|
data/ext/api-i386-mswin32.def
DELETED
data/ext/api-i386-mswin32.exp
DELETED
Binary file
|
data/ext/api-i386-mswin32.lib
DELETED
Binary file
|
data/ext/api-i386-mswin32.pdb
DELETED
Binary file
|
data/ext/api.obj
DELETED
Binary file
|
data/ext/mkmf.log
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
have_func: checking for strncpy_s()... -------------------- no
|
2
|
-
|
3
|
-
"cl -nologo -Feconftest -I. -IC:/ruby/lib/ruby/1.8/i386-mswin32 -I. -IC:/ruby/lib/ruby/1.8/i386-mswin32 -MD -Zi -O2b2xg- -G6 conftest.c msvcrt-ruby18-static.lib oldnames.lib user32.lib advapi32.lib wsock32.lib -link -libpath:"C:/ruby/lib" -stack:0x2000000"
|
4
|
-
conftest.c
|
5
|
-
conftest.obj : error LNK2001: unresolved external symbol _strncpy_s
|
6
|
-
conftest.exe : fatal error LNK1120: 1 unresolved externals
|
7
|
-
checked program was:
|
8
|
-
/* begin */
|
9
|
-
1: /*top*/
|
10
|
-
2: int main() { return 0; }
|
11
|
-
3: int t() { strncpy_s(); return 0; }
|
12
|
-
/* end */
|
13
|
-
|
14
|
-
"cl -nologo -Feconftest -I. -IC:/ruby/lib/ruby/1.8/i386-mswin32 -I. -IC:/ruby/lib/ruby/1.8/i386-mswin32 -MD -Zi -O2b2xg- -G6 conftest.c msvcrt-ruby18-static.lib oldnames.lib user32.lib advapi32.lib wsock32.lib -link -libpath:"C:/ruby/lib" -stack:0x2000000"
|
15
|
-
conftest.c
|
16
|
-
conftest.c(6) : error C2065: 'strncpy_s' : undeclared identifier
|
17
|
-
checked program was:
|
18
|
-
/* begin */
|
19
|
-
1: #include <windows.h>
|
20
|
-
2: #include <winsock.h>
|
21
|
-
3:
|
22
|
-
4: /*top*/
|
23
|
-
5: int main() { return 0; }
|
24
|
-
6: int t() { void ((*volatile p)()); p = (void ((*)()))strncpy_s; return 0; }
|
25
|
-
/* end */
|
26
|
-
|
27
|
-
--------------------
|
28
|
-
|
data/ext/vc60.pdb
DELETED
Binary file
|
data/ext/win32/api.so
DELETED
Binary file
|