win32-api 1.3.0-x86-mswin32-60 → 1.4.0-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/ext/win32/api.c +69 -60
- data/lib/win32/api.so +0 -0
- data/test/test_win32_api.rb +1 -1
- metadata +2 -2
data/CHANGES
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
= 1.4.0 - 19-Feb-2009
|
2
|
+
* Now compatible with Ruby 1.9.x.
|
3
|
+
* In what will go down as, "It seemed like a good idea at the time", I have
|
4
|
+
removed the feature where W (wide) character functions were used first if
|
5
|
+
your $KCODE environment variable was set to "UTF8". It caused too many
|
6
|
+
headaches in practice, especially amongst Rails users. You must now always
|
7
|
+
explicitly specify 'W' in the constructor if that's what you want.
|
8
|
+
* Fixed RF bug #23944 - bad error message for MSVCRT functions that failed
|
9
|
+
to load properly.
|
10
|
+
|
1
11
|
= 1.3.0 - 1-Jan-2009
|
2
12
|
* Fixed RubyForge bug #23395, which was caused by inadvertently modifying
|
3
13
|
a variable within a loop. This caused callbacks to fail in certain
|
data/ext/win32/api.c
CHANGED
@@ -1,8 +1,23 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <windows.h>
|
3
3
|
|
4
|
+
// Ruby 1.9.x
|
5
|
+
#ifndef RSTRING_PTR
|
6
|
+
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
7
|
+
#endif
|
8
|
+
#ifndef RSTRING_LEN
|
9
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifndef RARRAY_PTR
|
13
|
+
#define RARRAY_PTR(a) (RARRAY(a)->ptr)
|
14
|
+
#endif
|
15
|
+
#ifndef RARRAY_LEN
|
16
|
+
#define RARRAY_LEN(a) (RARRAY(a)->len)
|
17
|
+
#endif
|
18
|
+
|
4
19
|
#define MAX_BUF 1024
|
5
|
-
#define WINDOWS_API_VERSION "1.
|
20
|
+
#define WINDOWS_API_VERSION "1.4.0"
|
6
21
|
|
7
22
|
#define _T_VOID 0
|
8
23
|
#define _T_LONG 1
|
@@ -117,27 +132,27 @@ static VALUE callback_init(int argc, VALUE* argv, VALUE self)
|
|
117
132
|
rb_scan_args(argc, argv, "11&", &v_proto, &v_return, &v_proc);
|
118
133
|
|
119
134
|
/* Validate prototype characters */
|
120
|
-
for(i = 0; i <
|
121
|
-
switch(
|
135
|
+
for(i = 0; i < RSTRING_LEN(v_proto); i++){
|
136
|
+
switch(RSTRING_PTR(v_proto)[i]){
|
122
137
|
case 'I': case 'L': case 'P': case 'V': case 'S':
|
123
138
|
break;
|
124
139
|
default:
|
125
140
|
rb_raise(cAPIProtoError, "Illegal prototype '%c'",
|
126
|
-
|
141
|
+
RSTRING_PTR(v_proto)[i]
|
127
142
|
);
|
128
143
|
}
|
129
144
|
}
|
130
145
|
|
131
|
-
if(NIL_P(v_return) ||
|
146
|
+
if(NIL_P(v_return) || RARRAY_LEN(v_return) == 0){
|
132
147
|
v_return = rb_str_new2("L");
|
133
148
|
}
|
134
149
|
else{
|
135
|
-
switch(*(char*)
|
150
|
+
switch(*(char*)RSTRING_PTR(v_return)){
|
136
151
|
case 'I': case 'L': case 'P': case 'V': case 'S':
|
137
152
|
break;
|
138
153
|
default:
|
139
154
|
rb_raise(cAPIProtoError, "Illegal return type '%s'",
|
140
|
-
|
155
|
+
RSTRING_PTR(v_return)
|
141
156
|
);
|
142
157
|
}
|
143
158
|
}
|
@@ -145,7 +160,7 @@ static VALUE callback_init(int argc, VALUE* argv, VALUE self)
|
|
145
160
|
rb_iv_set(self, "@function", v_proc);
|
146
161
|
rb_iv_set(self, "@prototype", v_proto);
|
147
162
|
rb_iv_set(self, "@return_type", v_return);
|
148
|
-
rb_iv_set(self, "@address", ULONG2NUM((LPARAM)CallbackTable[
|
163
|
+
rb_iv_set(self, "@address", ULONG2NUM((LPARAM)CallbackTable[RSTRING_LEN(v_proto)]));
|
149
164
|
ActiveCallback = self;
|
150
165
|
|
151
166
|
return self;
|
@@ -209,14 +224,14 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
209
224
|
v_proto = rb_str_split(v_proto, "");
|
210
225
|
|
211
226
|
// Convert a nil or empty prototype to 'V' (void) automatically
|
212
|
-
if(NIL_P(v_proto) ||
|
227
|
+
if(NIL_P(v_proto) || RARRAY_LEN(v_proto) == 0){
|
213
228
|
v_proto = rb_ary_new();
|
214
229
|
rb_ary_push(v_proto, rb_str_new2("V"));
|
215
230
|
}
|
216
231
|
|
217
232
|
// Set an arbitrary limit of 20 parameters
|
218
|
-
if(20 <
|
219
|
-
rb_raise(rb_eArgError, "too many parameters: %d\n",
|
233
|
+
if(20 < RARRAY_LEN(v_proto))
|
234
|
+
rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY_LEN(v_proto));
|
220
235
|
|
221
236
|
// Set the default dll to 'kernel32'
|
222
237
|
if(NIL_P(v_dll))
|
@@ -229,12 +244,12 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
229
244
|
SafeStringValue(v_dll);
|
230
245
|
SafeStringValue(v_proc);
|
231
246
|
|
232
|
-
hLibrary = LoadLibrary(TEXT(
|
247
|
+
hLibrary = LoadLibrary(TEXT(RSTRING_PTR(v_dll)));
|
233
248
|
|
234
249
|
// The most likely cause of failure is a bad DLL load path
|
235
250
|
if(!hLibrary){
|
236
251
|
rb_raise(cAPILoadError, "LoadLibrary() function failed for '%s': %s",
|
237
|
-
|
252
|
+
RSTRING_PTR(v_dll),
|
238
253
|
StringError(GetLastError())
|
239
254
|
);
|
240
255
|
}
|
@@ -243,43 +258,37 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
243
258
|
|
244
259
|
/* Attempt to get the function. If it fails, try again with an 'A'
|
245
260
|
* appended. If that fails, try again with a 'W' appended. If that
|
246
|
-
* still fails, raise an API::
|
261
|
+
* still fails, raise an API::LoadLibraryError.
|
247
262
|
*/
|
248
|
-
fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_proc)->ptr));
|
249
263
|
|
250
|
-
|
251
|
-
if(!strcmp(rb_get_kcode(), "UTF8")){
|
252
|
-
first = "W";
|
253
|
-
second = "A";
|
254
|
-
}
|
264
|
+
fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_proc)));
|
255
265
|
|
256
266
|
// Skip the ANSI and Wide function checks for MSVCRT functions.
|
257
267
|
if(!fProc){
|
258
|
-
if(strstr(
|
268
|
+
if(strstr(RSTRING_PTR(v_dll), "msvcr")){
|
259
269
|
rb_raise(
|
260
270
|
cAPILoadError,
|
261
271
|
"Unable to load function '%s'",
|
262
|
-
|
263
|
-
StringError(GetLastError())
|
272
|
+
RSTRING_PTR(v_proc)
|
264
273
|
);
|
265
274
|
}
|
266
275
|
else{
|
267
276
|
VALUE v_ascii = rb_str_new3(v_proc);
|
268
277
|
v_ascii = rb_str_cat(v_ascii, first, 1);
|
269
|
-
fProc = GetProcAddress(hLibrary, TEXT(
|
278
|
+
fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_ascii)));
|
270
279
|
|
271
280
|
if(!fProc){
|
272
281
|
VALUE v_unicode = rb_str_new3(v_proc);
|
273
282
|
v_unicode = rb_str_cat(v_unicode, second, 1);
|
274
|
-
fProc = GetProcAddress(hLibrary, TEXT(
|
283
|
+
fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_unicode)));
|
275
284
|
|
276
285
|
if(!fProc){
|
277
286
|
rb_raise(
|
278
287
|
cAPILoadError,
|
279
288
|
"Unable to load function '%s', '%s', or '%s'",
|
280
|
-
|
281
|
-
|
282
|
-
|
289
|
+
RSTRING_PTR(v_proc),
|
290
|
+
RSTRING_PTR(v_ascii),
|
291
|
+
RSTRING_PTR(v_unicode)
|
283
292
|
);
|
284
293
|
}
|
285
294
|
else{
|
@@ -299,9 +308,9 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
299
308
|
|
300
309
|
// Push the numeric prototypes onto our int array for later use.
|
301
310
|
|
302
|
-
for(i = 0; i <
|
303
|
-
SafeStringValue(
|
304
|
-
switch(*(char*)StringValuePtr(
|
311
|
+
for(i = 0; i < RARRAY_LEN(v_proto); i++){
|
312
|
+
SafeStringValue(RARRAY_PTR(v_proto)[i]);
|
313
|
+
switch(*(char*)StringValuePtr(RARRAY_PTR(v_proto)[i])){
|
305
314
|
case 'L':
|
306
315
|
ptr->prototype[i] = _T_LONG;
|
307
316
|
break;
|
@@ -322,7 +331,7 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
322
331
|
break;
|
323
332
|
default:
|
324
333
|
rb_raise(cAPIProtoError, "Illegal prototype '%s'",
|
325
|
-
StringValuePtr(
|
334
|
+
StringValuePtr(RARRAY_PTR(v_proto)[i])
|
326
335
|
);
|
327
336
|
}
|
328
337
|
}
|
@@ -330,13 +339,13 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
330
339
|
// Store the return type for later use.
|
331
340
|
|
332
341
|
// Automatically convert empty strings or nil to type void.
|
333
|
-
if(NIL_P(v_return) ||
|
342
|
+
if(NIL_P(v_return) || RSTRING_LEN(v_return) == 0){
|
334
343
|
v_return = rb_str_new2("V");
|
335
344
|
ptr->return_type = _T_VOID;
|
336
345
|
}
|
337
346
|
else{
|
338
347
|
SafeStringValue(v_return);
|
339
|
-
switch(*
|
348
|
+
switch(*RSTRING_PTR(v_return)){
|
340
349
|
case 'L':
|
341
350
|
ptr->return_type = _T_LONG;
|
342
351
|
break;
|
@@ -354,7 +363,7 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self)
|
|
354
363
|
break;
|
355
364
|
default:
|
356
365
|
rb_raise(cAPIProtoError, "Illegal return type '%s'",
|
357
|
-
|
366
|
+
RSTRING_PTR(v_return)
|
358
367
|
);
|
359
368
|
}
|
360
369
|
}
|
@@ -408,14 +417,14 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){
|
|
408
417
|
v_proto = rb_str_split(v_proto, "");
|
409
418
|
|
410
419
|
// Convert a nil or empty prototype to 'V' (void) automatically
|
411
|
-
if(NIL_P(v_proto) ||
|
420
|
+
if(NIL_P(v_proto) || RARRAY_LEN(v_proto) == 0){
|
412
421
|
v_proto = rb_ary_new();
|
413
422
|
rb_ary_push(v_proto, rb_str_new2("V"));
|
414
423
|
}
|
415
424
|
|
416
425
|
// Set an arbitrary limit of 20 parameters
|
417
|
-
if(20 <
|
418
|
-
rb_raise(rb_eArgError, "too many parameters: %d\n",
|
426
|
+
if(20 < RARRAY_LEN(v_proto))
|
427
|
+
rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY_LEN(v_proto));
|
419
428
|
|
420
429
|
// Set the default return type to 'L' (DWORD)
|
421
430
|
if(NIL_P(v_return))
|
@@ -425,9 +434,9 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){
|
|
425
434
|
|
426
435
|
// Push the numeric prototypes onto our int array for later use.
|
427
436
|
|
428
|
-
for(i = 0; i <
|
429
|
-
SafeStringValue(
|
430
|
-
switch(*(char*)StringValuePtr(
|
437
|
+
for(i = 0; i < RARRAY_LEN(v_proto); i++){
|
438
|
+
SafeStringValue(RARRAY_PTR(v_proto)[i]);
|
439
|
+
switch(*(char*)StringValuePtr(RARRAY_PTR(v_proto)[i])){
|
431
440
|
case 'L':
|
432
441
|
ptr->prototype[i] = _T_LONG;
|
433
442
|
break;
|
@@ -448,7 +457,7 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){
|
|
448
457
|
break;
|
449
458
|
default:
|
450
459
|
rb_raise(cAPIProtoError, "Illegal prototype '%s'",
|
451
|
-
StringValuePtr(
|
460
|
+
StringValuePtr(RARRAY_PTR(v_proto)[i])
|
452
461
|
);
|
453
462
|
}
|
454
463
|
}
|
@@ -456,13 +465,13 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){
|
|
456
465
|
// Store the return type for later use.
|
457
466
|
|
458
467
|
// Automatically convert empty strings or nil to type void.
|
459
|
-
if(NIL_P(v_return) ||
|
468
|
+
if(NIL_P(v_return) || RSTRING_LEN(v_return) == 0){
|
460
469
|
v_return = rb_str_new2("V");
|
461
470
|
ptr->return_type = _T_VOID;
|
462
471
|
}
|
463
472
|
else{
|
464
473
|
SafeStringValue(v_return);
|
465
|
-
switch(*
|
474
|
+
switch(*RSTRING_PTR(v_return)){
|
466
475
|
case 'L':
|
467
476
|
ptr->return_type = _T_LONG;
|
468
477
|
break;
|
@@ -480,7 +489,7 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){
|
|
480
489
|
break;
|
481
490
|
default:
|
482
491
|
rb_raise(cAPIProtoError, "Illegal return type '%s'",
|
483
|
-
|
492
|
+
RSTRING_PTR(v_return)
|
484
493
|
);
|
485
494
|
}
|
486
495
|
}
|
@@ -507,15 +516,15 @@ DWORD CallbackFunction(CALLPARAM param)
|
|
507
516
|
|
508
517
|
if(!NIL_P(ActiveCallback)){
|
509
518
|
v_proto = rb_iv_get(ActiveCallback, "@prototype");
|
510
|
-
a_proto =
|
519
|
+
a_proto = RSTRING_PTR(v_proto);
|
511
520
|
|
512
521
|
v_return = rb_iv_get(ActiveCallback, "@return_type");
|
513
|
-
a_return =
|
522
|
+
a_return = RSTRING_PTR(v_return);
|
514
523
|
|
515
524
|
v_proc = rb_iv_get(ActiveCallback, "@function");
|
516
|
-
argc =
|
525
|
+
argc = RSTRING_LEN(v_proto);
|
517
526
|
|
518
|
-
for(i=0; i <
|
527
|
+
for(i=0; i < RSTRING_LEN(v_proto); i++){
|
519
528
|
argv[i] = Qnil;
|
520
529
|
switch(a_proto[i]){
|
521
530
|
case 'L':
|
@@ -530,7 +539,7 @@ DWORD CallbackFunction(CALLPARAM param)
|
|
530
539
|
break;
|
531
540
|
default:
|
532
541
|
rb_raise(cAPIProtoError, "Illegal prototype '%s'",
|
533
|
-
|
542
|
+
RSTRING_PTR(a_proto[i])
|
534
543
|
);
|
535
544
|
}
|
536
545
|
}
|
@@ -553,7 +562,7 @@ DWORD CallbackFunction(CALLPARAM param)
|
|
553
562
|
return NUM2ULONG(v_retval);
|
554
563
|
break;
|
555
564
|
case 'S':
|
556
|
-
return (unsigned long)
|
565
|
+
return (unsigned long)RSTRING_PTR(v_retval);
|
557
566
|
break;
|
558
567
|
case 'P':
|
559
568
|
if(NIL_P(v_retval)){
|
@@ -684,23 +693,23 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){
|
|
684
693
|
v_proto = rb_iv_get(self, "@prototype");
|
685
694
|
|
686
695
|
// For void prototypes, allow either no args or an explicit nil
|
687
|
-
if(
|
688
|
-
char* c = StringValuePtr(
|
696
|
+
if(RARRAY_LEN(v_proto) != RARRAY_LEN(v_args)){
|
697
|
+
char* c = StringValuePtr(RARRAY_PTR(v_proto)[0]);
|
689
698
|
if(!strcmp(c, "V")){
|
690
699
|
rb_ary_push(v_args, Qnil);
|
691
700
|
}
|
692
701
|
else{
|
693
702
|
rb_raise(rb_eArgError,
|
694
703
|
"wrong number of parameters: expected %d, got %d",
|
695
|
-
|
704
|
+
RARRAY_LEN(v_proto), RARRAY_LEN(v_args)
|
696
705
|
);
|
697
706
|
}
|
698
707
|
}
|
699
708
|
|
700
|
-
len =
|
709
|
+
len = RARRAY_LEN(v_proto);
|
701
710
|
|
702
711
|
for(i = 0; i < len; i++){
|
703
|
-
v_arg =
|
712
|
+
v_arg = RARRAY_PTR(v_args)[i];
|
704
713
|
|
705
714
|
// Convert nil to NULL. Otherwise convert as appropriate.
|
706
715
|
if(NIL_P(v_arg))
|
@@ -730,10 +739,10 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){
|
|
730
739
|
case _T_CALLBACK:
|
731
740
|
ActiveCallback = v_arg;
|
732
741
|
v_proto = rb_iv_get(ActiveCallback, "@prototype");
|
733
|
-
param.params[i] = (LPARAM)CallbackTable[
|
742
|
+
param.params[i] = (LPARAM)CallbackTable[RSTRING_LEN(v_proto)];
|
734
743
|
break;
|
735
744
|
case _T_STRING:
|
736
|
-
param.params[i] = (unsigned long)
|
745
|
+
param.params[i] = (unsigned long)RSTRING_PTR(v_arg);
|
737
746
|
break;
|
738
747
|
default:
|
739
748
|
param.params[i] = NUM2ULONG(v_arg);
|
@@ -763,7 +772,7 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){
|
|
763
772
|
}
|
764
773
|
else{
|
765
774
|
VALUE v_efunc = rb_iv_get(self, "@effective_function_name");
|
766
|
-
char* efunc =
|
775
|
+
char* efunc = RSTRING_PTR(v_efunc);
|
767
776
|
if(efunc[strlen(efunc)-1] == 'W'){
|
768
777
|
v_return = rb_str_new(
|
769
778
|
(TCHAR*)return_value,
|
@@ -778,7 +787,7 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){
|
|
778
787
|
case _T_STRING:
|
779
788
|
{
|
780
789
|
VALUE v_efunc = rb_iv_get(self, "@effective_function_name");
|
781
|
-
char* efunc =
|
790
|
+
char* efunc = RSTRING_PTR(v_efunc);
|
782
791
|
|
783
792
|
if(efunc[strlen(efunc)-1] == 'W'){
|
784
793
|
v_return = rb_str_new(
|
data/lib/win32/api.so
CHANGED
Binary file
|
data/test/test_win32_api.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: x86-mswin32-60
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-02-19 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|