diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 9e15194..e529d71 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -44,7 +44,7 @@ #define errno_from_Win32LastError() errno_from_Win32Error(GetLastError()) /* maps Win32 error to errno */ -static int +int errno_from_Win32Error(int win32_error) { switch (win32_error) { diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c index 6076c89..3fc6d67 100644 --- a/contrib/win32/win32compat/termio.c +++ b/contrib/win32/win32compat/termio.c @@ -2,25 +2,58 @@ #include "w32fd.h" #include "inc/defs.h" -/* Win7 - Read Term Support - START*/ +#define TERM_IO_BUF_SIZE 2048 +int errno_from_Win32Error(int win32_error); -int -fileio_initiateReadTerm_Win7(struct w32_io* pio) { +struct io_status { + char* buf[TERM_IO_BUF_SIZE]; + DWORD transferred; + DWORD error; +}; - if (pio->read_details.pending || w32_io_is_io_available(pio, TRUE)) { - debug("Win7 term read - ERROR - called in wrong state"); - errno = EINVAL; +static struct io_status read_status, write_status; + +static VOID CALLBACK ReadAPCProc( + _In_ ULONG_PTR dwParam + ) { + struct w32_io* pio = (struct w32_io*)dwParam; + pio->read_details.error = read_status.error; + pio->read_details.remaining = read_status.transferred; + pio->read_details.completed = 0; + pio->read_details.pending = FALSE; +} + +static DWORD WINAPI ReadThread( + _In_ LPVOID lpParameter + ) { + struct w32_io* pio = (struct w32_io*)lpParameter; + memset(&read_status, 0, sizeof(read_status)); + if (!ReadFile(WINHANDLE(pio), read_status.buf, TERM_IO_BUF_SIZE, &read_status.transferred, NULL)) { + read_status.error = GetLastError(); + } + + if (0 == QueueUserAPC(ReadAPCProc, main_thread, pio)) + DebugBreak(); +} + +static int +termio_initiate_read(struct w32_io* pio) { + HANDLE read_thread = CreateThread(NULL, 0, ReadThread, pio, 0, NULL); + if (read_thread == NULL) { + errno = errno_from_Win32Error(GetLastError()); return -1; } return 0; } -/* Win7 - Read Term Support - END*/ - int termio_on_select(struct w32_io* pio, BOOL rd) { - return fileio_on_select(pio, rd); + if (!rd) + return 0; + + if ((!fileio_is_io_available(pio, rd)) && (!pio->read_details.pending)) + return termio_initiate_read(pio); } int diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 8d42ae1..350908d 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -48,6 +48,9 @@ static struct w32fd_table fd_table; /* static table entries representing std in, out and error*/ static struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr; +/* main thread handle*/ +HANDLE main_thread; + void fd_table_set(struct w32_io* pio, int index); /* initializes mapping table*/ @@ -120,6 +123,7 @@ w32posix_initialize() { if ((fd_table_initialize() != 0) || (socketio_initialize() != 0)) DebugBreak(); + main_thread = GetCurrentThread(); signalio_initialize(); } diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h index b15861e..b9e4a3a 100644 --- a/contrib/win32/win32compat/w32fd.h +++ b/contrib/win32/win32compat/w32fd.h @@ -77,6 +77,7 @@ struct w32_io { #define WINHANDLE(pio) (((pio)->type == STD_IO_FD)? GetStdHandle((pio)->std_handle):(pio)->handle) #define FILETYPE(pio) (GetFileType(WINHANDLE(pio))) +extern HANDLE main_thread; BOOL w32_io_is_blocking(struct w32_io*); BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd);