xref: /aosp_15_r20/external/libusb/libusb/os/windows_common.c (revision 86b64dcb59b3a0b37502ecd56e119234366a6f7e)
1 /*
2  * windows backend for libusb 1.0
3  * Copyright © 2009-2012 Pete Batard <[email protected]>
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 	case USBD_STATUS_STALL_PID:
283 		return LIBUSB_TRANSFER_STALL;
284 	case USBD_STATUS_DEVICE_GONE:
285 		return LIBUSB_TRANSFER_NO_DEVICE;
286 	default:
287 		usbi_dbg(NULL, "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_CTX(transfer), "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 #ifndef ENABLE_LOGGING
336 	UNUSED(w); UNUSED(arch);
337 #endif
338 	memset(&vi, 0, sizeof(vi));
339 	vi.dwOSVersionInfoSize = sizeof(vi);
340 	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
341 		memset(&vi, 0, sizeof(vi));
342 		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
343 		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
344 			return WINDOWS_UNDEFINED;
345 	}
346 
347 	if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
348 		return WINDOWS_UNDEFINED;
349 
350 	if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
351 		// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
352 		// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
353 		// And starting with Windows 10 Preview 2, Windows enforces the use of the application/supportedOS
354 		// manifest in order for VerSetConditionMask() to report the ACTUAL OS major and minor...
355 
356 		major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
357 		for (major = vi.dwMajorVersion; major <= 9; major++) {
358 			memset(&vi2, 0, sizeof(vi2));
359 			vi2.dwOSVersionInfoSize = sizeof(vi2);
360 			vi2.dwMajorVersion = major;
361 			if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
362 				continue;
363 
364 			if (vi.dwMajorVersion < major) {
365 				vi.dwMajorVersion = major;
366 				vi.dwMinorVersion = 0;
367 			}
368 
369 			minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
370 			for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
371 				memset(&vi2, 0, sizeof(vi2));
372 				vi2.dwOSVersionInfoSize = sizeof(vi2);
373 				vi2.dwMinorVersion = minor;
374 				if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
375 					continue;
376 
377 				vi.dwMinorVersion = minor;
378 				break;
379 			}
380 
381 			break;
382 		}
383 	}
384 
385 	if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
386 		return WINDOWS_UNDEFINED;
387 
388 	ws = (vi.wProductType <= VER_NT_WORKSTATION);
389 	version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
390 
391 	switch (version) {
392 	case 0x50: winver = WINDOWS_2000;  w = "2000"; break;
393 	case 0x51: winver = WINDOWS_XP;	   w = "XP";   break;
394 	case 0x52: winver = WINDOWS_2003;  w = "2003"; break;
395 	case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008");	 break;
396 	case 0x61: winver = WINDOWS_7;	   w = (ws ? "7" : "2008_R2");	 break;
397 	case 0x62: winver = WINDOWS_8;	   w = (ws ? "8" : "2012");	 break;
398 	case 0x63: winver = WINDOWS_8_1;   w = (ws ? "8.1" : "2012_R2"); break;
399 	case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
400 	case 0xA0: winver = WINDOWS_10;	   w = (ws ? "10" : "2016");
401 		   if (vi.dwBuildNumber < 20000)
402 			   break;
403 		   // fallthrough
404 	case 0xB0: winver = WINDOWS_11;	   w = (ws ? "11" : "2022");	 break;
405 	default:
406 		if (version < 0x50)
407 			return WINDOWS_UNDEFINED;
408 		winver = WINDOWS_12_OR_LATER;
409 		w = "12 or later";
410 	}
411 
412 	// We cannot tell if we are on 8, 10, or 11 without "app manifest"
413 	if (version == 0x62 && vi.dwBuildNumber == 9200)
414 		w = "8 (or later)";
415 
416 	arch = is_x64() ? "64-bit" : "32-bit";
417 
418 	if (vi.wServicePackMinor)
419 		usbi_dbg(NULL, "Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
420 	else if (vi.wServicePackMajor)
421 		usbi_dbg(NULL, "Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
422 	else
423 		usbi_dbg(NULL, "Windows %s %s", w, arch);
424 
425 	return winver;
426 }
427 
windows_iocp_thread(void * arg)428 static unsigned __stdcall windows_iocp_thread(void *arg)
429 {
430 	struct libusb_context *ctx = arg;
431 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
432 	HANDLE iocp = priv->completion_port;
433 	DWORD num_bytes;
434 	ULONG_PTR completion_key;
435 	OVERLAPPED *overlapped;
436 	struct libusb_device_handle *dev_handle;
437 	struct libusb_device_handle *opened_device_handle;
438 	struct windows_device_handle_priv *handle_priv;
439 	struct windows_transfer_priv *transfer_priv;
440 	struct usbi_transfer *itransfer;
441 	bool found;
442 
443 	usbi_dbg(ctx, "I/O completion thread started");
444 
445 	while (true) {
446 		overlapped = NULL;
447 		if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
448 			usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
449 			break;
450 		}
451 
452 		if (overlapped == NULL) {
453 			// Signal to quit
454 			if (completion_key != (ULONG_PTR)ctx)
455 				usbi_err(ctx, "program assertion failed - overlapped is NULL");
456 			break;
457 		}
458 
459 		// Find the transfer associated with the OVERLAPPED that just completed.
460 		// If we cannot find a match, the I/O operation originated from outside of libusb
461 		// (e.g. within libusbK) and we need to ignore it.
462 		dev_handle = (struct libusb_device_handle *)completion_key;
463 
464 		found = false;
465 		transfer_priv = NULL;
466 
467 		// Issue 912: lock opened device handles in context to search the current device handle
468 		// to avoid accessing unallocated memory after device has been closed
469 		usbi_mutex_lock(&ctx->open_devs_lock);
470 		for_each_open_device(ctx, opened_device_handle) {
471 			if (dev_handle == opened_device_handle) {
472 				handle_priv = usbi_get_device_handle_priv(dev_handle);
473 
474 				usbi_mutex_lock(&dev_handle->lock);
475 				list_for_each_entry(transfer_priv, &handle_priv->active_transfers, list, struct windows_transfer_priv) {
476 					if (overlapped == &transfer_priv->overlapped) {
477 						// This OVERLAPPED belongs to us, remove the transfer from the device handle's list
478 						list_del(&transfer_priv->list);
479 						found = true;
480 						break;
481 					}
482 				}
483 				usbi_mutex_unlock(&dev_handle->lock);
484 			}
485 		}
486 		usbi_mutex_unlock(&ctx->open_devs_lock);
487 
488 		if (!found) {
489 			usbi_dbg(ctx, "ignoring overlapped %p for handle %p",
490 				 overlapped, dev_handle);
491 			continue;
492 		}
493 
494 		itransfer = TRANSFER_PRIV_TO_USBI_TRANSFER(transfer_priv);
495 		struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
496 		usbi_dbg(ctx, "transfer %p completed, length %lu",
497 			 transfer, ULONG_CAST(num_bytes));
498 		usbi_signal_transfer_completion(itransfer);
499 	}
500 
501 	usbi_dbg(ctx, "I/O completion thread exiting");
502 
503 	return 0;
504 }
505 
windows_init(struct libusb_context * ctx)506 static int windows_init(struct libusb_context *ctx)
507 {
508 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
509 	bool winusb_backend_init = false;
510 	int r;
511 
512 	// NB: concurrent usage supposes that init calls are equally balanced with
513 	// exit calls. If init is called more than exit, we will not exit properly
514 	if (++init_count == 1) { // First init?
515 		windows_version = get_windows_version();
516 		if (windows_version == WINDOWS_UNDEFINED) {
517 			usbi_err(ctx, "failed to detect Windows version");
518 			r = LIBUSB_ERROR_NOT_SUPPORTED;
519 			goto init_exit;
520 		} else if (windows_version < WINDOWS_VISTA) {
521 			usbi_err(ctx, "Windows version is too old");
522 			r = LIBUSB_ERROR_NOT_SUPPORTED;
523 			goto init_exit;
524 		}
525 
526 		if (!htab_create(ctx)) {
527 			r = LIBUSB_ERROR_NO_MEM;
528 			goto init_exit;
529 		}
530 
531 		r = winusb_backend.init(ctx);
532 		if (r != LIBUSB_SUCCESS)
533 			goto init_exit;
534 		winusb_backend_init = true;
535 
536 		r = usbdk_backend.init(ctx);
537 		if (r == LIBUSB_SUCCESS) {
538 			usbi_dbg(ctx, "UsbDk backend is available");
539 			usbdk_available = true;
540 		} else {
541 			usbi_info(ctx, "UsbDk backend is not available");
542 			// Do not report this as an error
543 		}
544 	}
545 
546 	// By default, new contexts will use the WinUSB backend
547 	priv->backend = &winusb_backend;
548 
549 	r = LIBUSB_ERROR_NO_MEM;
550 
551 	// Use an I/O completion port to manage all transfers for this context
552 	priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
553 	if (priv->completion_port == NULL) {
554 		usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
555 		goto init_exit;
556 	}
557 
558 	// And a dedicated thread to wait for I/O completions
559 	priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
560 	if (priv->completion_port_thread == NULL) {
561 		usbi_err(ctx, "failed to create I/O completion port thread");
562 		CloseHandle(priv->completion_port);
563 		goto init_exit;
564 	}
565 
566 	r = LIBUSB_SUCCESS;
567 
568 init_exit: // Holds semaphore here
569 	if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
570 		if (usbdk_available) {
571 			usbdk_backend.exit(ctx);
572 			usbdk_available = false;
573 		}
574 		if (winusb_backend_init)
575 			winusb_backend.exit(ctx);
576 		htab_destroy();
577 		--init_count;
578 	}
579 
580 	return r;
581 }
582 
windows_exit(struct libusb_context * ctx)583 static void windows_exit(struct libusb_context *ctx)
584 {
585 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
586 
587 	// A NULL completion status will indicate to the thread that it is time to exit
588 	if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
589 		usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
590 
591 	if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
592 		usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
593 
594 	CloseHandle(priv->completion_port_thread);
595 	CloseHandle(priv->completion_port);
596 
597 	// Only works if exits and inits are balanced exactly
598 	if (--init_count == 0) { // Last exit
599 		if (usbdk_available) {
600 			usbdk_backend.exit(ctx);
601 			usbdk_available = false;
602 		}
603 		winusb_backend.exit(ctx);
604 		htab_destroy();
605 	}
606 }
607 
windows_set_option(struct libusb_context * ctx,enum libusb_option option,va_list ap)608 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
609 {
610 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
611 
612 	UNUSED(ap);
613 
614 	if (option == LIBUSB_OPTION_USE_USBDK) {
615 		if (!usbdk_available) {
616 			usbi_err(ctx, "UsbDk backend not available");
617 			return LIBUSB_ERROR_NOT_FOUND;
618 		}
619 		usbi_dbg(ctx, "switching context %p to use UsbDk backend", ctx);
620 		priv->backend = &usbdk_backend;
621 		return LIBUSB_SUCCESS;
622 	}
623 
624 	return LIBUSB_ERROR_NOT_SUPPORTED;
625 }
626 
windows_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)627 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
628 {
629 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
630 	return priv->backend->get_device_list(ctx, discdevs);
631 }
632 
windows_open(struct libusb_device_handle * dev_handle)633 static int windows_open(struct libusb_device_handle *dev_handle)
634 {
635 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
636 	struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
637 
638 	list_init(&handle_priv->active_transfers);
639 	return priv->backend->open(dev_handle);
640 }
641 
windows_close(struct libusb_device_handle * dev_handle)642 static void windows_close(struct libusb_device_handle *dev_handle)
643 {
644 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
645 	priv->backend->close(dev_handle);
646 }
647 
windows_get_active_config_descriptor(struct libusb_device * dev,void * buffer,size_t len)648 static int windows_get_active_config_descriptor(struct libusb_device *dev,
649 	void *buffer, size_t len)
650 {
651 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
652 	return priv->backend->get_active_config_descriptor(dev, buffer, len);
653 }
654 
windows_get_config_descriptor(struct libusb_device * dev,uint8_t config_index,void * buffer,size_t len)655 static int windows_get_config_descriptor(struct libusb_device *dev,
656 	uint8_t config_index, void *buffer, size_t len)
657 {
658 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
659 	return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
660 }
661 
windows_get_config_descriptor_by_value(struct libusb_device * dev,uint8_t bConfigurationValue,void ** buffer)662 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
663 	uint8_t bConfigurationValue, void **buffer)
664 {
665 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
666 	return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
667 }
668 
windows_get_configuration(struct libusb_device_handle * dev_handle,uint8_t * config)669 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
670 {
671 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
672 	return priv->backend->get_configuration(dev_handle, config);
673 }
674 
windows_set_configuration(struct libusb_device_handle * dev_handle,int config)675 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
676 {
677 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
678 	if (config == -1)
679 		config = 0;
680 	return priv->backend->set_configuration(dev_handle, (uint8_t)config);
681 }
682 
windows_claim_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)683 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
684 {
685 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
686 	return priv->backend->claim_interface(dev_handle, interface_number);
687 }
688 
windows_release_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)689 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
690 {
691 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
692 	return priv->backend->release_interface(dev_handle, interface_number);
693 }
694 
windows_set_interface_altsetting(struct libusb_device_handle * dev_handle,uint8_t interface_number,uint8_t altsetting)695 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
696 	uint8_t interface_number, uint8_t altsetting)
697 {
698 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
699 	return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
700 }
701 
windows_clear_halt(struct libusb_device_handle * dev_handle,unsigned char endpoint)702 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
703 {
704 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
705 	return priv->backend->clear_halt(dev_handle, endpoint);
706 }
707 
windows_reset_device(struct libusb_device_handle * dev_handle)708 static int windows_reset_device(struct libusb_device_handle *dev_handle)
709 {
710 	struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
711 	return priv->backend->reset_device(dev_handle);
712 }
713 
windows_destroy_device(struct libusb_device * dev)714 static void windows_destroy_device(struct libusb_device *dev)
715 {
716 	struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
717 	priv->backend->destroy_device(dev);
718 }
719 
windows_submit_transfer(struct usbi_transfer * itransfer)720 static int windows_submit_transfer(struct usbi_transfer *itransfer)
721 {
722 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
723 	struct libusb_device_handle *dev_handle = transfer->dev_handle;
724 	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
725 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
726 	struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
727 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
728 	int r;
729 
730 	switch (transfer->type) {
731 	case LIBUSB_TRANSFER_TYPE_CONTROL:
732 	case LIBUSB_TRANSFER_TYPE_BULK:
733 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
734 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
735 		break;
736 	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
737 		usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
738 		return LIBUSB_ERROR_NOT_SUPPORTED;
739 	default:
740 		usbi_err(ctx, "unknown endpoint type %d", transfer->type);
741 		return LIBUSB_ERROR_INVALID_PARAM;
742 	}
743 
744 	if (transfer_priv->handle != NULL) {
745 		usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
746 		transfer_priv->handle = NULL;
747 	}
748 
749 	// Add transfer to the device handle's list
750 	usbi_mutex_lock(&dev_handle->lock);
751 	list_add_tail(&transfer_priv->list, &handle_priv->active_transfers);
752 	usbi_mutex_unlock(&dev_handle->lock);
753 
754 	r = priv->backend->submit_transfer(itransfer);
755 	if (r != LIBUSB_SUCCESS) {
756 		// Remove the unsuccessful transfer from the device handle's list
757 		usbi_mutex_lock(&dev_handle->lock);
758 		list_del(&transfer_priv->list);
759 		usbi_mutex_unlock(&dev_handle->lock);
760 
761 		// Always call the backend's clear_transfer_priv() function on failure
762 		priv->backend->clear_transfer_priv(itransfer);
763 		transfer_priv->handle = NULL;
764 		return r;
765 	}
766 
767 	// The backend should set the HANDLE used for each submitted transfer
768 	// by calling set_transfer_priv_handle()
769 	if (transfer_priv->handle == NULL)
770 		usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
771 
772 	return r;
773 }
774 
windows_cancel_transfer(struct usbi_transfer * itransfer)775 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
776 {
777 	struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
778 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
779 
780 	// Try CancelIoEx() on the transfer
781 	// If that fails, fall back to the backend's cancel_transfer()
782 	// function if it is available
783 	if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
784 		return LIBUSB_SUCCESS;
785 	else if (GetLastError() == ERROR_NOT_FOUND)
786 		return LIBUSB_ERROR_NOT_FOUND;
787 
788 	if (priv->backend->cancel_transfer)
789 		return priv->backend->cancel_transfer(itransfer);
790 
791 	usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
792 	return LIBUSB_ERROR_NOT_SUPPORTED;
793 }
794 
windows_handle_transfer_completion(struct usbi_transfer * itransfer)795 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
796 {
797 	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
798 	struct windows_context_priv *priv = usbi_get_context_priv(ctx);
799 	const struct windows_backend *backend = priv->backend;
800 	struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
801 	enum libusb_transfer_status status, istatus;
802 	DWORD result, bytes_transferred;
803 
804 	if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
805 		result = NO_ERROR;
806 	else
807 		result = GetLastError();
808 
809 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
810 	usbi_dbg(ctx, "handling transfer %p completion with errcode %lu, length %lu",
811 		 transfer, ULONG_CAST(result), ULONG_CAST(bytes_transferred));
812 
813 	switch (result) {
814 	case NO_ERROR:
815 		status = backend->copy_transfer_data(itransfer, bytes_transferred);
816 		break;
817 	case ERROR_GEN_FAILURE:
818 		usbi_dbg(ctx, "detected endpoint stall");
819 		status = LIBUSB_TRANSFER_STALL;
820 		break;
821 	case ERROR_SEM_TIMEOUT:
822 		usbi_dbg(ctx, "detected semaphore timeout");
823 		status = LIBUSB_TRANSFER_TIMED_OUT;
824 		break;
825 	case ERROR_OPERATION_ABORTED:
826 		istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
827 		if (istatus != LIBUSB_TRANSFER_COMPLETED)
828 			usbi_dbg(ctx, "failed to copy partial data in aborted operation: %d", (int)istatus);
829 
830 		usbi_dbg(ctx, "detected operation aborted");
831 		status = LIBUSB_TRANSFER_CANCELLED;
832 		break;
833 	case ERROR_FILE_NOT_FOUND:
834 	case ERROR_DEVICE_NOT_CONNECTED:
835 	case ERROR_NO_SUCH_DEVICE:
836 		usbi_dbg(ctx, "detected device removed");
837 		status = LIBUSB_TRANSFER_NO_DEVICE;
838 		break;
839 	default:
840 		usbi_err(ctx, "detected I/O error %lu: %s",
841 			ULONG_CAST(result), windows_error_str(result));
842 		status = LIBUSB_TRANSFER_ERROR;
843 		break;
844 	}
845 
846 	transfer_priv->handle = NULL;
847 
848 	// Backend-specific cleanup
849 	backend->clear_transfer_priv(itransfer);
850 
851 	if (status == LIBUSB_TRANSFER_CANCELLED)
852 		return usbi_handle_transfer_cancellation(itransfer);
853 	else
854 		return usbi_handle_transfer_completion(itransfer, status);
855 }
856 
857 #ifndef HAVE_CLOCK_GETTIME
usbi_get_monotonic_time(struct timespec * tp)858 void usbi_get_monotonic_time(struct timespec *tp)
859 {
860 	static LONG hires_counter_init;
861 	static uint64_t hires_ticks_to_ps;
862 	static uint64_t hires_frequency;
863 	LARGE_INTEGER hires_counter;
864 
865 	if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
866 		LARGE_INTEGER li_frequency;
867 
868 		// Microsoft says that the QueryPerformanceFrequency() and
869 		// QueryPerformanceCounter() functions always succeed on XP and later
870 		QueryPerformanceFrequency(&li_frequency);
871 
872 		// The hires frequency can go as high as 4 GHz, so we'll use a conversion
873 		// to picoseconds to compute the tv_nsecs part
874 		hires_frequency = li_frequency.QuadPart;
875 		hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
876 	}
877 
878 	QueryPerformanceCounter(&hires_counter);
879 	tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
880 	tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
881 }
882 #endif
883 
884 // NB: MSVC6 does not support named initializers.
885 const struct usbi_os_backend usbi_backend = {
886 	"Windows",
887 	USBI_CAP_HAS_HID_ACCESS,
888 	windows_init,
889 	windows_exit,
890 	windows_set_option,
891 	windows_get_device_list,
892 	NULL,	/* hotplug_poll */
893 	NULL,	/* wrap_sys_device */
894 	windows_open,
895 	windows_close,
896 	windows_get_active_config_descriptor,
897 	windows_get_config_descriptor,
898 	windows_get_config_descriptor_by_value,
899 	windows_get_configuration,
900 	windows_set_configuration,
901 	windows_claim_interface,
902 	windows_release_interface,
903 	windows_set_interface_altsetting,
904 	windows_clear_halt,
905 	windows_reset_device,
906 	NULL,	/* alloc_streams */
907 	NULL,	/* free_streams */
908 	NULL,	/* dev_mem_alloc */
909 	NULL,	/* dev_mem_free */
910 	NULL,	/* kernel_driver_active */
911 	NULL,	/* detach_kernel_driver */
912 	NULL,	/* attach_kernel_driver */
913 	windows_destroy_device,
914 	windows_submit_transfer,
915 	windows_cancel_transfer,
916 	NULL,	/* clear_transfer_priv */
917 	NULL,	/* handle_events */
918 	windows_handle_transfer_completion,
919 	sizeof(struct windows_context_priv),
920 	sizeof(union windows_device_priv),
921 	sizeof(struct windows_device_handle_priv),
922 	sizeof(struct windows_transfer_priv),
923 };
924