summaryrefslogtreecommitdiff
path: root/libusb/os
diff options
context:
space:
mode:
Diffstat (limited to 'libusb/os')
-rw-r--r--libusb/os/poll_windows.c33
-rw-r--r--libusb/os/poll_windows.h2
-rw-r--r--libusb/os/windows_usb.c17
3 files changed, 41 insertions, 11 deletions
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index 7033470..9f66d44 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)
@@ -474,7 +486,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);
@@ -510,6 +534,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;
}
diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h
index fb79153..cfdc58a 100644
--- a/libusb/os/poll_windows.h
+++ b/libusb/os/poll_windows.h
@@ -41,7 +41,7 @@
// Handle synchronous completion through the overlapped structure
#if !defined(STATUS_REPARSE) // reuse the REPARSE status code
-#define STATUS_REPARSE ((NTSTATUS)0x00000104L)
+#define STATUS_REPARSE ((LONG)0x00000104L)
#endif
#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE
#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY)
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index e74ba44..40d36dc 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -2720,6 +2720,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer)
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
wfd = usbi_create_fd(winusb_handle, _O_RDONLY);
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -2796,16 +2797,17 @@ static int winusb_submit_bulk_transfer(struct usbi_transfer *itransfer)
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
wfd = usbi_create_fd(winusb_handle, direction_in?_O_RDONLY:_O_WRONLY);
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
if (direction_in) {
usbi_dbg("reading %d bytes", transfer->length);
- ret = WinUsb_ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
+ ret = WinUsb_ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
} else {
usbi_dbg("writing %d bytes", transfer->length);
- ret = WinUsb_WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
+ ret = WinUsb_WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
}
if (!ret) {
if(GetLastError() != ERROR_IO_PENDING) {
@@ -4487,7 +4489,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer)
usbi_dbg("will use interface %d", current_interface);
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
wfd = usbi_create_fd(hid_handle, _O_RDONLY);
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
@@ -4497,7 +4499,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer)
case LIBUSB_REQUEST_TYPE_STANDARD:
switch(setup->request) {
case LIBUSB_REQUEST_GET_DESCRIPTOR:
- r = _hid_get_descriptor(priv->hid, hid_handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
+ r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
(setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
break;
case LIBUSB_REQUEST_GET_CONFIGURATION:
@@ -4532,7 +4534,7 @@ static int hid_submit_control_transfer(struct usbi_transfer *itransfer)
}
break;
case LIBUSB_REQUEST_TYPE_CLASS:
- r =_hid_class_request(priv->hid, hid_handle, setup->request_type, setup->request, setup->value,
+ r =_hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value,
setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
&size, wfd.overlapped);
break;
@@ -4591,6 +4593,7 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) {
direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
wfd = usbi_create_fd(hid_handle, direction_in?_O_RDONLY:_O_WRONLY);
+ // Always use the handle returned from usbi_create_fd (wfd.handle)
if (wfd.fd < 0) {
return LIBUSB_ERROR_NO_MEM;
}
@@ -4603,13 +4606,13 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) {
if (direction_in) {
transfer_priv->hid_buffer[0] = priv->hid->input_report_id;
usbi_dbg("reading %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]);
- ret = ReadFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
+ ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
} else {
transfer_priv->hid_buffer[0] = priv->hid->output_report_id;
memcpy(transfer_priv->hid_buffer+1, transfer->buffer, transfer->length);
usbi_dbg("writing %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]);
transfer_priv->hid_buffer[0] = 0;
- ret = WriteFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
+ ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
}
if (!ret) {
if (GetLastError() != ERROR_IO_PENDING) {