diff options
author | Pete Batard <pbatard@gmail.com> | 2010-03-15 13:54:09 +0000 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-03-15 13:54:09 +0000 |
commit | f06e130f77f08b60642ff7ca085126375a7a7ea2 (patch) | |
tree | ec9512a64db7b9d2bd86be9b2f05770c32145387 /libusb/os/poll_windows.c | |
parent | 78710622a4ccf385950965edc6973c44cb570667 (diff) | |
download | libusb-f06e130f77f08b60642ff7ca085126375a7a7ea2.tar.gz |
added partial CancelIoEx emulation for XP and earlierr207
also added warning when CancelIo tries to cancel I/O started
from another thread
Diffstat (limited to 'libusb/os/poll_windows.c')
-rw-r--r-- | libusb/os/poll_windows.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c index 0fa2dce..0d8d487 100644 --- a/libusb/os/poll_windows.c +++ b/libusb/os/poll_windows.c @@ -123,7 +123,9 @@ struct winfd poll_fd[MAX_FDS]; struct { CRITICAL_SECTION mutex; // lock for fds BYTE marker; // 1st byte of a usbi_read operation gets stored here - + // Additional variables for XP CancelIoEx partial emulation + HANDLE original_handle; + DWORD thread_id; } _poll_fd[MAX_FDS]; // globals @@ -146,11 +148,19 @@ __inline BOOL cancel_io(int index) if ((index < 0) || (index >= MAX_FDS)) { return FALSE; } + + if ( (poll_fd[index].fd < 0) || (poll_fd[index].handle == INVALID_HANDLE_VALUE) + || (poll_fd[index].handle == 0) || (poll_fd[index].overlapped == NULL) ) { + return TRUE; + } if (pCancelIoEx != NULL) { return (*pCancelIoEx)(poll_fd[index].handle, poll_fd[index].overlapped); - } else { + } + if (_poll_fd[index].thread_id == GetCurrentThreadId()) { return CancelIo(poll_fd[index].handle); } + usbi_warn(NULL, "Unable to cancel I/O that was started from another thread"); + return FALSE; } // Init @@ -169,6 +179,8 @@ void init_polling(void) for (i=0; i<MAX_FDS; i++) { poll_fd[i] = INVALID_WINFD; _poll_fd[i].marker = 0; + _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; + _poll_fd[i].thread_id = 0; InitializeCriticalSection(&_poll_fd[i].mutex); } #if defined(DYNAMIC_FDS) @@ -470,7 +482,19 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode) continue; } wfd.fd = fd; - wfd.handle = handle; + // Attempt to emulate some of the CancelIoEx behaviour on platforms + // that don't have it + if (pCancelIoEx == NULL) { + _poll_fd[i].thread_id = GetCurrentThreadId(); + _poll_fd[i].original_handle = handle; + if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), + &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + usbi_warn(NULL, "could not duplicate handle for CancelIo - using orignal one"); + wfd.handle = handle; + } + } else { + wfd.handle = handle; + } wfd.overlapped = overlapped; memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); LeaveCriticalSection(&_poll_fd[i].mutex); @@ -499,6 +523,9 @@ void _free_index(int index) _close(poll_fd[index].fd); } free_overlapped(poll_fd[index].overlapped); + CloseHandle(_poll_fd[index].original_handle); + _poll_fd[index].original_handle = INVALID_HANDLE_VALUE; + _poll_fd[index].thread_id = 0; poll_fd[index] = INVALID_WINFD; } |