win32-api 1.0.4-x86-mswin32-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGES 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
+