win32-api 1.0.3-mswin32 → 1.0.4-mswin32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,18 +1,24 @@
1
- = 1.0.3 - 28-Sep-2007
2
- * Fixed a subtle but dangerous copy-on-write bug in the API#call method.
3
-
4
- = 1.0.2 - 28-Sep-2007
5
- * Fixed a bug in an internal struct member that was causing segfaults. Thanks
6
- go to Lars Olsson for the spot.
7
- * Fixed the 'install' task in the Rakefile. This only affected native builds,
8
- not the prebuilt binary.
9
- * Added a few more tests.
10
-
11
- = 1.0.1 - 27-Sep-2007
12
- * Functions declared with a void prototype no longer require an explicit nil
13
- argument to fulfill the arity requirement. You can still call them with an
14
- explicit nil if you wish, however.
15
- * Fixed the gemspec for the native build.
16
-
17
- = 1.0.0 - 14-Sep-2007
1
+ = 1.0.4 - 26-Oct-2007
2
+ * Fixed a bug where methods that returned pointers ('P') could choke if the
3
+ resulting pointer was 0 or NULL. In this case, nil is now returned instead.
4
+ * Tweak to the extconf.rb file that helps the gem build it from source
5
+ properly.
6
+
7
+ = 1.0.3 - 28-Sep-2007
8
+ * Fixed a subtle but dangerous copy-on-write bug in the API#call method.
9
+
10
+ = 1.0.2 - 28-Sep-2007
11
+ * Fixed a bug in an internal struct member that was causing segfaults. Thanks
12
+ go to Lars Olsson for the spot.
13
+ * Fixed the 'install' task in the Rakefile. This only affected native builds,
14
+ not the prebuilt binary.
15
+ * Added a few more tests.
16
+
17
+ = 1.0.1 - 27-Sep-2007
18
+ * Functions declared with a void prototype no longer require an explicit nil
19
+ argument to fulfill the arity requirement. You can still call them with an
20
+ explicit nil if you wish, however.
21
+ * Fixed the gemspec for the native build.
22
+
23
+ = 1.0.0 - 14-Sep-2007
18
24
  * Initial release
data/MANIFEST CHANGED
@@ -1,9 +1,9 @@
1
- CHANGES
2
- MANIFEST
3
- README
4
- Rakefile
5
- win32-api.gemspec
6
- ext/extconf.rb
7
- ext/win32/api.c
8
- test/tc_win32_api_callback.rb
9
- test/tc_win32_api.rb
1
+ * CHANGES
2
+ * MANIFEST
3
+ * README
4
+ * Rakefile
5
+ * win32-api.gemspec
6
+ * ext/extconf.rb
7
+ * ext/win32/api.c
8
+ * test/tc_win32_api_callback.rb
9
+ * test/tc_win32_api.rb
data/README CHANGED
@@ -1,72 +1,72 @@
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
- buf = 0.chr * 260
10
- len = [@buf.length].pack('L')
11
-
12
- GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
13
- GetUserName.call(buf, len)
14
-
15
- puts buf.strip
16
-
17
- = Differences between win32-api and Win32API
18
- * Argument order change. The DLL name is now last, not first.
19
- * Removed the 'N' and 'n'. Always use 'L' for longs now.
20
- * Sensible default arguments for the prototype, return type and DLL name.
21
- * Reader methods for the function name, prototype, return type and DLL.
22
- * Removed the support for lower case prototype and return types. Always
23
- use capital letters.
24
-
25
- = Developer's Notes
26
- The current Win32API library that ships with the standard library has been
27
- slated for removal from Ruby 2.0 and it will not receive any updates in the
28
- Ruby 1.8.x branch. I have far too many libraries invested in it to let it
29
- die at this point.
30
-
31
- In addition, the current Win32API library was written in the bad old Ruby
32
- 1.6.x days, which means it doesn't use the newer allocation framework.
33
- There were several other refactorings that I felt it needed to more closely
34
- match how it was actually being used in practice.
35
-
36
- The first order of business was changing the order of the arguments. By
37
- moving the DLL name from first to last, I was able to provide reasonable
38
- default arguments for the prototype, return type and the DLL. Only the
39
- function name is required now.
40
-
41
- There was a laundry list of other refactorings that were needed: sensical
42
- instance variable names with proper accessors, removing support for lower
43
- case prototype and return value characters that no one used in practice,
44
- better naming conventions, the addition of RDoc ready comments and,
45
- especially, callback support.
46
-
47
- Most importantly, we can now add, modify and fix any features that we feel
48
- best benefit our end users.
49
-
50
- = Documentation
51
- The source file contains inline RDoc documentation. If you installed
52
- this file as a gem, then you have the docs.
53
-
54
- = Warranty
55
- This package is provided "as is" and without any express or
56
- implied warranties, including, without limitation, the implied
57
- warranties of merchantability and fitness for a particular purpose.
58
-
59
- = Known Bugs
60
- None that I'm aware of. Please submit any bug reports to the project page
61
- at http://www.rubyforge.org/projects/win32utils.
62
-
63
- = Copyright
64
- (C) 2003-2007 Daniel J. Berger
65
- All Rights Reserved
66
-
67
- = License
68
- Ruby's
69
-
70
- = Authors
71
- Daniel J. Berger
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
+ buf = 0.chr * 260
10
+ len = [@buf.length].pack('L')
11
+
12
+ GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
13
+ GetUserName.call(buf, len)
14
+
15
+ puts buf.strip
16
+
17
+ = Differences between win32-api and Win32API
18
+ * Argument order change. The DLL name is now last, not first.
19
+ * Removed the 'N' and 'n'. Always use 'L' for longs now.
20
+ * Sensible default arguments for the prototype, return type and DLL name.
21
+ * Reader methods for the function name, prototype, return type and DLL.
22
+ * Removed the support for lower case prototype and return types. Always
23
+ use capital letters.
24
+
25
+ = Developer's Notes
26
+ The current Win32API library that ships with the standard library has been
27
+ slated for removal from Ruby 2.0 and it will not receive any updates in the
28
+ Ruby 1.8.x branch. I have far too many libraries invested in it to let it
29
+ die at this point.
30
+
31
+ In addition, the current Win32API library was written in the bad old Ruby
32
+ 1.6.x days, which means it doesn't use the newer allocation framework.
33
+ There were several other refactorings that I felt it needed to more closely
34
+ match how it was actually being used in practice.
35
+
36
+ The first order of business was changing the order of the arguments. By
37
+ moving the DLL name from first to last, I was able to provide reasonable
38
+ default arguments for the prototype, return type and the DLL. Only the
39
+ function name is required now.
40
+
41
+ There was a laundry list of other refactorings that were needed: sensical
42
+ instance variable names with proper accessors, removing support for lower
43
+ case prototype and return value characters that no one used in practice,
44
+ better naming conventions, the addition of RDoc ready comments and,
45
+ especially, callback support.
46
+
47
+ Most importantly, we can now add, modify and fix any features that we feel
48
+ best benefit our end users.
49
+
50
+ = Documentation
51
+ The source file contains inline RDoc documentation. If you installed
52
+ this file as a gem, then you have the docs.
53
+
54
+ = Warranty
55
+ This package is provided "as is" and without any express or
56
+ implied warranties, including, without limitation, the implied
57
+ warranties of merchantability and fitness for a particular purpose.
58
+
59
+ = Known Bugs
60
+ None that I'm aware of. Please submit any bug reports to the project page
61
+ at http://www.rubyforge.org/projects/win32utils.
62
+
63
+ = Copyright
64
+ (C) 2003-2007 Daniel J. Berger
65
+ All Rights Reserved
66
+
67
+ = License
68
+ Ruby's
69
+
70
+ = Authors
71
+ Daniel J. Berger
72
72
  Park Heesob
@@ -0,0 +1,10 @@
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
+ create_makefile('win32/api', 'win32')
@@ -0,0 +1,524 @@
1
+ #include <ruby.h>
2
+ #include <windows.h>
3
+
4
+ #define MAX_BUF 1024
5
+ #define WINDOWS_API_VERSION "1.0.4"
6
+
7
+ #define _T_VOID 0
8
+ #define _T_LONG 1
9
+ #define _T_POINTER 2
10
+ #define _T_INTEGER 3
11
+ #define _T_CALLBACK 4
12
+
13
+ VALUE cAPIError, cCallbackError;
14
+
15
+ /* Helper function that converts the error number returned by GetLastError()
16
+ * into a human readable string. Internal use only.
17
+ */
18
+ char* StringError(DWORD dwError){
19
+ LPVOID lpMsgBuf;
20
+ static char buf[MAX_PATH];
21
+ DWORD dwLen;
22
+
23
+ /* Assume ASCII error messages from the Windows API */
24
+ dwLen = FormatMessageA(
25
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
26
+ FORMAT_MESSAGE_FROM_SYSTEM |
27
+ FORMAT_MESSAGE_IGNORE_INSERTS,
28
+ NULL,
29
+ dwError,
30
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
31
+ (LPSTR)&lpMsgBuf,
32
+ 0,
33
+ NULL
34
+ );
35
+
36
+ if(!dwLen)
37
+ rb_raise(cAPIError, "Attempt to format message failed");
38
+
39
+ memset(buf, 0, MAX_PATH);
40
+
41
+ /* remove \r\n */
42
+ #ifdef HAVE_STRNCPY_S
43
+ strncpy_s(buf, MAX_PATH, lpMsgBuf, dwLen - 2);
44
+ #else
45
+ strncpy(buf, lpMsgBuf, dwLen - 2);
46
+ #endif
47
+
48
+ LocalFree(lpMsgBuf);
49
+
50
+ return buf;
51
+ }
52
+
53
+ /*
54
+ * call-seq:
55
+ * Win32::API::Callback.new(prototype, return='L')
56
+ *
57
+ * Creates and returns a new Win32::API::Callback object. The +function+ is
58
+ * the name of the Windows function.
59
+ *
60
+ * The +prototype+ is the function prototype for the callback function. This
61
+ * is a string. The possible valid characters are 'I' (integer), 'L' (long),
62
+ * 'V' (void), or 'P' (pointer). Unlike API objects, API::Callback objects
63
+ * do not have a default prototype.
64
+ *
65
+ * The +return+ argument is the return type for the callback function. The
66
+ * valid characters are the same as for the +prototype+. The default is
67
+ * 'L' (long).
68
+ */
69
+ static VALUE callback_init(int argc, VALUE* argv, VALUE self)
70
+ {
71
+ VALUE v_proto, v_return, v_proc;
72
+ int i;
73
+
74
+ rb_scan_args(argc, argv, "11", &v_proto, &v_return);
75
+
76
+ /* Validate prototype characters */
77
+ for(i = 0; i < RSTRING(v_proto)->len; i++){
78
+ switch(RSTRING(v_proto)->ptr[i]){
79
+ case 'I': case 'L': case 'P': case 'V':
80
+ break;
81
+ default:
82
+ rb_raise(cCallbackError, "Illegal prototype '%c'",
83
+ RSTRING(v_proto)->ptr[i]);
84
+ }
85
+ }
86
+
87
+ if(NIL_P(v_return) || RARRAY(v_return)->len == 0)
88
+ v_return = rb_str_new2("L");
89
+
90
+ if(rb_block_given_p())
91
+ v_proc = rb_block_proc();
92
+ else
93
+ v_proc = Qnil;
94
+
95
+ rb_iv_set(self, "@function", v_proc);
96
+ rb_iv_set(self, "@prototype", v_proto);
97
+ rb_iv_set(self, "@return_type", v_return);
98
+
99
+ return self;
100
+ }
101
+
102
+
103
+ typedef struct {
104
+ HANDLE library;
105
+ FARPROC function;
106
+ int return_type;
107
+ int prototype[16];
108
+ } Win32API;
109
+
110
+ static void api_free(Win32API* ptr){
111
+ if(ptr->library)
112
+ FreeLibrary(ptr->library);
113
+
114
+ free(ptr);
115
+ }
116
+
117
+ static VALUE api_allocate(VALUE klass){
118
+ Win32API* ptr = malloc(sizeof(Win32API));
119
+ return Data_Wrap_Struct(klass, 0, api_free, ptr);
120
+ }
121
+
122
+ /*
123
+ * call-seq:
124
+ * Win32::API.new(function, prototype='V', return='L', dll='kernel32')
125
+ *
126
+ * Creates and returns a new Win32::API object. The +function+ is the name
127
+ * of the Windows function.
128
+ *
129
+ * The +prototype+ is the function prototype for +function+. This can be a
130
+ * string or an array of characters. The possible valid characters are 'I'
131
+ * (integer), 'L' (long), 'V' (void), 'P' (pointer), or 'K' (callback).
132
+ * The default is void ('V').
133
+ *
134
+ * The +return+ argument is the return type for the function. The valid
135
+ * characters are the same as for the +prototype+. The default is 'L' (long).
136
+ *
137
+ * The +dll+ is the name of the DLL file that the function is exported from.
138
+ * The default is 'kernel32'.
139
+ *
140
+ * If the function cannot be found then an API::Error is raised (a subclass
141
+ * of RuntimeError).
142
+ */
143
+ static VALUE api_init(int argc, VALUE* argv, VALUE self)
144
+ {
145
+ HMODULE hLibrary;
146
+ FARPROC fProc;
147
+ Win32API* ptr;
148
+ int i;
149
+ VALUE v_proc, v_proto, v_return, v_dll, v_bool, v_name;
150
+
151
+ rb_scan_args(argc, argv, "13", &v_proc, &v_proto, &v_return, &v_dll);
152
+
153
+ Data_Get_Struct(self, Win32API, ptr);
154
+
155
+ /* Convert a string prototype to an array of characters */
156
+ if(rb_respond_to(v_proto, rb_intern("split")))
157
+ v_proto = rb_str_split(v_proto, "");
158
+
159
+ /* Set an arbitrary limit of 16 parameters */
160
+ if(16 < RARRAY(v_proto)->len)
161
+ rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
162
+
163
+ /* Convert a nil or empty prototype to 'V' (void) automatically */
164
+ if(NIL_P(v_proto) || RARRAY(v_proto)->len == 0){
165
+ v_proto = rb_ary_new();
166
+ rb_ary_push(v_proto, rb_str_new2("V"));
167
+ }
168
+
169
+ /* Set the default dll to 'kernel32' */
170
+ if(NIL_P(v_dll))
171
+ v_dll = rb_str_new2("kernel32");
172
+
173
+ /* Set the default return type to 'L' (DWORD) */
174
+ if(NIL_P(v_return))
175
+ v_return = rb_str_new2("L");
176
+
177
+ SafeStringValue(v_dll);
178
+ SafeStringValue(v_proc);
179
+
180
+ hLibrary = LoadLibrary(TEXT(RSTRING(v_dll)->ptr));
181
+
182
+ /* The most likely cause of failure is a bad DLL load path */
183
+ if(!hLibrary){
184
+ rb_raise(cAPIError, "LoadLibrary() function failed for '%s': %s",
185
+ RSTRING(v_dll)->ptr,
186
+ StringError(GetLastError())
187
+ );
188
+ }
189
+
190
+ ptr->library = hLibrary;
191
+
192
+ /* Attempt to get the function. If it fails, try again with an 'A'
193
+ * appended. If that fails, try again with a 'W' appended. If that
194
+ * still fails, raise an API::Error.
195
+ */
196
+ fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_proc)->ptr));
197
+
198
+ if(!fProc){
199
+ VALUE v_ascii = rb_str_new3(v_proc);
200
+ v_ascii = rb_str_cat(v_ascii, "A", 1);
201
+ fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_ascii)->ptr));
202
+
203
+ if(!fProc){
204
+ VALUE v_unicode = rb_str_new3(v_proc);
205
+ v_unicode = rb_str_cat(v_unicode, "W", 1);
206
+ fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_unicode)->ptr));
207
+
208
+ if(!fProc){
209
+ rb_raise(
210
+ cAPIError,
211
+ "GetProcAddress() failed for '%s', '%s' and '%s': %s",
212
+ RSTRING(v_proc)->ptr,
213
+ RSTRING(v_ascii)->ptr,
214
+ RSTRING(v_unicode)->ptr,
215
+ StringError(GetLastError())
216
+ );
217
+ }
218
+ }
219
+ }
220
+
221
+ ptr->function = fProc;
222
+
223
+ /* Push the numeric prototypes onto our int array for later use. */
224
+ for(i = 0; i < RARRAY(v_proto)->len; i++){
225
+ SafeStringValue(RARRAY(v_proto)->ptr[i]);
226
+ switch(*(char*)StringValuePtr(RARRAY(v_proto)->ptr[i])){
227
+ case 'L':
228
+ ptr->prototype[i] = _T_LONG;
229
+ break;
230
+ case 'P':
231
+ ptr->prototype[i] = _T_POINTER;
232
+ break;
233
+ case 'I': case 'B':
234
+ ptr->prototype[i] = _T_INTEGER;
235
+ break;
236
+ case 'V':
237
+ ptr->prototype[i] = _T_VOID;
238
+ break;
239
+ case 'K':
240
+ ptr->prototype[i] = _T_CALLBACK;
241
+ break;
242
+ default:
243
+ rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
244
+ }
245
+ }
246
+
247
+ /* Store the return type for later use. Automatically convert empty
248
+ * strings or nil to type void.
249
+ */
250
+ if(NIL_P(v_return) || RSTRING(v_return)->len == 0){
251
+ v_return = rb_str_new2("V");
252
+ ptr->return_type = _T_VOID;
253
+ }
254
+ else{
255
+ SafeStringValue(v_return);
256
+ switch(*RSTRING(v_return)->ptr){
257
+ case 'L':
258
+ ptr->return_type = _T_LONG;
259
+ break;
260
+ case 'P':
261
+ ptr->return_type = _T_POINTER;
262
+ break;
263
+ case 'I': case 'B':
264
+ ptr->return_type = _T_INTEGER;
265
+ break;
266
+ case 'V':
267
+ ptr->return_type = _T_VOID;
268
+ break;
269
+ default:
270
+ rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
271
+ }
272
+ }
273
+
274
+ rb_iv_set(self, "@dll_name", v_dll);
275
+ rb_iv_set(self, "@function_name", v_proc);
276
+ rb_iv_set(self, "@prototype", v_proto);
277
+ rb_iv_set(self, "@return_type", v_return);
278
+
279
+ return self;
280
+ }
281
+
282
+ typedef struct {
283
+ DWORD params[1];
284
+ } PARAM;
285
+
286
+ static VALUE ActiveCallback;
287
+
288
+ DWORD CallbackFunction(PARAM param)
289
+ {
290
+ VALUE v_proto, v_return, v_proc, v_retval;
291
+ VALUE argv[16];
292
+ int i, argc;
293
+ char *a_proto;
294
+ char *a_return;
295
+
296
+ if(!NIL_P(ActiveCallback)){
297
+ v_proto = rb_iv_get(ActiveCallback, "@prototype");
298
+ a_proto = RSTRING(v_proto)->ptr;
299
+
300
+ v_return = rb_iv_get(ActiveCallback, "@return_type");
301
+ a_return = RSTRING(v_return)->ptr;
302
+
303
+ v_proc = rb_iv_get(ActiveCallback, "@function");
304
+ argc = RSTRING(v_proto)->len;
305
+
306
+ for(i=0; i < RSTRING(v_proto)->len; i++){
307
+ argv[i] = Qnil;
308
+ switch(a_proto[i]){
309
+ case 'L':
310
+ argv[i] = ULONG2NUM(param.params[i]);
311
+ break;
312
+ case 'P':
313
+ if(param.params[i])
314
+ argv[i] = rb_str_new2((char *)param.params[i]);
315
+ break;
316
+ case 'I':
317
+ argv[i] = INT2NUM(param.params[i]);
318
+ break;
319
+ default:
320
+ rb_raise(cCallbackError, "Illegal prototype '%c'", a_proto[i]);
321
+ }
322
+ }
323
+
324
+ v_retval = rb_funcall2(v_proc, rb_intern("call"), argc, argv);
325
+
326
+ /* Handle true and false explicitly, as some CALLBACK functions
327
+ * require TRUE or FALSE to break out of loops, etc.
328
+ */
329
+ if(v_retval == Qtrue)
330
+ return TRUE;
331
+ else if(v_retval == Qfalse)
332
+ return FALSE;
333
+
334
+ switch (*a_return) {
335
+ case 'I':
336
+ return NUM2INT(v_retval);
337
+ break;
338
+ case 'L':
339
+ return NUM2ULONG(v_retval);
340
+ break;
341
+ case 'P':
342
+ if(NIL_P(v_retval)){
343
+ return 0;
344
+ }
345
+ else if (FIXNUM_P(v_retval)){
346
+ return NUM2ULONG(v_retval);
347
+ }
348
+ else{
349
+ StringValue(v_retval);
350
+ rb_str_modify(v_retval);
351
+ return (unsigned long)StringValuePtr(v_retval);
352
+ }
353
+ break;
354
+ }
355
+ }
356
+
357
+ return 0;
358
+ }
359
+
360
+ /*
361
+ * call-seq:
362
+ * Win32::API#call(arg1, arg2, ...)
363
+ *
364
+ * Calls the function pointer with the given arguments (if any). Note that,
365
+ * while this method will catch some prototype mismatches (raising a TypeError
366
+ * in the process), it is not fulproof. It is ultimately your job to make
367
+ * sure the arguments match the +prototype+ specified in the constructor.
368
+ *
369
+ * For convenience, nil is converted to NULL, true is converted to TRUE (1)
370
+ * and false is converted to FALSE (0).
371
+ */
372
+ static VALUE api_call(int argc, VALUE* argv, VALUE self){
373
+ VALUE v_proto, v_args, v_arg, v_return;
374
+ Win32API* ptr;
375
+ unsigned long return_value;
376
+ int i = 0;
377
+
378
+ struct{
379
+ unsigned long params[16];
380
+ } param;
381
+
382
+ Data_Get_Struct(self, Win32API, ptr);
383
+
384
+ rb_scan_args(argc, argv, "0*", &v_args);
385
+
386
+ v_proto = rb_iv_get(self, "@prototype");
387
+
388
+ /* For void prototypes, allow either no args or an explicit nil */
389
+ if(RARRAY(v_proto)->len != RARRAY(v_args)->len){
390
+ char* c = StringValuePtr(RARRAY(v_proto)->ptr[0]);
391
+ if(!strcmp(c, "V")){
392
+ rb_ary_push(v_args, Qnil);
393
+ }
394
+ else{
395
+ rb_raise(rb_eArgError,
396
+ "wrong number of parameters: expected %d, got %d",
397
+ RARRAY(v_proto)->len, RARRAY(v_args)->len
398
+ );
399
+ }
400
+ }
401
+
402
+ for(i = 0; i < RARRAY(v_proto)->len; i++){
403
+ v_arg = RARRAY(v_args)->ptr[i];
404
+
405
+ /* Convert nil to NULL. Otherwise convert as appropriate. */
406
+ if(NIL_P(v_arg))
407
+ param.params[i] = (unsigned long)NULL;
408
+ else if(v_arg == Qtrue)
409
+ param.params[i] = TRUE;
410
+ else if(v_arg == Qfalse)
411
+ param.params[i] = FALSE;
412
+ else
413
+ switch(ptr->prototype[i]){
414
+ case _T_LONG:
415
+ param.params[i] = NUM2ULONG(v_arg);
416
+ break;
417
+ case _T_INTEGER:
418
+ param.params[i] = NUM2INT(v_arg);
419
+ break;
420
+ case _T_POINTER:
421
+ if(FIXNUM_P(v_arg)){
422
+ param.params[i] = NUM2ULONG(v_arg);
423
+ }
424
+ else{
425
+ StringValue(v_arg);
426
+ rb_str_modify(v_arg);
427
+ param.params[i] = (unsigned long)StringValuePtr(v_arg);
428
+ }
429
+ break;
430
+ case _T_CALLBACK:
431
+ ActiveCallback = v_arg;
432
+ param.params[i] = (LPARAM)CallbackFunction;
433
+ break;
434
+ default:
435
+ param.params[i] = NUM2ULONG(v_arg);
436
+ }
437
+ }
438
+
439
+ /* Call the function, get the return value */
440
+ return_value = ptr->function(param);
441
+
442
+ /* Return the appropriate type based on the return type specified
443
+ * in the constructor.
444
+ */
445
+ switch(ptr->return_type){
446
+ case _T_INTEGER:
447
+ v_return = INT2NUM(return_value);
448
+ break;
449
+ case _T_LONG:
450
+ v_return = LONG2NUM(return_value);
451
+ break;
452
+ case _T_VOID:
453
+ v_return = Qnil;
454
+ break;
455
+ case _T_POINTER:
456
+ if(!return_value)
457
+ v_return = Qnil;
458
+ else
459
+ v_return = rb_str_new2((TCHAR*)return_value);
460
+ break;
461
+ default:
462
+ v_return = INT2NUM(0);
463
+ }
464
+
465
+ return v_return;
466
+ }
467
+
468
+ /*
469
+ * Wraps the Windows API functions in a Ruby interface.
470
+ */
471
+ void Init_api(){
472
+ VALUE mWin32, cAPI, cCallback;
473
+
474
+ /* Modules and Classes */
475
+
476
+ /* The Win32 module serves as a namespace only */
477
+ mWin32 = rb_define_module("Win32");
478
+
479
+ /* The API class encapsulates a function pointer to Windows API function */
480
+ cAPI = rb_define_class_under(mWin32, "API", rb_cObject);
481
+
482
+ /* The API::Callback class encapsulates a Windows CALLBACK function */
483
+ cCallback = rb_define_class_under(cAPI, "Callback", rb_cObject);
484
+
485
+ /* The API::Error class is raised if the constructor fails */
486
+ cAPIError = rb_define_class_under(cAPI, "Error", rb_eRuntimeError);
487
+
488
+ /* The API::Callback::Error class is raised if the constructor fails */
489
+ cCallbackError = rb_define_class_under(cCallback, "Error", rb_eRuntimeError);
490
+
491
+ /* Miscellaneous */
492
+ rb_define_alloc_func(cAPI, api_allocate);
493
+
494
+ /* Win32::API Instance Methods */
495
+ rb_define_method(cAPI, "initialize", api_init, -1);
496
+ rb_define_method(cAPI, "call", api_call, -1);
497
+
498
+ rb_define_method(cCallback, "initialize", callback_init, -1);
499
+
500
+ /* The name of the DLL that exports the API function */
501
+ rb_define_attr(cAPI, "dll_name", 1, 0);
502
+
503
+ /* The name of the function */
504
+ rb_define_attr(cAPI, "function_name", 1, 0);
505
+
506
+ /* The prototype, returned as an array of characters */
507
+ rb_define_attr(cAPI, "prototype", 1, 0);
508
+
509
+ /* The return type, returned as a single character, P, L, I, V or B */
510
+ rb_define_attr(cAPI, "return_type", 1, 0);
511
+
512
+ /* Win32::API::Callback Instance Methods */
513
+
514
+ /* The prototype, returned as an array of characters */
515
+ rb_define_attr(cCallback, "prototype", 1, 0);
516
+
517
+ /* The return type, returned as a single character, P, L, I, V or B */
518
+ rb_define_attr(cCallback, "return_type", 1, 0);
519
+
520
+ /* Constants */
521
+
522
+ /* 1.0.0: The version of this library, returned as a String */
523
+ rb_define_const(cAPI, "VERSION", rb_str_new2(WINDOWS_API_VERSION));
524
+ }
Binary file
@@ -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.2', API::VERSION)
19
+ assert_equal('1.0.4', API::VERSION)
20
20
  end
21
21
 
22
22
  def test_call
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: win32-api
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.3
7
- date: 2007-09-28 00:00:00 -06:00
6
+ version: 1.0.4
7
+ date: 2007-10-29 00:00:00 -07:00
8
8
  summary: A superior replacement for Win32API
9
9
  require_paths:
10
10
  - lib
@@ -29,9 +29,12 @@ post_install_message:
29
29
  authors:
30
30
  - Daniel J. Berger
31
31
  files:
32
- - lib/win32/api.so
32
+ - ext/extconf.rb
33
+ - ext/win32
34
+ - ext/win32/api.c
33
35
  - test/tc_win32_api.rb
34
36
  - test/tc_win32_api_callback.rb
37
+ - lib/win32/api.so
35
38
  - README
36
39
  - CHANGES
37
40
  - MANIFEST
@@ -44,6 +47,7 @@ extra_rdoc_files:
44
47
  - README
45
48
  - CHANGES
46
49
  - MANIFEST
50
+ - ext/win32/api.c
47
51
  executables: []
48
52
 
49
53
  extensions: []