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