win32-api 1.0.4-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,24 @@
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
24
+ * Initial release
@@ -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
@@ -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
@@ -0,0 +1,74 @@
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
+ @gle = API.new('GetLastError', 'V', 'L')
16
+ end
17
+
18
+ def test_version
19
+ assert_equal('1.0.4', API::VERSION)
20
+ end
21
+
22
+ def test_call
23
+ assert_respond_to(@api, :call)
24
+ assert_nothing_raised{ @api.call(@buf.length, @buf) }
25
+ assert_equal(Dir.pwd.tr('/', "\\"), @buf.strip)
26
+ end
27
+
28
+ def test_call_with_void
29
+ assert_nothing_raised{ @gle.call }
30
+ assert_nothing_raised{ @gle.call(nil) }
31
+ end
32
+
33
+ def test_dll_name
34
+ assert_respond_to(@api, :dll_name)
35
+ assert_equal('kernel32', @api.dll_name)
36
+ end
37
+
38
+ def test_function_name
39
+ assert_respond_to(@api, :function_name)
40
+ assert_equal('GetCurrentDirectory', @api.function_name)
41
+ end
42
+
43
+ def test_prototype
44
+ assert_respond_to(@api, :prototype)
45
+ assert_equal(['L', 'P'], @api.prototype)
46
+ end
47
+
48
+ def test_return_type
49
+ assert_respond_to(@api, :return_type)
50
+ assert_equal('L', @api.return_type)
51
+ end
52
+
53
+ def test_constructor_high_iteration
54
+ 1000.times{
55
+ assert_nothing_raised{ API.new('GetUserName', 'P', 'P', 'advapi32') }
56
+ }
57
+ end
58
+
59
+ def test_constructor_expected_failures
60
+ assert_raise(API::Error){ API.new('GetUserName', 'PL', 'I', 'foo') }
61
+ assert_raise(API::Error){ API.new('GetUserName', 'X', 'I', 'foo') }
62
+ assert_raise(API::Error){ API.new('GetUserName', 'PL', 'X', 'foo') }
63
+ end
64
+
65
+ def test_call_expected_failures
66
+ assert_raise(TypeError){ @api.call('test', @buf) }
67
+ end
68
+
69
+ def teardown
70
+ @buf = nil
71
+ @api = nil
72
+ @gle = nil
73
+ end
74
+ 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,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4.6
3
+ specification_version: 2
4
+ name: win32-api
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.4
7
+ date: 2007-10-26 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::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.0
24
+ version:
25
+ required_rubygems_version: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: "0"
30
+ version:
31
+ platform: !ruby/object:Gem::Platform
32
+ cpu: x86
33
+ os: mswin32
34
+ version: "60"
35
+ signing_key:
36
+ cert_chain: []
37
+
38
+ post_install_message:
39
+ authors:
40
+ - Daniel J. Berger
41
+ files:
42
+ - ext/win32
43
+ - ext/win32/api.c
44
+ - lib/win32
45
+ - lib/win32/api.so
46
+ - test/tc_win32_api.rb
47
+ - test/tc_win32_api_callback.rb
48
+ - README
49
+ - CHANGES
50
+ - MANIFEST
51
+ test_files:
52
+ - test/tc_win32_api.rb
53
+ - test/tc_win32_api_callback.rb
54
+ rdoc_options: []
55
+
56
+ extra_rdoc_files:
57
+ - README
58
+ - CHANGES
59
+ - MANIFEST
60
+ - ext/win32/api.c
61
+ executables: []
62
+
63
+ extensions: []
64
+
65
+ requirements: []
66
+
67
+ dependencies: []
68
+