Hi,
2008/10/26 Daniel Berger <djberg96 at gmail.com>:> Hi,
>
> Windows Vista
> Ruby 1.8.6-p114 - One click
>
> I tried the following script below but it segfaults. One thing I realized
is
> that we don''t explicitly handle VOID callbacks (e.g.
> FileIOCompletionRoutine) in api.c. Could that be the issue?
>
> require ''windows/file''
> require ''windows/handle''
> require ''windows/error''
> require ''windows/synchronize''
> require ''windows/thread''
>
> include Windows::File
> include Windows::Handle
> include Windows::Error
> include Windows::Synchronize
> include Windows::Thread
>
> file = "test.txt"
> File.open(file, ''w''){ |fh| fh.puts "The quick brown
fox jumped over" }
>
> overlapped = 0.chr * 20
> overlapped[8,4] = [4].pack("L")
>
> handle = CreateFile(
> file,
> FILE_READ_DATA,
> FILE_SHARE_READ,
> 0,
> OPEN_EXISTING,
> FILE_FLAG_OVERLAPPED,
> 0
> )
>
> if handle == INVALID_HANDLE_VALUE
> raise get_last_error
> end
>
> buf = 0.chr * File.size(file)
> bytes = [0].pack(''L'')
>
> func = Win32::API::Callback.new(''LLP'',
''V''){ |err, bytes, olap|
> puts "Hello"
> }
>
> #bool = ReadFile(handle, buf, 5, bytes, overlapped)
> bool = ReadFileEx(handle, buf, 5, overlapped, func)
>
> unless bool
> error = GetLastError()
> if error == ERROR_IO_PENDING
> unless GetOverlappedResult(handle, overlapped, bytes, true)
> raise get_last_error
> end
> else
> CloseHandle(handle)
> raise error
> end
> end
>
> SleepEx(1,true)
>
> CloseHandle(handle)
>
> p buf.strip
>
I looked into callback again and finally found the current
implementation is a faulty product.
Here is an ugly but reliable patch.
If you use some assemby code, it might be more compact.
--- api.c.org 2008-10-26 22:31:16.000000000 +0900
+++ api.c 2008-10-26 22:37:47.000000000 +0900
@@ -469,10 +469,13 @@
typedef struct {
DWORD params[1];
} PARAM;
+typedef struct {
+ DWORD params[16];
+} CALLPARAM;
static VALUE ActiveCallback;
-DWORD CallbackFunction(PARAM param)
+DWORD CallbackFunction(CALLPARAM param)
{
VALUE v_proto, v_return, v_proc, v_retval;
VALUE argv[16];
@@ -547,6 +550,61 @@
return 0;
}
+DWORD CALLBACK CallbackFunction0() {
+ CALLPARAM param = {0};
+ param.params[0] = 0;
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction1(DWORD p1) {
+ CALLPARAM param = {p1};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction2(DWORD p1,DWORD p2) {
+ CALLPARAM param = {p1,p2};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction3(DWORD p1,DWORD p2,DWORD p3) {
+ CALLPARAM param = {p1,p2,p3};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction4(DWORD p1,DWORD p2,DWORD p3,DWORD p4) {
+ CALLPARAM param = {p1,p2,p3,p4};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction5(DWORD p1,DWORD p2,DWORD p3,DWORD
p4,DWORD p5) {
+ CALLPARAM param = {p1,p2,p3,p4,p5};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction6(DWORD p1,DWORD p2,DWORD p3,DWORD
p4,DWORD p5,DWORD p6) {
+ CALLPARAM param = {p1,p2,p3,p4,p5,p6};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction7(DWORD p1,DWORD p2,DWORD p3,DWORD
p4,DWORD p5,DWORD p6,DWORD p7) {
+ CALLPARAM param = {p1,p2,p3,p4,p5,p6,p7};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction8(DWORD p1,DWORD p2,DWORD p3,DWORD
p4,DWORD p5,DWORD p6,DWORD p7,DWORD p8) {
+ CALLPARAM param = {p1,p2,p3,p4,p5,p6,p7,p8};
+ return CallbackFunction(param);
+}
+DWORD CALLBACK CallbackFunction9(DWORD p1,DWORD p2,DWORD p3,DWORD
p4,DWORD p5,DWORD p6,DWORD p7,DWORD p8,DWORD p9) {
+ CALLPARAM param = {p1,p2,p3,p4,p5,p6,p7,p8,p9};
+ return CallbackFunction(param);
+}
+
+void *CallbackTable[] = {
+ CallbackFunction0,
+ CallbackFunction1,
+ CallbackFunction2,
+ CallbackFunction3,
+ CallbackFunction4,
+ CallbackFunction5,
+ CallbackFunction6,
+ CallbackFunction7,
+ CallbackFunction8,
+ CallbackFunction9
+};
+
/*
* call-seq:
* Win32::API#call(arg1, arg2, ...)
@@ -619,7 +677,8 @@
break;
case _T_CALLBACK:
ActiveCallback = v_arg;
- param.params[i] = (LPARAM)CallbackFunction;
+ v_proto = rb_iv_get(ActiveCallback, "@prototype");
+ param.params[i] =
(LPARAM)CallbackTable[RSTRING(v_proto)->len];
break;
case _T_STRING:
param.params[i] = (unsigned long)RSTRING(v_arg)->ptr;
Regards,
Park Heesob