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