summaryrefslogtreecommitdiff
path: root/libusb/os/poll_windows.c
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-03-15 13:54:09 +0000
committerPete Batard <pbatard@gmail.com>2010-03-15 13:54:09 +0000
commitf06e130f77f08b60642ff7ca085126375a7a7ea2 (patch)
treeec9512a64db7b9d2bd86be9b2f05770c32145387 /libusb/os/poll_windows.c
parent78710622a4ccf385950965edc6973c44cb570667 (diff)
downloadlibusb-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.c33
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;
}