• 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 <inttypes.h>
28 #include <process.h>
29 #include <stdio.h>
30 
31 #include "libusbi.h"
32 #include "windows_common.h"
33 #include "windows_nt_common.h"
34 
35 // Global variables
36 const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
37 
38 // Global variables for clock_gettime mechanism
39 static uint64_t hires_ticks_to_ps;
40 static uint64_t hires_frequency;
41 
42 #define TIMER_REQUEST_RETRY_MS	100
43 #define WM_TIMER_REQUEST	(WM_USER + 1)
44 #define WM_TIMER_EXIT		(WM_USER + 2)
45 
46 // used for monotonic clock_gettime()
47 struct timer_request {
48 	struct timespec *tp;
49 	HANDLE event;
50 };
51 
52 // Timer thread
53 static HANDLE timer_thread = NULL;
54 static DWORD timer_thread_id = 0;
55 
56 /* User32 dependencies */
57 DLL_DECLARE_HANDLE(User32);
58 DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT));
59 DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT));
60 DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM));
61 
62 static unsigned __stdcall windows_clock_gettime_threaded(void *param);
63 
64 /*
65 * Converts a windows error to human readable string
66 * uses retval as errorcode, or, if 0, use GetLastError()
67 */
68 #if defined(ENABLE_LOGGING)
windows_error_str(DWORD retval)69 const char *windows_error_str(DWORD retval)
70 {
71 	static char err_string[ERR_BUFFER_SIZE];
72 
73 	DWORD error_code, format_error;
74 	DWORD size;
75 	ssize_t i;
76 
77 	error_code = retval ? retval : GetLastError();
78 
79 	safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", (unsigned int)error_code);
80 
81 	// Translate codes returned by SetupAPI. The ones we are dealing with are either
82 	// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
83 	// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
84 	switch (error_code & 0xE0000000) {
85 	case 0:
86 		error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
87 		break;
88 	case 0xE0000000:
89 		error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
90 		break;
91 	default:
92 		break;
93 	}
94 
95 	size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
96 			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)],
97 			ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL);
98 	if (size == 0) {
99 		format_error = GetLastError();
100 		if (format_error)
101 			safe_sprintf(err_string, ERR_BUFFER_SIZE,
102 					"Windows error code %u (FormatMessage error code %u)",
103 					(unsigned int)error_code, (unsigned int)format_error);
104 		else
105 			safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code);
106 	}
107 	else {
108 		// Remove CR/LF terminators
109 		for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--)
110 			err_string[i] = 0;
111 	}
112 
113 	return err_string;
114 }
115 #endif
116 
117 /* Hash table functions - modified From glibc 2.3.2:
118    [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
119    [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
120 
121 #define HTAB_SIZE 1021
122 
123 typedef struct htab_entry {
124 	unsigned long used;
125 	char *str;
126 } htab_entry;
127 
128 static htab_entry *htab_table = NULL;
129 static usbi_mutex_t htab_write_mutex = NULL;
130 static unsigned long htab_size, htab_filled;
131 
132 /* For the used double hash method the table size has to be a prime. To
133    correct the user given table size we need a prime test.  This trivial
134    algorithm is adequate because the code is called only during init and
135    the number is likely to be small  */
isprime(unsigned long number)136 static int isprime(unsigned long number)
137 {
138 	// no even number will be passed
139 	unsigned int divider = 3;
140 
141 	while((divider * divider < number) && (number % divider != 0))
142 		divider += 2;
143 
144 	return (number % divider != 0);
145 }
146 
147 /* Before using the hash table we must allocate memory for it.
148    We allocate one element more as the found prime number says.
149    This is done for more effective indexing as explained in the
150    comment for the hash function.  */
htab_create(struct libusb_context * ctx,unsigned long nel)151 static bool htab_create(struct libusb_context *ctx, unsigned long nel)
152 {
153 	if (htab_table != NULL) {
154 		usbi_err(ctx, "hash table already allocated");
155 		return true;
156 	}
157 
158 	// Create a mutex
159 	usbi_mutex_init(&htab_write_mutex);
160 
161 	// Change nel to the first prime number not smaller as nel.
162 	nel |= 1;
163 	while (!isprime(nel))
164 		nel += 2;
165 
166 	htab_size = nel;
167 	usbi_dbg("using %lu entries hash table", nel);
168 	htab_filled = 0;
169 
170 	// allocate memory and zero out.
171 	htab_table = calloc(htab_size + 1, sizeof(htab_entry));
172 	if (htab_table == NULL) {
173 		usbi_err(ctx, "could not allocate space for hash table");
174 		return false;
175 	}
176 
177 	return true;
178 }
179 
180 /* After using the hash table it has to be destroyed.  */
htab_destroy(void)181 static void htab_destroy(void)
182 {
183 	unsigned long i;
184 
185 	if (htab_table == NULL)
186 		return;
187 
188 	for (i = 0; i < htab_size; i++) {
189 		if (htab_table[i].used)
190 			safe_free(htab_table[i].str);
191 	}
192 
193 	usbi_mutex_destroy(&htab_write_mutex);
194 	safe_free(htab_table);
195 }
196 
197 /* This is the search function. It uses double hashing with open addressing.
198    We use a trick to speed up the lookup. The table is created with one
199    more element available. This enables us to use the index zero special.
200    This index will never be used because we store the first hash index in
201    the field used where zero means not used. Every other value means used.
202    The used field can be used as a first fast comparison for equality of
203    the stored and the parameter value. This helps to prevent unnecessary
204    expensive calls of strcmp.  */
htab_hash(const char * str)205 unsigned long htab_hash(const char *str)
206 {
207 	unsigned long hval, hval2;
208 	unsigned long idx;
209 	unsigned long r = 5381;
210 	int c;
211 	const char *sz = str;
212 
213 	if (str == NULL)
214 		return 0;
215 
216 	// Compute main hash value (algorithm suggested by Nokia)
217 	while ((c = *sz++) != 0)
218 		r = ((r << 5) + r) + c;
219 	if (r == 0)
220 		++r;
221 
222 	// compute table hash: simply take the modulus
223 	hval = r % htab_size;
224 	if (hval == 0)
225 		++hval;
226 
227 	// Try the first index
228 	idx = hval;
229 
230 	if (htab_table[idx].used) {
231 		if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0))
232 			return idx; // existing hash
233 
234 		usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
235 
236 		// Second hash function, as suggested in [Knuth]
237 		hval2 = 1 + hval % (htab_size - 2);
238 
239 		do {
240 			// Because size is prime this guarantees to step through all available indexes
241 			if (idx <= hval2)
242 				idx = htab_size + idx - hval2;
243 			else
244 				idx -= hval2;
245 
246 			// If we visited all entries leave the loop unsuccessfully
247 			if (idx == hval)
248 				break;
249 
250 			// If entry is found use it.
251 			if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0))
252 				return idx;
253 		} while (htab_table[idx].used);
254 	}
255 
256 	// Not found => New entry
257 
258 	// If the table is full return an error
259 	if (htab_filled >= htab_size) {
260 		usbi_err(NULL, "hash table is full (%d entries)", htab_size);
261 		return 0;
262 	}
263 
264 	// Concurrent threads might be storing the same entry at the same time
265 	// (eg. "simultaneous" enums from different threads) => use a mutex
266 	usbi_mutex_lock(&htab_write_mutex);
267 	// Just free any previously allocated string (which should be the same as
268 	// new one). The possibility of concurrent threads storing a collision
269 	// string (same hash, different string) at the same time is extremely low
270 	safe_free(htab_table[idx].str);
271 	htab_table[idx].used = hval;
272 	htab_table[idx].str = _strdup(str);
273 	if (htab_table[idx].str == NULL) {
274 		usbi_err(NULL, "could not duplicate string for hash table");
275 		usbi_mutex_unlock(&htab_write_mutex);
276 		return 0;
277 	}
278 	++htab_filled;
279 	usbi_mutex_unlock(&htab_write_mutex);
280 
281 	return idx;
282 }
283 
windows_init_dlls(void)284 static int windows_init_dlls(void)
285 {
286 	DLL_GET_HANDLE(User32);
287 	DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE);
288 	DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE);
289 	DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE);
290 
291 	return LIBUSB_SUCCESS;
292 }
293 
windows_exit_dlls(void)294 static void windows_exit_dlls(void)
295 {
296 	DLL_FREE_HANDLE(User32);
297 }
298 
windows_init_clock(struct libusb_context * ctx)299 static bool windows_init_clock(struct libusb_context *ctx)
300 {
301 	DWORD_PTR affinity, dummy;
302 	HANDLE event = NULL;
303 	LARGE_INTEGER li_frequency;
304 	int i;
305 
306 	if (QueryPerformanceFrequency(&li_frequency)) {
307 		// Load DLL imports
308 		if (windows_init_dlls() != LIBUSB_SUCCESS) {
309 			usbi_err(ctx, "could not resolve DLL functions");
310 			return false;
311 		}
312 
313 		// The hires frequency can go as high as 4 GHz, so we'll use a conversion
314 		// to picoseconds to compute the tv_nsecs part in clock_gettime
315 		hires_frequency = li_frequency.QuadPart;
316 		hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
317 		usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
318 
319 		// Because QueryPerformanceCounter might report different values when
320 		// running on different cores, we create a separate thread for the timer
321 		// calls, which we glue to the first available core always to prevent timing discrepancies.
322 		if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
323 			usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
324 			return false;
325 		}
326 
327 		// The process affinity mask is a bitmask where each set bit represents a core on
328 		// which this process is allowed to run, so we find the first set bit
329 		for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
330 		affinity = (DWORD_PTR)(1 << i);
331 
332 		usbi_dbg("timer thread will run on core #%d", i);
333 
334 		event = CreateEvent(NULL, FALSE, FALSE, NULL);
335 		if (event == NULL) {
336 			usbi_err(ctx, "could not create event: %s", windows_error_str(0));
337 			return false;
338 		}
339 
340 		timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
341 				0, (unsigned int *)&timer_thread_id);
342 		if (timer_thread == NULL) {
343 			usbi_err(ctx, "unable to create timer thread - aborting");
344 			CloseHandle(event);
345 			return false;
346 		}
347 
348 		if (!SetThreadAffinityMask(timer_thread, affinity))
349 			usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
350 
351 		// Wait for timer thread to init before continuing.
352 		if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
353 			usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
354 			CloseHandle(event);
355 			return false;
356 		}
357 
358 		CloseHandle(event);
359 	} else {
360 		usbi_dbg("no hires timer available on this platform");
361 		hires_frequency = 0;
362 		hires_ticks_to_ps = UINT64_C(0);
363 	}
364 
365 	return true;
366 }
367 
windows_destroy_clock(void)368 void windows_destroy_clock(void)
369 {
370 	if (timer_thread) {
371 		// actually the signal to quit the thread.
372 		if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0)
373 				|| (WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
374 			usbi_dbg("could not wait for timer thread to quit");
375 			TerminateThread(timer_thread, 1);
376 			// shouldn't happen, but we're destroying
377 			// all objects it might have held anyway.
378 		}
379 		CloseHandle(timer_thread);
380 		timer_thread = NULL;
381 		timer_thread_id = 0;
382 	}
383 }
384 
385 /*
386 * Monotonic and real time functions
387 */
windows_clock_gettime_threaded(void * param)388 static unsigned __stdcall windows_clock_gettime_threaded(void *param)
389 {
390 	struct timer_request *request;
391 	LARGE_INTEGER hires_counter;
392 	MSG msg;
393 
394 	// The following call will create this thread's message queue
395 	// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
396 	pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
397 
398 	// Signal windows_init_clock() that we're ready to service requests
399 	if (!SetEvent((HANDLE)param))
400 		usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
401 	param = NULL;
402 
403 	// Main loop - wait for requests
404 	while (1) {
405 		if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
406 			usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
407 			return 1;
408 		}
409 
410 		switch (msg.message) {
411 		case WM_TIMER_REQUEST:
412 			// Requests to this thread are for hires always
413 			// Microsoft says that this function always succeeds on XP and later
414 			// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
415 			request = (struct timer_request *)msg.lParam;
416 			QueryPerformanceCounter(&hires_counter);
417 			request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
418 			request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
419 			if (!SetEvent(request->event))
420 				usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
421 			break;
422 		case WM_TIMER_EXIT:
423 			usbi_dbg("timer thread quitting");
424 			return 0;
425 		}
426 	}
427 }
428 
windows_clock_gettime(int clk_id,struct timespec * tp)429 int windows_clock_gettime(int clk_id, struct timespec *tp)
430 {
431 	struct timer_request request;
432 	FILETIME filetime;
433 	ULARGE_INTEGER rtime;
434 	DWORD r;
435 
436 	switch (clk_id) {
437 	case USBI_CLOCK_MONOTONIC:
438 		if (timer_thread) {
439 			request.tp = tp;
440 			request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
441 			if (request.event == NULL)
442 				return LIBUSB_ERROR_NO_MEM;
443 
444 			if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
445 				usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
446 				CloseHandle(request.event);
447 				return LIBUSB_ERROR_OTHER;
448 			}
449 
450 			do {
451 				r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
452 				if (r == WAIT_TIMEOUT)
453 					usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
454 				else if (r == WAIT_FAILED)
455 					usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
456 			} while (r == WAIT_TIMEOUT);
457 			CloseHandle(request.event);
458 
459 			if (r == WAIT_OBJECT_0)
460 				return LIBUSB_SUCCESS;
461 			else
462 				return LIBUSB_ERROR_OTHER;
463 		}
464 		// Fall through and return real-time if monotonic was not detected @ timer init
465 	case USBI_CLOCK_REALTIME:
466 		// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
467 		// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
468 		// Note however that our resolution is bounded by the Windows system time
469 		// functions and is at best of the order of 1 ms (or, usually, worse)
470 		GetSystemTimeAsFileTime(&filetime);
471 		rtime.LowPart = filetime.dwLowDateTime;
472 		rtime.HighPart = filetime.dwHighDateTime;
473 		rtime.QuadPart -= epoch_time;
474 		tp->tv_sec = (long)(rtime.QuadPart / 10000000);
475 		tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
476 		return LIBUSB_SUCCESS;
477 	default:
478 		return LIBUSB_ERROR_INVALID_PARAM;
479 	}
480 }
481 
windows_transfer_callback(struct usbi_transfer * itransfer,uint32_t io_result,uint32_t io_size)482 static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
483 {
484 	int status, istatus;
485 
486 	usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size);
487 
488 	switch (io_result) {
489 	case NO_ERROR:
490 		status = windows_copy_transfer_data(itransfer, io_size);
491 		break;
492 	case ERROR_GEN_FAILURE:
493 		usbi_dbg("detected endpoint stall");
494 		status = LIBUSB_TRANSFER_STALL;
495 		break;
496 	case ERROR_SEM_TIMEOUT:
497 		usbi_dbg("detected semaphore timeout");
498 		status = LIBUSB_TRANSFER_TIMED_OUT;
499 		break;
500 	case ERROR_OPERATION_ABORTED:
501 		istatus = windows_copy_transfer_data(itransfer, io_size);
502 		if (istatus != LIBUSB_TRANSFER_COMPLETED)
503 			usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
504 
505 		usbi_dbg("detected operation aborted");
506 		status = LIBUSB_TRANSFER_CANCELLED;
507 		break;
508 	default:
509 		usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result));
510 		status = LIBUSB_TRANSFER_ERROR;
511 		break;
512 	}
513 	windows_clear_transfer_priv(itransfer);	// Cancel polling
514 	if (status == LIBUSB_TRANSFER_CANCELLED)
515 		usbi_handle_transfer_cancellation(itransfer);
516 	else
517 		usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
518 }
519 
windows_handle_callback(struct usbi_transfer * itransfer,uint32_t io_result,uint32_t io_size)520 void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
521 {
522 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
523 
524 	switch (transfer->type) {
525 	case LIBUSB_TRANSFER_TYPE_CONTROL:
526 	case LIBUSB_TRANSFER_TYPE_BULK:
527 	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
528 	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
529 		windows_transfer_callback(itransfer, io_result, io_size);
530 		break;
531 	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
532 		usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
533 		break;
534 	default:
535 		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
536 	}
537 }
538 
windows_handle_events(struct libusb_context * ctx,struct pollfd * fds,POLL_NFDS_TYPE nfds,int num_ready)539 int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
540 {
541 	POLL_NFDS_TYPE i = 0;
542 	bool found = false;
543 	struct usbi_transfer *transfer;
544 	struct winfd *pollable_fd = NULL;
545 	DWORD io_size, io_result;
546 	int r = LIBUSB_SUCCESS;
547 
548 	usbi_mutex_lock(&ctx->open_devs_lock);
549 	for (i = 0; i < nfds && num_ready > 0; i++) {
550 
551 		usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
552 
553 		if (!fds[i].revents)
554 			continue;
555 
556 		num_ready--;
557 
558 		// Because a Windows OVERLAPPED is used for poll emulation,
559 		// a pollable fd is created and stored with each transfer
560 		usbi_mutex_lock(&ctx->flying_transfers_lock);
561 		found = false;
562 		list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
563 			pollable_fd = windows_get_fd(transfer);
564 			if (pollable_fd->fd == fds[i].fd) {
565 				found = true;
566 				break;
567 			}
568 		}
569 		usbi_mutex_unlock(&ctx->flying_transfers_lock);
570 
571 		if (found) {
572 			windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size);
573 
574 			usbi_remove_pollfd(ctx, pollable_fd->fd);
575 			// let handle_callback free the event using the transfer wfd
576 			// If you don't use the transfer wfd, you run a risk of trying to free a
577 			// newly allocated wfd that took the place of the one from the transfer.
578 			windows_handle_callback(transfer, io_result, io_size);
579 		} else {
580 			usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
581 			r = LIBUSB_ERROR_NOT_FOUND;
582 			break;
583 		}
584 	}
585 	usbi_mutex_unlock(&ctx->open_devs_lock);
586 
587 	return r;
588 }
589 
windows_common_init(struct libusb_context * ctx)590 int windows_common_init(struct libusb_context *ctx)
591 {
592 	if (!windows_init_clock(ctx))
593 		goto error_roll_back;
594 
595 	if (!htab_create(ctx, HTAB_SIZE))
596 		goto error_roll_back;
597 
598 	return LIBUSB_SUCCESS;
599 
600 error_roll_back:
601 	windows_common_exit();
602 	return LIBUSB_ERROR_NO_MEM;
603 }
604 
windows_common_exit(void)605 void windows_common_exit(void)
606 {
607 	htab_destroy();
608 	windows_destroy_clock();
609 	windows_exit_dlls();
610 }
611