• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * windows backend for libusb 1.0
3  * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
4  * With contributions from Michael Plante, Orin Eman et al.
5  * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
6  * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
7  * Hash table functions adapted from glibc, by Ulrich Drepper et al.
8  * Major code testing contribution by Xiaofan Chen
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 #include <config.h>
26 
27 #include <stdio.h>
28 
29 #include "libusbi.h"
30 #include "windows_common.h"
31 
32 #define EPOCH_TIME	UINT64_C(116444736000000000)	// 1970.01.01 00:00:000 in MS Filetime
33 
34 #define STATUS_SUCCESS	((ULONG_PTR)0UL)
35 
36 // Public
37 enum windows_version windows_version = WINDOWS_UNDEFINED;
38 
39 // Global variables for init/exit
40 static unsigned int init_count;
41 static bool usbdk_available;
42 
43 /*
44 * Converts a windows error to human readable string
45 * uses retval as errorcode, or, if 0, use GetLastError()
46 */
47 #if defined(ENABLE_LOGGING)
windows_error_str(DWORD error_code)48 const char *windows_error_str(DWORD error_code)
49 {
50 	static char err_string[256];
51 
52 	DWORD size;
53 	int len;
54 
55 	if (error_code == 0)
56 		error_code = GetLastError();
57 
58 	len = sprintf(err_string, "[%lu] ", ULONG_CAST(error_code));
59 
60 	// Translate codes returned by SetupAPI. The ones we are dealing with are either
61 	// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
62 	// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
63 	switch (error_code & 0xE0000000) {
64 	case 0:
65 		error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
66 		break;
67 	case 0xE0000000:
68 		error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
69 		break;
70 	default:
71 		break;
72 	}
73 
74 	size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
75 			NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
76 			&err_string[len], sizeof(err_string) - len, NULL);
77 	if (size == 0) {
78 		DWORD format_error = GetLastError();
79 		if (format_error)
80 			snprintf(err_string, sizeof(err_string),
81 				"Windows error code %lu (FormatMessage error code %lu)",
82 				ULONG_CAST(error_code), ULONG_CAST(format_error));
83 		else
84 			snprintf(err_string, sizeof(err_string), "Unknown error code %lu",
85 				ULONG_CAST(error_code));
86 	} else {
87 		// Remove CRLF from end of message, if present
88 		size_t pos = len + size - 2;
89 		if (err_string[pos] == '\r')
90 			err_string[pos] = '\0';
91 	}
92 
93 	return err_string;
94 }
95 #endif
96 
97 /*
98  * Dynamically loads a DLL from the Windows system directory.  Unlike the
99  * LoadLibraryA() function, this function will not search through any
100  * directories to try and find the library.
101  */
load_system_library(struct libusb_context * ctx,const char * name)102 HMODULE load_system_library(struct libusb_context *ctx, const char *name)
103 {
104 	char library_path[MAX_PATH];
105 	char *filename_start;
106 	UINT length;
107 
108 	length = GetSystemDirectoryA(library_path, sizeof(library_path));
109 	if ((length == 0) || (length >= (UINT)sizeof(library_path))) {
110 		usbi_err(ctx, "program assertion failed - could not get system directory");
111 		return NULL;
112 	}
113 
114 	filename_start = library_path + length;
115 	// Append '\' + name + ".dll" + NUL
116 	length += 1 + (UINT)strlen(name) + 4 + 1;
117 	if (length >= (UINT)sizeof(library_path)) {
118 		usbi_err(ctx, "program assertion failed - library path buffer overflow");
119 		return NULL;
120 	}
121 
122 	sprintf(filename_start, "\\%s.dll", name);
123 	return LoadLibraryA(library_path);
124 }
125 
126 /* Hash table functions - modified From glibc 2.3.2:
127    [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
128    [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
129 
130 #define HTAB_SIZE 1021UL	// *MUST* be a prime number!!
131 
132 typedef struct htab_entry {
133 	unsigned long used;
134 	char *str;
135 } htab_entry;
136 
137 static htab_entry *htab_table;
138 static usbi_mutex_t htab_mutex;
139 static unsigned long htab_filled;
140 
141 /* Before using the hash table we must allocate memory for it.
142    We allocate one element more as the found prime number says.
143    This is done for more effective indexing as explained in the
144    comment for the hash function.  */
htab_create(struct libusb_context * ctx)145 static bool htab_create(struct libusb_context *ctx)
146 {
147 	if (htab_table != NULL) {
148 		usbi_err(ctx, "program assertion failed - hash table already allocated");
149 		return true;
150 	}
151 
152 	// Create a mutex
153 	usbi_mutex_init(&htab_mutex);
154 
155 	usbi_dbg(ctx, "using %lu entries hash table", HTAB_SIZE);
156 	htab_filled = 0;
157 
158 	// allocate memory and zero out.
159 	htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry));
160 	if (htab_table == NULL) {
161 		usbi_err(ctx, "could not allocate space for hash table");
162 		return false;
163 	}
164 
165 	return true;
166 }
167 
168 /* After using the hash table it has to be destroyed.  */
htab_destroy(void)169 static void htab_destroy(void)
170 {
171 	unsigned long i;
172 
173 	if (htab_table == NULL)
174 		return;
175 
176 	for (i = 0; i < HTAB_SIZE; i++)
177 		free(htab_table[i].str);
178 
179 	safe_free(htab_table);
180 
181 	usbi_mutex_destroy(&htab_mutex);
182 }
183 
184 /* This is the search function. It uses double hashing with open addressing.
185    We use a trick to speed up the lookup. The table is created with one
186    more element available. This enables us to use the index zero special.
187    This index will never be used because we store the first hash index in
188    the field used where zero means not used. Every other value means used.
189    The used field can be used as a first fast comparison for equality of
190    the stored and the parameter value. This helps to prevent unnecessary
191    expensive calls of strcmp.  */
htab_hash(const char * str)192 unsigned long htab_hash(const char *str)
193 {
194 	unsigned long hval, hval2;
195 	unsigned long idx;
196 	unsigned long r = 5381UL;
197 	int c;
198 	const char *sz = str;
199 
200 	if (str == NULL)
201 		return 0;
202 
203 	// Compute main hash value (algorithm suggested by Nokia)
204 	while ((c = *sz++) != 0)
205 		r = ((r << 5) + r) + c;
206 	if (r == 0)
207 		++r;
208 
209 	// compute table hash: simply take the modulus
210 	hval = r % HTAB_SIZE;
211 	if (hval == 0)
212 		++hval;
213 
214 	// Try the first index
215 	idx = hval;
216 
217 	// Mutually exclusive access (R/W lock would be better)
218 	usbi_mutex_lock(&htab_mutex);
219 
220 	if (htab_table[idx].used) {
221 		if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
222 			goto out_unlock; // existing hash
223 
224 		usbi_dbg(NULL, "hash collision ('%s' vs '%s')", str, htab_table[idx].str);
225 
226 		// Second hash function, as suggested in [Knuth]
227 		hval2 = 1UL + hval % (HTAB_SIZE - 2);
228 
229 		do {
230 			// Because size is prime this guarantees to step through all available indexes
231 			if (idx <= hval2)
232 				idx = HTAB_SIZE + idx - hval2;
233 			else
234 				idx -= hval2;
235 
236 			// If we visited all entries leave the loop unsuccessfully
237 			if (idx == hval)
238 				break;
239 
240 			// If entry is found use it.
241 			if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
242 				goto out_unlock;
243 		} while (htab_table[idx].used);
244 	}
245 
246 	// Not found => New entry
247 
248 	// If the table is full return an error
249 	if (htab_filled >= HTAB_SIZE) {
250 		usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
251 		idx = 0UL;
252 		goto out_unlock;
253 	}
254 
255 	htab_table[idx].str = _strdup(str);
256 	if (htab_table[idx].str == NULL) {
257 		usbi_err(NULL, "could not duplicate string for hash table");
258 		idx = 0UL;
259 		goto out_unlock;
260 	}
261 
262 	htab_table[idx].used = hval;
263 	++htab_filled;
264 
265 out_unlock:
266 	usbi_mutex_unlock(&htab_mutex);
267 
268 	return idx;
269 }
270 
usbd_status_to_libusb_transfer_status(USBD_STATUS status)271 enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
272 {
273 	if (USBD_SUCCESS(status))
274 		return LIBUSB_TRANSFER_COMPLETED;
275 
276 	switch (status) {
277 	case USBD_STATUS_TIMEOUT:
278 		return LIBUSB_TRANSFER_TIMED_OUT;
279 	case USBD_STATUS_CANCELED:
280 		return LIBUSB_TRANSFER_CANCELLED;
281 	case USBD_STATUS_ENDPOINT_HALTED:
282 		return LIBUSB_TRANSFER_STALL;
283 	case USBD_STATUS_DEVICE_GONE:
284 		return LIBUSB_TRANSFER_NO_DEVICE;
285 	default:
286 		usbi_dbg(NULL, "USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
287 		return LIBUSB_TRANSFER_ERROR;
288 	}
289 }
290 
291 /*
292  * Make a transfer complete synchronously
293  */
windows_force_sync_completion(struct usbi_transfer * itransfer,ULONG size)294 void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size)
295 {
296 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
297 	struct windows_context_priv *priv = usbi_get_context_priv(TRANSFER_CTX(transfer));
298 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
299 	OVERLAPPED *overlapped = &transfer_priv->overlapped;
300 
301 	usbi_dbg(TRANSFER_CTX(transfer), "transfer %p, length %lu", transfer, ULONG_CAST(size));
302 
303 	overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
304 	overlapped->InternalHigh = (ULONG_PTR)size;
305 
306 	if (!PostQueuedCompletionStatus(priv->completion_port, (DWORD)size, (ULONG_PTR)transfer->dev_handle, overlapped))
307 		usbi_err(TRANSFER_CTX(transfer), "failed to post I/O completion: %s", windows_error_str(0));
308 }
309 
310 /* Windows version detection */
is_x64(void)311 static BOOL is_x64(void)
312 {
313 	BOOL ret = FALSE;
314 
315 	// Detect if we're running a 32 or 64 bit system
316 	if (sizeof(uintptr_t) < 8) {
317 		IsWow64Process(GetCurrentProcess(), &ret);
318 	} else {
319 		ret = TRUE;
320 	}
321 
322 	return ret;
323 }
324 
get_windows_version(void)325 static enum windows_version get_windows_version(void)
326 {
327 	enum windows_version winver;
328 	OSVERSIONINFOEXA vi, vi2;
329 	unsigned major, minor, version;
330 	ULONGLONG major_equal, minor_equal;
331 	const char *w, *arch;
332 	bool ws;
333 
334 	memset(&vi, 0, sizeof(vi));
335 	vi.dwOSVersionInfoSize = sizeof(vi);
336 	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
337 		memset(&vi, 0, sizeof(vi));
338 		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
339 		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
340 			return WINDOWS_UNDEFINED;
341 	}
342 
343 	if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
344 		return WINDOWS_UNDEFINED;
345 
346 	if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
347 		// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
348 		// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
349 		// And starting with Windows 10 Preview 2, Windows enforces the use of the application/supportedOS
350 		// manifest in order for VerSetConditionMask() to report the ACTUAL OS major and minor...
351 
352 		major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
353 		for (major = vi.dwMajorVersion; major <= 9; major++) {
354 			memset(&vi2, 0, sizeof(vi2));
355 			vi2.dwOSVersionInfoSize = sizeof(vi2);
356 			vi2.dwMajorVersion = major;
357 			if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
358 				continue;
359 
360 			if (vi.dwMajorVersion < major) {
361 				vi.dwMajorVersion = major;
362 				vi.dwMinorVersion = 0;
363 			}
364 
365 			minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
366 			for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
367 				memset(&vi2, 0, sizeof(vi2));
368 				vi2.dwOSVersionInfoSize = sizeof(vi2);
369 				vi2.dwMinorVersion = minor;
370 				if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
371 					continue;
372 
373 				vi.dwMinorVersion = minor;
374 				break;
375 			}
376 
377 			break;
378 		}
379 	}
380 
381 	if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
382 		return WINDOWS_UNDEFINED;
383 
384 	ws = (vi.wProductType <= VER_NT_WORKSTATION);
385 	version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
386 
387 	switch (version) {
388 	case 0x50: winver = WINDOWS_2000;  w = "2000"; break;
389 	case 0x51: winver = WINDOWS_XP;	   w = "XP";   break;
390 	case 0x52: winver = WINDOWS_2003;  w = "2003"; break;
391 	case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008");	 break;
392 	case 0x61: winver = WINDOWS_7;	   w = (ws ? "7" : "2008_R2");	 break;
393 	case 0x62: winver = WINDOWS_8;	   w = (ws ? "8" : "2012");	 break;
394 	case 0x63: winver = WINDOWS_8_1;   w = (ws ? "8.1" : "2012_R2"); break;
395 	case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
396 	case 0xA0: winver = WINDOWS_10;	   w = (ws ? "10" : "2016");
397 		   if (vi.dwBuildNumber < 20000)
398 			   break;
399 		   // fallthrough
400 	case 0xB0: winver = WINDOWS_11;	   w = (ws ? "11" : "2022");	 break;
401 	default:
402 		if (version < 0x50)
403 			return WINDOWS_UNDEFINED;
404 		winver = WINDOWS_12_OR_LATER;
405 		w = "12 or later";
406 	}
407 
408 	// We cannot tell if we are on 8, 10, or 11 without "app manifest"
409 	if (version == 0x62 && vi.dwBuildNumber == 9200)
410 		w = "8 (or later)";
411 
412 	arch = is_x64() ? "64-bit" : "32-bit";
413 
414 	if (vi.wServicePackMinor)
415 		usbi_dbg(NULL, "Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
416 	else if (vi.wServicePackMajor)
417 		usbi_dbg(NULL, "Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
418 	else
419 		usbi_dbg(NULL, "Windows %s %s", w, arch);
420 
421 	return winver;
422 }
423 
windows_iocp_thread(void * arg)424 static unsigned __stdcall windows_iocp_thread(void *arg)
425 {
426 	struct libusb_context *ctx = arg;
427 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
428 	HANDLE iocp = priv->completion_port;
429 	DWORD num_bytes;
430 	ULONG_PTR completion_key;
431 	OVERLAPPED *overlapped;
432 	struct libusb_device_handle *dev_handle;
433 	struct libusb_device_handle *opened_device_handle;
434 	struct windows_device_handle_priv *handle_priv;
435 	struct windows_transfer_priv *transfer_priv;
436 	struct usbi_transfer *itransfer;
437 	bool found;
438 
439 	usbi_dbg(ctx, "I/O completion thread started");
440 
441 	while (true) {
442 		overlapped = NULL;
443 		if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
444 			usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
445 			break;
446 		}
447 
448 		if (overlapped == NULL) {
449 			// Signal to quit
450 			if (completion_key != (ULONG_PTR)ctx)
451 				usbi_err(ctx, "program assertion failed - overlapped is NULL");
452 			break;
453 		}
454 
455 		// Find the transfer associated with the OVERLAPPED that just completed.
456 		// If we cannot find a match, the I/O operation originated from outside of libusb
457 		// (e.g. within libusbK) and we need to ignore it.
458 		dev_handle = (struct libusb_device_handle *)completion_key;
459 
460 		found = false;
461 		transfer_priv = NULL;
462 
463 		// Issue 912: lock opened device handles in context to search the current device handle
464 		// to avoid accessing unallocated memory after device has been closed
465 		usbi_mutex_lock(&ctx->open_devs_lock);
466 		for_each_open_device(ctx, opened_device_handle) {
467 			if (dev_handle == opened_device_handle) {
468 				handle_priv = usbi_get_device_handle_priv(dev_handle);
469 
470 				usbi_mutex_lock(&dev_handle->lock);
471 				list_for_each_entry(transfer_priv, &handle_priv->active_transfers, list, struct windows_transfer_priv) {
472 					if (overlapped == &transfer_priv->overlapped) {
473 						// This OVERLAPPED belongs to us, remove the transfer from the device handle's list
474 						list_del(&transfer_priv->list);
475 						found = true;
476 						break;
477 					}
478 				}
479 				usbi_mutex_unlock(&dev_handle->lock);
480 			}
481 		}
482 		usbi_mutex_unlock(&ctx->open_devs_lock);
483 
484 		if (!found) {
485 			usbi_dbg(ctx, "ignoring overlapped %p for handle %p (device %u.%u)",
486 				overlapped, dev_handle, dev_handle->dev->bus_number, dev_handle->dev->device_address);
487 			continue;
488 		}
489 
490 		itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
491 		usbi_dbg(ctx, "transfer %p completed, length %lu",
492 			 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes));
493 		usbi_signal_transfer_completion(itransfer);
494 	}
495 
496 	usbi_dbg(ctx, "I/O completion thread exiting");
497 
498 	return 0;
499 }
500 
windows_init(struct libusb_context * ctx)501 static int windows_init(struct libusb_context *ctx)
502 {
503 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
504 	bool winusb_backend_init = false;
505 	int r;
506 
507 	// NB: concurrent usage supposes that init calls are equally balanced with
508 	// exit calls. If init is called more than exit, we will not exit properly
509 	if (++init_count == 1) { // First init?
510 		windows_version = get_windows_version();
511 		if (windows_version == WINDOWS_UNDEFINED) {
512 			usbi_err(ctx, "failed to detect Windows version");
513 			r = LIBUSB_ERROR_NOT_SUPPORTED;
514 			goto init_exit;
515 		} else if (windows_version < WINDOWS_VISTA) {
516 			usbi_err(ctx, "Windows version is too old");
517 			r = LIBUSB_ERROR_NOT_SUPPORTED;
518 			goto init_exit;
519 		}
520 
521 		if (!htab_create(ctx)) {
522 			r = LIBUSB_ERROR_NO_MEM;
523 			goto init_exit;
524 		}
525 
526 		r = winusb_backend.init(ctx);
527 		if (r != LIBUSB_SUCCESS)
528 			goto init_exit;
529 		winusb_backend_init = true;
530 
531 		r = usbdk_backend.init(ctx);
532 		if (r == LIBUSB_SUCCESS) {
533 			usbi_dbg(ctx, "UsbDk backend is available");
534 			usbdk_available = true;
535 		} else {
536 			usbi_info(ctx, "UsbDk backend is not available");
537 			// Do not report this as an error
538 		}
539 	}
540 
541 	// By default, new contexts will use the WinUSB backend
542 	priv->backend = &winusb_backend;
543 
544 	r = LIBUSB_ERROR_NO_MEM;
545 
546 	// Use an I/O completion port to manage all transfers for this context
547 	priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
548 	if (priv->completion_port == NULL) {
549 		usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
550 		goto init_exit;
551 	}
552 
553 	// And a dedicated thread to wait for I/O completions
554 	priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
555 	if (priv->completion_port_thread == NULL) {
556 		usbi_err(ctx, "failed to create I/O completion port thread");
557 		CloseHandle(priv->completion_port);
558 		goto init_exit;
559 	}
560 
561 	r = LIBUSB_SUCCESS;
562 
563 init_exit: // Holds semaphore here
564 	if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
565 		if (usbdk_available) {
566 			usbdk_backend.exit(ctx);
567 			usbdk_available = false;
568 		}
569 		if (winusb_backend_init)
570 			winusb_backend.exit(ctx);
571 		htab_destroy();
572 		--init_count;
573 	}
574 
575 	return r;
576 }
577 
windows_exit(struct libusb_context * ctx)578 static void windows_exit(struct libusb_context *ctx)
579 {
580 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
581 
582 	// A NULL completion status will indicate to the thread that it is time to exit
583 	if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
584 		usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
585 
586 	if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
587 		usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
588 
589 	CloseHandle(priv->completion_port_thread);
590 	CloseHandle(priv->completion_port);
591 
592 	// Only works if exits and inits are balanced exactly
593 	if (--init_count == 0) { // Last exit
594 		if (usbdk_available) {
595 			usbdk_backend.exit(ctx);
596 			usbdk_available = false;
597 		}
598 		winusb_backend.exit(ctx);
599 		htab_destroy();
600 	}
601 }
602 
windows_set_option(struct libusb_context * ctx,enum libusb_option option,va_list ap)603 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
604 {
605 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
606 
607 	UNUSED(ap);
608 
609 	if (option == LIBUSB_OPTION_USE_USBDK) {
610 		if (!usbdk_available) {
611 			usbi_err(ctx, "UsbDk backend not available");
612 			return LIBUSB_ERROR_NOT_FOUND;
613 		}
614 		usbi_dbg(ctx, "switching context %p to use UsbDk backend", ctx);
615 		priv->backend = &usbdk_backend;
616 		return LIBUSB_SUCCESS;
617 	}
618 
619 	return LIBUSB_ERROR_NOT_SUPPORTED;
620 }
621 
windows_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)622 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
623 {
624 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
625 	return priv->backend->get_device_list(ctx, discdevs);
626 }
627 
windows_open(struct libusb_device_handle * dev_handle)628 static int windows_open(struct libusb_device_handle *dev_handle)
629 {
630 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
631 	struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
632 
633 	list_init(&handle_priv->active_transfers);
634 	return priv->backend->open(dev_handle);
635 }
636 
windows_close(struct libusb_device_handle * dev_handle)637 static void windows_close(struct libusb_device_handle *dev_handle)
638 {
639 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
640 	priv->backend->close(dev_handle);
641 }
642 
windows_get_active_config_descriptor(struct libusb_device * dev,void * buffer,size_t len)643 static int windows_get_active_config_descriptor(struct libusb_device *dev,
644 	void *buffer, size_t len)
645 {
646 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
647 	return priv->backend->get_active_config_descriptor(dev, buffer, len);
648 }
649 
windows_get_config_descriptor(struct libusb_device * dev,uint8_t config_index,void * buffer,size_t len)650 static int windows_get_config_descriptor(struct libusb_device *dev,
651 	uint8_t config_index, void *buffer, size_t len)
652 {
653 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
654 	return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
655 }
656 
windows_get_config_descriptor_by_value(struct libusb_device * dev,uint8_t bConfigurationValue,void ** buffer)657 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
658 	uint8_t bConfigurationValue, void **buffer)
659 {
660 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
661 	return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
662 }
663 
windows_get_configuration(struct libusb_device_handle * dev_handle,uint8_t * config)664 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
665 {
666 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
667 	return priv->backend->get_configuration(dev_handle, config);
668 }
669 
windows_set_configuration(struct libusb_device_handle * dev_handle,int config)670 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
671 {
672 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
673 	if (config == -1)
674 		config = 0;
675 	return priv->backend->set_configuration(dev_handle, (uint8_t)config);
676 }
677 
windows_claim_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)678 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
679 {
680 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
681 	return priv->backend->claim_interface(dev_handle, interface_number);
682 }
683 
windows_release_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)684 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
685 {
686 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
687 	return priv->backend->release_interface(dev_handle, interface_number);
688 }
689 
windows_set_interface_altsetting(struct libusb_device_handle * dev_handle,uint8_t interface_number,uint8_t altsetting)690 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
691 	uint8_t interface_number, uint8_t altsetting)
692 {
693 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
694 	return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
695 }
696 
windows_clear_halt(struct libusb_device_handle * dev_handle,unsigned char endpoint)697 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
698 {
699 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
700 	return priv->backend->clear_halt(dev_handle, endpoint);
701 }
702 
windows_reset_device(struct libusb_device_handle * dev_handle)703 static int windows_reset_device(struct libusb_device_handle *dev_handle)
704 {
705 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
706 	return priv->backend->reset_device(dev_handle);
707 }
708 
windows_destroy_device(struct libusb_device * dev)709 static void windows_destroy_device(struct libusb_device *dev)
710 {
711 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
712 	priv->backend->destroy_device(dev);
713 }
714 
windows_submit_transfer(struct usbi_transfer * itransfer)715 static int windows_submit_transfer(struct usbi_transfer *itransfer)
716 {
717 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
718 	struct libusb_device_handle *dev_handle = transfer->dev_handle;
719 	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
720 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
721 	struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
722 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
723 	int r;
724 
725 	switch (transfer->type) {
726 	case LIBUSB_TRANSFER_TYPE_CONTROL:
727 	case LIBUSB_TRANSFER_TYPE_BULK:
728 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
729 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
730 		break;
731 	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
732 		usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
733 		return LIBUSB_ERROR_NOT_SUPPORTED;
734 	default:
735 		usbi_err(ctx, "unknown endpoint type %d", transfer->type);
736 		return LIBUSB_ERROR_INVALID_PARAM;
737 	}
738 
739 	if (transfer_priv->handle != NULL) {
740 		usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
741 		transfer_priv->handle = NULL;
742 	}
743 
744 	// Add transfer to the device handle's list
745 	usbi_mutex_lock(&dev_handle->lock);
746 	list_add_tail(&transfer_priv->list, &handle_priv->active_transfers);
747 	usbi_mutex_unlock(&dev_handle->lock);
748 
749 	r = priv->backend->submit_transfer(itransfer);
750 	if (r != LIBUSB_SUCCESS) {
751 		// Remove the unsuccessful transfer from the device handle's list
752 		usbi_mutex_lock(&dev_handle->lock);
753 		list_del(&transfer_priv->list);
754 		usbi_mutex_unlock(&dev_handle->lock);
755 
756 		// Always call the backend's clear_transfer_priv() function on failure
757 		priv->backend->clear_transfer_priv(itransfer);
758 		transfer_priv->handle = NULL;
759 		return r;
760 	}
761 
762 	// The backend should set the HANDLE used for each submitted transfer
763 	// by calling set_transfer_priv_handle()
764 	if (transfer_priv->handle == NULL)
765 		usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
766 
767 	return r;
768 }
769 
windows_cancel_transfer(struct usbi_transfer * itransfer)770 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
771 {
772 	struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
773 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
774 
775 	// Try CancelIoEx() on the transfer
776 	// If that fails, fall back to the backend's cancel_transfer()
777 	// function if it is available
778 	if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
779 		return LIBUSB_SUCCESS;
780 	else if (GetLastError() == ERROR_NOT_FOUND)
781 		return LIBUSB_ERROR_NOT_FOUND;
782 
783 	if (priv->backend->cancel_transfer)
784 		return priv->backend->cancel_transfer(itransfer);
785 
786 	usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
787 	return LIBUSB_ERROR_NOT_SUPPORTED;
788 }
789 
windows_handle_transfer_completion(struct usbi_transfer * itransfer)790 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
791 {
792 	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
793 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
794 	const struct windows_backend *backend = priv->backend;
795 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
796 	enum libusb_transfer_status status, istatus;
797 	DWORD result, bytes_transferred;
798 
799 	if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
800 		result = NO_ERROR;
801 	else
802 		result = GetLastError();
803 
804 	usbi_dbg(ctx, "handling transfer %p completion with errcode %lu, length %lu",
805 		 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
806 
807 	switch (result) {
808 	case NO_ERROR:
809 		status = backend->copy_transfer_data(itransfer, bytes_transferred);
810 		break;
811 	case ERROR_GEN_FAILURE:
812 		usbi_dbg(ctx, "detected endpoint stall");
813 		status = LIBUSB_TRANSFER_STALL;
814 		break;
815 	case ERROR_SEM_TIMEOUT:
816 		usbi_dbg(ctx, "detected semaphore timeout");
817 		status = LIBUSB_TRANSFER_TIMED_OUT;
818 		break;
819 	case ERROR_OPERATION_ABORTED:
820 		istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
821 		if (istatus != LIBUSB_TRANSFER_COMPLETED)
822 			usbi_dbg(ctx, "failed to copy partial data in aborted operation: %d", (int)istatus);
823 
824 		usbi_dbg(ctx, "detected operation aborted");
825 		status = LIBUSB_TRANSFER_CANCELLED;
826 		break;
827 	case ERROR_FILE_NOT_FOUND:
828 	case ERROR_DEVICE_NOT_CONNECTED:
829 	case ERROR_NO_SUCH_DEVICE:
830 		usbi_dbg(ctx, "detected device removed");
831 		status = LIBUSB_TRANSFER_NO_DEVICE;
832 		break;
833 	default:
834 		usbi_err(ctx, "detected I/O error %lu: %s",
835 			ULONG_CAST(result), windows_error_str(result));
836 		status = LIBUSB_TRANSFER_ERROR;
837 		break;
838 	}
839 
840 	transfer_priv->handle = NULL;
841 
842 	// Backend-specific cleanup
843 	backend->clear_transfer_priv(itransfer);
844 
845 	if (status == LIBUSB_TRANSFER_CANCELLED)
846 		return usbi_handle_transfer_cancellation(itransfer);
847 	else
848 		return usbi_handle_transfer_completion(itransfer, status);
849 }
850 
usbi_get_monotonic_time(struct timespec * tp)851 void usbi_get_monotonic_time(struct timespec *tp)
852 {
853 	static LONG hires_counter_init;
854 	static uint64_t hires_ticks_to_ps;
855 	static uint64_t hires_frequency;
856 	LARGE_INTEGER hires_counter;
857 
858 	if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
859 		LARGE_INTEGER li_frequency;
860 
861 		// Microsoft says that the QueryPerformanceFrequency() and
862 		// QueryPerformanceCounter() functions always succeed on XP and later
863 		QueryPerformanceFrequency(&li_frequency);
864 
865 		// The hires frequency can go as high as 4 GHz, so we'll use a conversion
866 		// to picoseconds to compute the tv_nsecs part
867 		hires_frequency = li_frequency.QuadPart;
868 		hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
869 	}
870 
871 	QueryPerformanceCounter(&hires_counter);
872 	tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
873 	tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
874 }
875 
876 // NB: MSVC6 does not support named initializers.
877 const struct usbi_os_backend usbi_backend = {
878 	"Windows",
879 	USBI_CAP_HAS_HID_ACCESS,
880 	windows_init,
881 	windows_exit,
882 	windows_set_option,
883 	windows_get_device_list,
884 	NULL,	/* hotplug_poll */
885 	NULL,	/* wrap_sys_device */
886 	windows_open,
887 	windows_close,
888 	windows_get_active_config_descriptor,
889 	windows_get_config_descriptor,
890 	windows_get_config_descriptor_by_value,
891 	windows_get_configuration,
892 	windows_set_configuration,
893 	windows_claim_interface,
894 	windows_release_interface,
895 	windows_set_interface_altsetting,
896 	windows_clear_halt,
897 	windows_reset_device,
898 	NULL,	/* alloc_streams */
899 	NULL,	/* free_streams */
900 	NULL,	/* dev_mem_alloc */
901 	NULL,	/* dev_mem_free */
902 	NULL,	/* kernel_driver_active */
903 	NULL,	/* detach_kernel_driver */
904 	NULL,	/* attach_kernel_driver */
905 	windows_destroy_device,
906 	windows_submit_transfer,
907 	windows_cancel_transfer,
908 	NULL,	/* clear_transfer_priv */
909 	NULL,	/* handle_events */
910 	windows_handle_transfer_completion,
911 	sizeof(struct windows_context_priv),
912 	sizeof(union windows_device_priv),
913 	sizeof(struct windows_device_handle_priv),
914 	sizeof(struct windows_transfer_priv),
915 };
916