win32-api 1.0.0-mswin32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,2 @@
1
+ = 1.0.0 - 14-Sep-2007
2
+ * Initial release
data/MANIFEST ADDED
@@ -0,0 +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
data/README ADDED
@@ -0,0 +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
72
+ Park Heesob
data/ext/win32/api.c ADDED
@@ -0,0 +1,496 @@
1
+ #include <ruby.h>
2
+ #include <windows.h>
3
+
4
+ #define MAX_BUF 1024
5
+ #define WINDOWS_API_VERSION "1.0.0"
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
+
73
+ rb_scan_args(argc, argv, "11", &v_proto, &v_return);
74
+
75
+ if(NIL_P(v_return) || RARRAY(v_return)->len == 0)
76
+ v_return = rb_str_new2("L");
77
+
78
+ if(rb_block_given_p())
79
+ v_proc = rb_block_proc();
80
+ else
81
+ v_proc = Qnil;
82
+
83
+ rb_iv_set(self, "@function", v_proc);
84
+ rb_iv_set(self, "@prototype", v_proto);
85
+ rb_iv_set(self, "@return_type", v_return);
86
+
87
+ return self;
88
+ }
89
+
90
+
91
+ typedef struct {
92
+ HANDLE library;
93
+ FARPROC function;
94
+ int return_type;
95
+ int prototype[];
96
+ } Win32API;
97
+
98
+ static void api_free(Win32API* ptr){
99
+ if(ptr->library)
100
+ FreeLibrary(ptr->library);
101
+
102
+ free(ptr);
103
+ }
104
+
105
+ static VALUE api_allocate(VALUE klass){
106
+ Win32API* ptr = malloc(sizeof(Win32API));
107
+ return Data_Wrap_Struct(klass, 0, api_free, ptr);
108
+ }
109
+
110
+ /*
111
+ * call-seq:
112
+ * Win32::API.new(function, prototype='V', return='L', dll='kernel32')
113
+ *
114
+ * Creates and returns a new Win32::API object. The +function+ is the name
115
+ * of the Windows function.
116
+ *
117
+ * The +prototype+ is the function prototype for +function+. This can be a
118
+ * string or an array of characters. The possible valid characters are 'I'
119
+ * (integer), 'L' (long), 'V' (void), 'P' (pointer), or 'K' (callback).
120
+ * The default is void ('V').
121
+ *
122
+ * The +return+ argument is the return type for the function. The valid
123
+ * characters are the same as for the +prototype+. The default is 'L' (long).
124
+ *
125
+ * The +dll+ is the name of the DLL file that the function is exported from.
126
+ * The default is 'kernel32'.
127
+ *
128
+ * If the function cannot be found then an API::Error is raised (a subclass
129
+ * of RuntimeError).
130
+ */
131
+ static VALUE api_init(int argc, VALUE* argv, VALUE self)
132
+ {
133
+ HMODULE hLibrary;
134
+ FARPROC fProc;
135
+ Win32API* ptr;
136
+ int i;
137
+ VALUE v_proc, v_proto, v_return, v_dll, v_bool, v_name;
138
+
139
+ rb_scan_args(argc, argv, "13", &v_proc, &v_proto, &v_return, &v_dll);
140
+
141
+ Data_Get_Struct(self, Win32API, ptr);
142
+
143
+ /* Convert a string prototype to an array of characters */
144
+ if(rb_respond_to(v_proto, rb_intern("split")))
145
+ v_proto = rb_str_split(v_proto, "");
146
+
147
+ /* Set an arbitrary limit of 16 parameters */
148
+ if(16 < RARRAY(v_proto)->len)
149
+ rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
150
+
151
+ /* Convert a nil or empty prototype to 'V' (void) automatically */
152
+ if(NIL_P(v_proto) || RARRAY(v_proto)->len == 0){
153
+ v_proto = rb_ary_new();
154
+ rb_ary_push(v_proto, rb_str_new2("V"));
155
+ }
156
+
157
+ /* Set the default dll to 'kernel32' */
158
+ if(NIL_P(v_dll))
159
+ v_dll = rb_str_new2("kernel32");
160
+
161
+ /* Set the default return type to 'L' (DWORD) */
162
+ if(NIL_P(v_return))
163
+ v_return = rb_str_new2("L");
164
+
165
+ SafeStringValue(v_dll);
166
+ SafeStringValue(v_proc);
167
+
168
+ hLibrary = LoadLibrary(TEXT(RSTRING(v_dll)->ptr));
169
+
170
+ /* The most likely cause of failure is a bad DLL load path */
171
+ if(!hLibrary){
172
+ rb_raise(cAPIError, "LoadLibrary() function failed for '%s': %s",
173
+ RSTRING(v_dll)->ptr,
174
+ StringError(GetLastError())
175
+ );
176
+ }
177
+
178
+ ptr->library = hLibrary;
179
+
180
+ /* Attempt to get the function. If it fails, try again with an 'A'
181
+ * appended. If that fails, try again with a 'W' appended. If that
182
+ * still fails, raise an API::Error.
183
+ */
184
+ fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_proc)->ptr));
185
+
186
+ if(!fProc){
187
+ VALUE v_ascii = rb_str_new3(v_proc);
188
+ v_ascii = rb_str_cat(v_ascii, "A", 1);
189
+ fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_ascii)->ptr));
190
+
191
+ if(!fProc){
192
+ VALUE v_unicode = rb_str_new3(v_proc);
193
+ v_unicode = rb_str_cat(v_unicode, "W", 1);
194
+ fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_unicode)->ptr));
195
+
196
+ if(!fProc){
197
+ rb_raise(
198
+ cAPIError,
199
+ "GetProcAddress() failed for '%s', '%s' and '%s': %s",
200
+ RSTRING(v_proc)->ptr,
201
+ RSTRING(v_ascii)->ptr,
202
+ RSTRING(v_unicode)->ptr,
203
+ StringError(GetLastError())
204
+ );
205
+ }
206
+ }
207
+ }
208
+
209
+ ptr->function = fProc;
210
+
211
+ /* Push the numeric prototypes onto our int array for later use. */
212
+ for(i = 0; i < RARRAY(v_proto)->len; i++){
213
+ SafeStringValue(RARRAY(v_proto)->ptr[i]);
214
+ switch(*(char*)StringValuePtr(RARRAY(v_proto)->ptr[i])){
215
+ case 'L':
216
+ ptr->prototype[i] = _T_LONG;
217
+ break;
218
+ case 'P':
219
+ ptr->prototype[i] = _T_POINTER;
220
+ break;
221
+ case 'I': case 'B':
222
+ ptr->prototype[i] = _T_INTEGER;
223
+ break;
224
+ case 'V':
225
+ ptr->prototype[i] = _T_VOID;
226
+ break;
227
+ case 'K':
228
+ ptr->prototype[i] = _T_CALLBACK;
229
+ break;
230
+ default:
231
+ rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
232
+ }
233
+ }
234
+
235
+ /* Store the return type for later use. Automatically convert empty
236
+ * strings or nil to type void.
237
+ */
238
+ if(NIL_P(v_return) || RSTRING(v_return)->len == 0){
239
+ v_return = rb_str_new2("V");
240
+ ptr->return_type = _T_VOID;
241
+ }
242
+ else{
243
+ SafeStringValue(v_return);
244
+ switch(*RSTRING(v_return)->ptr){
245
+ case 'L':
246
+ ptr->return_type = _T_LONG;
247
+ break;
248
+ case 'P':
249
+ ptr->return_type = _T_POINTER;
250
+ break;
251
+ case 'I': case 'B':
252
+ ptr->return_type = _T_INTEGER;
253
+ break;
254
+ case 'V':
255
+ ptr->return_type = _T_VOID;
256
+ break;
257
+ default:
258
+ rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
259
+ }
260
+ }
261
+
262
+ rb_iv_set(self, "@dll_name", v_dll);
263
+ rb_iv_set(self, "@function_name", v_proc);
264
+ rb_iv_set(self, "@prototype", v_proto);
265
+ rb_iv_set(self, "@return_type", v_return);
266
+
267
+ return self;
268
+ }
269
+
270
+ typedef struct {
271
+ DWORD params[1];
272
+ } PARAM;
273
+
274
+ static VALUE ActiveCallback;
275
+
276
+ DWORD CallbackFunction(PARAM param)
277
+ {
278
+ VALUE v_proto, v_return, v_proc, v_retval;
279
+ VALUE argv[16];
280
+ int i, argc;
281
+ char *a_proto;
282
+ char *a_return;
283
+
284
+ if(!NIL_P(ActiveCallback)){
285
+ v_proto = rb_iv_get(ActiveCallback, "@prototype");
286
+ a_proto = RSTRING(v_proto)->ptr;
287
+
288
+ v_return = rb_iv_get(ActiveCallback, "@return_type");
289
+ a_return = RSTRING(v_return)->ptr;
290
+
291
+ v_proc = rb_iv_get(ActiveCallback, "@function");
292
+ argc = RSTRING(v_proto)->len;
293
+
294
+ for(i=0; i < RSTRING(v_proto)->len; i++){
295
+ argv[i] = Qnil;
296
+ switch(a_proto[i]){
297
+ case 'L':
298
+ argv[i] = ULONG2NUM(param.params[i]);
299
+ break;
300
+ case 'P':
301
+ if(param.params[i])
302
+ argv[i] = rb_str_new2((char *)param.params[i]);
303
+ break;
304
+ case 'I':
305
+ argv[i] = INT2NUM(param.params[i]);
306
+ break;
307
+ default:
308
+ rb_raise(cCallbackError, "Illegal prototype '%s'", a_proto[i]);
309
+ }
310
+ }
311
+
312
+ v_retval = rb_funcall2(v_proc, rb_intern("call"), argc, argv);
313
+
314
+ /* Handle true and false explicitly, as some CALLBACK functions
315
+ * require TRUE or FALSE to break out of loops, etc.
316
+ */
317
+ if(v_retval == Qtrue)
318
+ return TRUE;
319
+ else if(v_retval == Qfalse)
320
+ return FALSE;
321
+
322
+ switch (*a_return) {
323
+ case 'I':
324
+ return NUM2INT(v_retval);
325
+ break;
326
+ case 'L':
327
+ return NUM2ULONG(v_retval);
328
+ break;
329
+ case 'P':
330
+ if(NIL_P(v_retval)){
331
+ return 0;
332
+ }
333
+ else if (FIXNUM_P(v_retval)){
334
+ return NUM2ULONG(v_retval);
335
+ }
336
+ else{
337
+ StringValue(v_retval);
338
+ rb_str_modify(v_retval);
339
+ return (unsigned long)StringValuePtr(v_retval);
340
+ }
341
+ break;
342
+ }
343
+ }
344
+
345
+ return 0;
346
+ }
347
+
348
+ /*
349
+ * call-seq:
350
+ * Win32::API#call(arg1, arg2, ...)
351
+ *
352
+ * Calls the function pointer with the given arguments (if any). Note that,
353
+ * while this method will catch some prototype mismatches (raising a TypeError
354
+ * in the process), it is not fulproof. It is ultimately your job to make
355
+ * sure the arguments match the +prototype+ specified in the constructor.
356
+ *
357
+ * For convenience, nil is converted to NULL, true is converted to TRUE (1)
358
+ * and false is converted to FALSE (0).
359
+ */
360
+ static VALUE api_call(int argc, VALUE* argv, VALUE self){
361
+ VALUE v_proto, v_args, v_arg, v_return;
362
+ Win32API* ptr;
363
+ unsigned long return_value;
364
+ int i = 0;
365
+
366
+ struct{
367
+ unsigned long params[16];
368
+ } param;
369
+
370
+ Data_Get_Struct(self, Win32API, ptr);
371
+
372
+ rb_scan_args(argc, argv, "0*", &v_args);
373
+
374
+ v_proto = rb_iv_get(self, "@prototype");
375
+
376
+ if(RARRAY(v_proto)->len != RARRAY(v_args)->len)
377
+ rb_raise(rb_eArgError, "wrong number of parameters: expected %d, got %d",
378
+ RARRAY(v_proto)->len, RARRAY(v_args)->len
379
+ );
380
+
381
+ for(i = 0; i < RARRAY(v_proto)->len; i++){
382
+ v_arg = RARRAY(v_args)->ptr[i];
383
+
384
+ /* Convert nil to NULL. Otherwise convert as appropriate. */
385
+ if(NIL_P(v_arg))
386
+ param.params[i] = (unsigned long)NULL;
387
+ else if(v_arg == Qtrue)
388
+ param.params[i] = TRUE;
389
+ else if(v_arg == Qfalse)
390
+ param.params[i] = FALSE;
391
+ else
392
+ switch(ptr->prototype[i]){
393
+ case _T_LONG:
394
+ param.params[i] = NUM2ULONG(v_arg);
395
+ break;
396
+ case _T_INTEGER:
397
+ param.params[i] = NUM2INT(v_arg);
398
+ break;
399
+ case _T_POINTER:
400
+ if(FIXNUM_P(v_arg))
401
+ param.params[i] = NUM2ULONG(v_arg);
402
+ else
403
+ param.params[i] = (unsigned long)StringValuePtr(v_arg);
404
+ break;
405
+ case _T_CALLBACK:
406
+ ActiveCallback = v_arg;
407
+ param.params[i] = (LPARAM)CallbackFunction;
408
+ break;
409
+ default:
410
+ param.params[i] = NUM2ULONG(v_arg);
411
+ }
412
+ }
413
+
414
+ /* Call the function, get the return value */
415
+ return_value = ptr->function(param);
416
+
417
+ /* Return the appropriate type based on the return type specified
418
+ * in the constructor.
419
+ */
420
+ switch(ptr->return_type){
421
+ case _T_INTEGER:
422
+ v_return = INT2NUM(return_value);
423
+ break;
424
+ case _T_LONG:
425
+ v_return = LONG2NUM(return_value);
426
+ break;
427
+ case _T_VOID:
428
+ v_return = Qnil;
429
+ break;
430
+ case _T_POINTER:
431
+ v_return = rb_str_new2((TCHAR*)return_value);
432
+ break;
433
+ default:
434
+ v_return = INT2NUM(0);
435
+ }
436
+
437
+ return v_return;
438
+ }
439
+
440
+ /*
441
+ * Wraps the Windows API functions in a Ruby interface.
442
+ */
443
+ void Init_api(){
444
+ VALUE mWin32, cAPI, cCallback;
445
+
446
+ /* Modules and Classes */
447
+
448
+ /* The Win32 module serves as a namespace only */
449
+ mWin32 = rb_define_module("Win32");
450
+
451
+ /* The API class encapsulates a function pointer to Windows API function */
452
+ cAPI = rb_define_class_under(mWin32, "API", rb_cObject);
453
+
454
+ /* The API::Callback class encapsulates a Windows CALLBACK function */
455
+ cCallback = rb_define_class_under(cAPI, "Callback", rb_cObject);
456
+
457
+ /* The API::Error class is raised if the constructor fails */
458
+ cAPIError = rb_define_class_under(cAPI, "Error", rb_eRuntimeError);
459
+
460
+ /* The API::Callback::Error class is raised if the constructor fails */
461
+ cCallbackError = rb_define_class_under(cCallback, "Error", rb_eRuntimeError);
462
+
463
+ /* Miscellaneous */
464
+ rb_define_alloc_func(cAPI, api_allocate);
465
+
466
+ /* Win32::API Instance Methods */
467
+ rb_define_method(cAPI, "initialize", api_init, -1);
468
+ rb_define_method(cAPI, "call", api_call, -1);
469
+
470
+ rb_define_method(cCallback, "initialize", callback_init, -1);
471
+
472
+ /* The name of the DLL that exports the API function */
473
+ rb_define_attr(cAPI, "dll_name", 1, 0);
474
+
475
+ /* The name of the function */
476
+ rb_define_attr(cAPI, "function_name", 1, 0);
477
+
478
+ /* The prototype, returned as an array of characters */
479
+ rb_define_attr(cAPI, "prototype", 1, 0);
480
+
481
+ /* The return type, returned as a single character, P, L, I, V or B */
482
+ rb_define_attr(cAPI, "return_type", 1, 0);
483
+
484
+ /* Win32::API::Callback Instance Methods */
485
+
486
+ /* The prototype, returned as an array of characters */
487
+ rb_define_attr(cCallback, "prototype", 1, 0);
488
+
489
+ /* The return type, returned as a single character, P, L, I, V or B */
490
+ rb_define_attr(cCallback, "return_type", 1, 0);
491
+
492
+ /* Constants */
493
+
494
+ /* 1.0.0: The version of this library, returned as a String */
495
+ rb_define_const(cAPI, "VERSION", rb_str_new2(WINDOWS_API_VERSION));
496
+ }
data/lib/win32/api.so ADDED
Binary file
@@ -0,0 +1,61 @@
1
+ ############################################################################
2
+ # tc_win32_api.rb
3
+ #
4
+ # Test case for the Win32::API class. You should run this as Rake task,
5
+ # i.e. 'rake test', instead of running it directly.
6
+ ############################################################################
7
+ require 'win32/api'
8
+ require 'test/unit'
9
+ include Win32
10
+
11
+ class TC_Win32_API < Test::Unit::TestCase
12
+ def setup
13
+ @buf = 0.chr * 260
14
+ @api = API.new('GetCurrentDirectory', 'LP')
15
+ end
16
+
17
+ def test_version
18
+ assert_equal('1.0.0', API::VERSION)
19
+ end
20
+
21
+ def test_call
22
+ assert_respond_to(@api, :call)
23
+ assert_nothing_raised{ @api.call(@buf.length, @buf) }
24
+ assert_equal(Dir.pwd.tr('/', "\\"), @buf.strip)
25
+ end
26
+
27
+ def test_dll_name
28
+ assert_respond_to(@api, :dll_name)
29
+ assert_equal('kernel32', @api.dll_name)
30
+ end
31
+
32
+ def test_function_name
33
+ assert_respond_to(@api, :function_name)
34
+ assert_equal('GetCurrentDirectory', @api.function_name)
35
+ end
36
+
37
+ def test_prototype
38
+ assert_respond_to(@api, :prototype)
39
+ assert_equal(['L', 'P'], @api.prototype)
40
+ end
41
+
42
+ def test_return_type
43
+ assert_respond_to(@api, :return_type)
44
+ assert_equal('L', @api.return_type)
45
+ end
46
+
47
+ def test_constructor_expected_failures
48
+ assert_raise(API::Error){ API.new('GetUserName', 'PL', 'I', 'foo') }
49
+ assert_raise(API::Error){ API.new('GetUserName', 'X', 'I', 'foo') }
50
+ assert_raise(API::Error){ API.new('GetUserName', 'PL', 'X', 'foo') }
51
+ end
52
+
53
+ def test_call_expected_failures
54
+ assert_raise(TypeError){ @api.call('test', @buf) }
55
+ end
56
+
57
+ def teardown
58
+ @buf = nil
59
+ @api = nil
60
+ end
61
+ end
@@ -0,0 +1,58 @@
1
+ ############################################################################
2
+ # tc_win32_api_callback.rb
3
+ #
4
+ # Test case for the Win32::API::Callback class. You should run this as Rake
5
+ # task, i.e. 'rake test', instead of running it directly.
6
+ ############################################################################
7
+ require 'win32/api'
8
+ require 'test/unit'
9
+ include Win32
10
+
11
+ class TC_Win32_API_Callback < Test::Unit::TestCase
12
+ def setup
13
+ @buffer = 0.chr * 260
14
+ @api_ew = API.new('EnumWindows', 'KP', 'L', 'user32')
15
+ @api_gwt = API.new('GetWindowText', 'LPI', 'I', 'user32')
16
+ @callback = nil
17
+ end
18
+
19
+ def test_constructor
20
+ assert_respond_to(API::Callback, :new)
21
+ assert_nothing_raised{ API::Callback.new('LP', 'I') }
22
+ assert_nothing_raised{ API::Callback.new('LP', 'I'){} }
23
+ end
24
+
25
+ def test_prototype
26
+ assert_nothing_raised{ @callback = API::Callback.new('LP', 'I') }
27
+ assert_respond_to(@callback, :prototype)
28
+ assert_equal('LP', @callback.prototype)
29
+ end
30
+
31
+ def test_return_value
32
+ assert_nothing_raised{ @callback = API::Callback.new('LP', 'I') }
33
+ assert_respond_to(@callback, :return_type)
34
+ assert_equal('I', @callback.return_type)
35
+ end
36
+
37
+ def test_callback
38
+ assert_nothing_raised{
39
+ @callback = API::Callback.new('LP', 'I'){ |handle, param|
40
+ buf = "\0" * 200
41
+ @api_gwt.call(handle, buf, 200);
42
+ buf.index(param).nil? ? true : false
43
+ }
44
+ }
45
+ assert_nothing_raised{ @api_ew.call(@callback, 'UEDIT32') }
46
+ end
47
+
48
+ def test_constructor_expected_errors
49
+ assert_raise(API::Callback::Error){ API::Callback.new('X') }
50
+ end
51
+
52
+ def teardown
53
+ @buffer = nil
54
+ @api_ew = nil
55
+ @api_gwt = nil
56
+ @callback = nil
57
+ end
58
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: win32-api
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2007-09-14 00:00:00 -06:00
8
+ summary: A superior replacement for Win32API
9
+ require_paths:
10
+ - lib
11
+ email: djberg96@gmail.com
12
+ homepage: http://www.rubyforge.org/projects/win32utils
13
+ rubyforge_project: win32utils
14
+ description: A superior replacement for Win32API
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.0
24
+ version:
25
+ platform: mswin32
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Daniel J. Berger
31
+ files:
32
+ - lib/win32/api.so
33
+ - test/tc_win32_api.rb
34
+ - test/tc_win32_api_callback.rb
35
+ - README
36
+ - CHANGES
37
+ - MANIFEST
38
+ - ext/win32/api.c
39
+ test_files:
40
+ - test/tc_win32_api.rb
41
+ - test/tc_win32_api_callback.rb
42
+ rdoc_options: []
43
+
44
+ extra_rdoc_files:
45
+ - README
46
+ - CHANGES
47
+ - MANIFEST
48
+ - ext/win32/api.c
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ requirements: []
54
+
55
+ dependencies: []
56
+