[Win32utils-devel] ReadFileEx segfault

Heesob Park phasis at gmail.com
Sun Oct 26 09:49:06 EDT 2008


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


More information about the win32utils-devel mailing list