Windows: Enable dynamic selection between WinUSB and UsbDk backends

This commit unifies the two Windows backends into a single project and
enables the user to switch to the UsbDk backend, if available, using the
libusb_set_option() function. All contexts will use the WinUSB backend
by default for backwards compatibility.

With this change, the UsbDk-specific projects are no longer required.

Closes #309

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
index b1b892d..e4da62e 100644
--- a/libusb/Makefile.am
+++ b/libusb/Makefile.am
@@ -13,10 +13,12 @@
 OPENBSD_USB_SRC = os/openbsd_usb.c
 NETBSD_USB_SRC = os/netbsd_usb.c
 SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
-WINDOWS_COMMON_SRC = os/windows_nt_common.h os/windows_nt_common.c \
-                     os/windows_common.h libusb-1.0.rc libusb-1.0.def
-WINDOWS_USB_SRC = os/windows_winusb.h os/windows_winusb.c
-WINDOWS_USBDK_SRC = os/windows_usbdk.h os/windows_usbdk.c
+WINDOWS_USB_SRC = libusb-1.0.def libusb-1.0.rc \
+		os/windows_common.h \
+		os/windows_nt_common.h os/windows_nt_common.c \
+		os/windows_nt_shared_types.h \
+		os/windows_usbdk.h os/windows_usbdk.c \
+		os/windows_winusb.h os/windows_winusb.c
 WINCE_USB_SRC = os/wince_usb.h os/wince_usb.c
 HAIKU_USB_SRC = os/haiku_usb.h os/haiku_usb_backend.cpp \
 		os/haiku_usb_raw.h os/haiku_usb_raw.cpp os/haiku_pollfs.cpp
@@ -25,8 +27,8 @@
 	$(WINDOWS_POLL_SRC) $(WINDOWS_THREADS_SRC) \
 	$(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) \
 	$(OPENBSD_USB_SRC) $(NETBSD_USB_SRC) \
-	$(WINDOWS_COMMON_SRC) $(WINDOWS_USB_SRC) $(WINDOWS_USBDK_SRC) \
-        $(WINCE_USB_SRC) $(HAIKU_USB_SRC) \
+	$(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
+	$(HAIKU_USB_SRC) \
 	os/linux_udev.c os/linux_netlink.c
 
 if OS_LINUX
@@ -63,12 +65,7 @@
 endif
 
 if OS_WINDOWS
-
-if USE_USBDK
-OS_SRC = $(WINDOWS_USBDK_SRC) $(WINDOWS_COMMON_SRC)
-else
-OS_SRC = $(WINDOWS_USB_SRC) $(WINDOWS_COMMON_SRC)
-endif
+OS_SRC = $(WINDOWS_USB_SRC)
 
 .rc.lo:
 	$(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) -i $< -o $@
diff --git a/libusb/core.c b/libusb/core.c
index 587a2d1..50f92f6 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -2065,19 +2065,15 @@
 			ctx->debug = (enum libusb_log_level)arg;
 #endif
 		break;
+
 	/* Handle all backend-specific options here */
-#if 0
-	/* This code is compiled out until the first backend-specific option is
-	 * added to the library. When this time comes, remove the #if/#endif
-	 * lines and this comment, then replace the case statement with the
-	 * valid option name. */
-	case LIBUSB_OPTION_<...>:
+	case LIBUSB_OPTION_USE_USBDK:
 		if (usbi_backend.set_option)
 			r = usbi_backend.set_option(ctx, option, ap);
 		else
 			r = LIBUSB_ERROR_NOT_SUPPORTED;
 		break;
-#endif
+
 	default:
 		r = LIBUSB_ERROR_INVALID_PARAM;
 	}
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 082e66f..e3755a0 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -2016,6 +2016,15 @@
 	 * does nothing: you'll always get messages from all levels.
 	 */
 	LIBUSB_OPTION_LOG_LEVEL,
+
+	/** Use the UsbDk backend for a specific context, if available.
+	 *
+	 * This option should be set immediately after calling libusb_init(), otherwise
+	 * unspecified behavior may occur.
+	 *
+	 * Only valid on Windows.
+	 */
+	LIBUSB_OPTION_USE_USBDK,
 };
 
 int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h
index 2650fb4..bd22c7f 100644
--- a/libusb/os/poll_windows.h
+++ b/libusb/os/poll_windows.h
@@ -41,21 +41,6 @@
 
 #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
 
-/* Windows versions */
-enum windows_version {
-	WINDOWS_CE = -2,
-	WINDOWS_UNDEFINED = -1,
-	WINDOWS_UNSUPPORTED = 0,
-	WINDOWS_XP = 0x51,
-	WINDOWS_2003 = 0x52,	// Also XP x64
-	WINDOWS_VISTA = 0x60,
-	WINDOWS_7 = 0x61,
-	WINDOWS_8 = 0x62,
-	WINDOWS_8_1_OR_LATER = 0x63,
-	WINDOWS_MAX
-};
-extern int windows_version;
-
 #define MAX_FDS     256
 
 #define POLLIN      0x0001    /* There is data to read */
diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c
index 29e6559..a0f35e9 100644
--- a/libusb/os/wince_usb.c
+++ b/libusb/os/wince_usb.c
@@ -32,7 +32,6 @@
 
 // Global variables
 int errno = 0;
-int windows_version = WINDOWS_CE;
 static uint64_t hires_frequency, hires_ticks_to_ps;
 static HANDLE driver_handle = INVALID_HANDLE_VALUE;
 static int concurrent_usage = -1;
@@ -110,7 +109,7 @@
 	}
 }
 
-static int init_dllimports(void)
+static BOOL init_dllimports(void)
 {
 	DLL_GET_HANDLE(ceusbkwrapper);
 	DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE);
@@ -136,7 +135,7 @@
 	DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE);
 	DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE);
 
-	return LIBUSB_SUCCESS;
+	return TRUE;
 }
 
 static void exit_dllimports(void)
@@ -188,7 +187,7 @@
 	// exit calls. If init is called more than exit, we will not exit properly
 	if ( ++concurrent_usage == 0 ) {	// First init?
 		// Load DLL imports
-		if (init_dllimports() != LIBUSB_SUCCESS) {
+		if (!init_dllimports()) {
 			usbi_err(ctx, "could not resolve DLL functions");
 			r = LIBUSB_ERROR_NOT_SUPPORTED;
 			goto init_exit;
diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h
index cde5924..b1725c2 100644
--- a/libusb/os/windows_common.h
+++ b/libusb/os/windows_common.h
@@ -68,21 +68,23 @@
 /*
  * Macros for handling DLL themselves
  */
+#define DLL_HANDLE_NAME(name) __dll_##name##_handle
+
 #define DLL_DECLARE_HANDLE(name)				\
-	static HMODULE __dll_##name##_handle = NULL
+	static HMODULE DLL_HANDLE_NAME(name) = NULL
 
 #define DLL_GET_HANDLE(name)					\
 	do {							\
-		__dll_##name##_handle = DLL_LOAD_LIBRARY(name);	\
-		if (!__dll_##name##_handle)			\
-			return LIBUSB_ERROR_NOT_FOUND;		\
+		DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name);	\
+		if (!DLL_HANDLE_NAME(name))			\
+			return FALSE;				\
 	} while (0)
 
 #define DLL_FREE_HANDLE(name)					\
 	do {							\
-		if (__dll_##name##_handle) {			\
-			FreeLibrary(__dll_##name##_handle);	\
-			__dll_##name##_handle = NULL;		\
+		if (DLL_HANDLE_NAME(name)) {			\
+			FreeLibrary(DLL_HANDLE_NAME(name));	\
+			DLL_HANDLE_NAME(name) = NULL;		\
 		}						\
 	} while (0)
 
@@ -90,9 +92,11 @@
 /*
  * Macros for handling functions within a DLL
  */
+#define DLL_FUNC_NAME(name) __dll_##name##_func_t
+
 #define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args)	\
-	typedef ret (api * __dll_##name##_func_t)args;			\
-	static __dll_##name##_func_t prefixname = NULL
+	typedef ret (api * DLL_FUNC_NAME(name))args;			\
+	static DLL_FUNC_NAME(name) prefixname = NULL
 
 #define DLL_DECLARE_FUNC(api, ret, name, args)				\
 	DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args)
@@ -101,21 +105,21 @@
 
 #define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure)	\
 	do {								\
-		HMODULE h = __dll_##dll##_handle;			\
-		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
+		HMODULE h = DLL_HANDLE_NAME(dll);			\
+		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
 				DLL_STRINGIFY(name));			\
 		if (prefixname)						\
 			break;						\
-		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
+		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
 				DLL_STRINGIFY(name) DLL_STRINGIFY(A));	\
 		if (prefixname)						\
 			break;						\
-		prefixname = (__dll_##name##_func_t)GetProcAddress(h,	\
+		prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h,	\
 				DLL_STRINGIFY(name) DLL_STRINGIFY(W));	\
 		if (prefixname)						\
 			break;						\
 		if (ret_on_failure)					\
-			return LIBUSB_ERROR_NOT_FOUND;			\
+			return FALSE;					\
 	} while (0)
 
 #define DLL_LOAD_FUNC(dll, name, ret_on_failure)			\
diff --git a/libusb/os/windows_nt_common.c b/libusb/os/windows_nt_common.c
index 900eace..ad17678 100644
--- a/libusb/os/windows_nt_common.c
+++ b/libusb/os/windows_nt_common.c
@@ -34,6 +34,11 @@
 
 // Public
 BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED);
+enum windows_version windows_version = WINDOWS_UNDEFINED;
+
+ // Global variables for init/exit
+static unsigned int init_count = 0;
+static bool usbdk_available = false;
 
 // Global variables for clock_gettime mechanism
 static uint64_t hires_ticks_to_ps;
@@ -53,6 +58,11 @@
 static HANDLE timer_thread = NULL;
 static DWORD timer_thread_id = 0;
 
+/* Kernel32 dependencies */
+DLL_DECLARE_HANDLE(Kernel32);
+/* This call is only available from XP SP2 */
+DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL));
+
 /* User32 dependencies */
 DLL_DECLARE_HANDLE(User32);
 DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT));
@@ -114,6 +124,11 @@
 }
 #endif
 
+static inline struct windows_context_priv *_context_priv(struct libusb_context *ctx)
+{
+	return (struct windows_context_priv *)ctx->os_priv;
+}
+
 /* Hash table functions - modified From glibc 2.3.2:
    [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
    [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
@@ -259,15 +274,22 @@
 	return idx;
 }
 
-static int windows_init_dlls(void)
+/*
+* Make a transfer complete synchronously
+*/
+void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size)
 {
-	HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
+	overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+	overlapped->InternalHigh = size;
+	SetEvent(overlapped->hEvent);
+}
 
-	if (hKernel32 == NULL)
-		return LIBUSB_ERROR_NOT_FOUND;
-
+static BOOL windows_init_dlls(void)
+{
+	DLL_GET_HANDLE(Kernel32);
+	DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE);
 	pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED))
-		GetProcAddress(hKernel32, "CancelIoEx");
+		GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx");
 	usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : "");
 
 	DLL_GET_HANDLE(User32);
@@ -275,28 +297,23 @@
 	DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE);
 	DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE);
 
-	return LIBUSB_SUCCESS;
+	return TRUE;
 }
 
 static void windows_exit_dlls(void)
 {
+	DLL_FREE_HANDLE(Kernel32);
 	DLL_FREE_HANDLE(User32);
 }
 
 static bool windows_init_clock(struct libusb_context *ctx)
 {
 	DWORD_PTR affinity, dummy;
-	HANDLE event = NULL;
+	HANDLE event;
 	LARGE_INTEGER li_frequency;
 	int i;
 
 	if (QueryPerformanceFrequency(&li_frequency)) {
-		// Load DLL imports
-		if (windows_init_dlls() != LIBUSB_SUCCESS) {
-			usbi_err(ctx, "could not resolve DLL functions");
-			return false;
-		}
-
 		// The hires frequency can go as high as 4 GHz, so we'll use a conversion
 		// to picoseconds to compute the tv_nsecs part in clock_gettime
 		hires_frequency = li_frequency.QuadPart;
@@ -352,7 +369,7 @@
 	return true;
 }
 
-void windows_destroy_clock(void)
+static void windows_destroy_clock(void)
 {
 	if (timer_thread) {
 		// actually the signal to quit the thread.
@@ -369,6 +386,110 @@
 	}
 }
 
+/* Windows version detection */
+static BOOL is_x64(void)
+{
+	BOOL ret = FALSE;
+
+	// Detect if we're running a 32 or 64 bit system
+	if (sizeof(uintptr_t) < 8) {
+		if (pIsWow64Process != NULL)
+			pIsWow64Process(GetCurrentProcess(), &ret);
+	} else {
+		ret = TRUE;
+	}
+
+	return ret;
+}
+
+static void get_windows_version(void)
+{
+	OSVERSIONINFOEXA vi, vi2;
+	const char *arch, *w = NULL;
+	unsigned major, minor, version;
+	ULONGLONG major_equal, minor_equal;
+	BOOL ws;
+
+	windows_version = WINDOWS_UNDEFINED;
+
+	memset(&vi, 0, sizeof(vi));
+	vi.dwOSVersionInfoSize = sizeof(vi);
+	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
+		memset(&vi, 0, sizeof(vi));
+		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
+		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
+			return;
+	}
+
+	if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
+		return;
+
+	if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
+		// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
+		// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
+
+		major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
+		for (major = vi.dwMajorVersion; major <= 9; major++) {
+			memset(&vi2, 0, sizeof(vi2));
+			vi2.dwOSVersionInfoSize = sizeof(vi2);
+			vi2.dwMajorVersion = major;
+			if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
+				continue;
+
+			if (vi.dwMajorVersion < major) {
+				vi.dwMajorVersion = major;
+				vi.dwMinorVersion = 0;
+			}
+
+			minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
+			for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
+				memset(&vi2, 0, sizeof(vi2));
+				vi2.dwOSVersionInfoSize = sizeof(vi2);
+				vi2.dwMinorVersion = minor;
+				if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
+					continue;
+
+				vi.dwMinorVersion = minor;
+				break;
+			}
+
+			break;
+		}
+	}
+
+	if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
+		return;
+
+	ws = (vi.wProductType <= VER_NT_WORKSTATION);
+	version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
+	switch (version) {
+	case 0x50: windows_version = WINDOWS_2000;  w = "2000";	break;
+	case 0x51: windows_version = WINDOWS_XP;    w = "XP";	break;
+	case 0x52: windows_version = WINDOWS_2003;  w = "2003";	break;
+	case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008");  break;
+	case 0x61: windows_version = WINDOWS_7;	    w = (ws ? "7" : "2008_R2");	  break;
+	case 0x62: windows_version = WINDOWS_8;	    w = (ws ? "8" : "2012");	  break;
+	case 0x63: windows_version = WINDOWS_8_1;   w = (ws ? "8.1" : "2012_R2"); break;
+	case 0x64: windows_version = WINDOWS_10;    w = (ws ? "10" : "2016");	  break;
+	default:
+		if (version < 0x50) {
+			return;
+		} else {
+			windows_version = WINDOWS_11_OR_LATER;
+			w = "11 or later";
+		}
+	}
+
+	arch = is_x64() ? "64-bit" : "32-bit";
+
+	if (vi.wServicePackMinor)
+		usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
+	else if (vi.wServicePackMajor)
+		usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
+	else
+		usbi_dbg("Windows %s %s", w, arch);
+}
+
 /*
 * Monotonic and real time functions
 */
@@ -413,7 +534,378 @@
 	}
 }
 
-int windows_clock_gettime(int clk_id, struct timespec *tp)
+static void windows_transfer_callback(const struct windows_backend *backend,
+	struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
+{
+	int status, istatus;
+
+	usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size);
+
+	switch (io_result) {
+	case NO_ERROR:
+		status = backend->copy_transfer_data(itransfer, (uint32_t)io_size);
+		break;
+	case ERROR_GEN_FAILURE:
+		usbi_dbg("detected endpoint stall");
+		status = LIBUSB_TRANSFER_STALL;
+		break;
+	case ERROR_SEM_TIMEOUT:
+		usbi_dbg("detected semaphore timeout");
+		status = LIBUSB_TRANSFER_TIMED_OUT;
+		break;
+	case ERROR_OPERATION_ABORTED:
+		istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size);
+		if (istatus != LIBUSB_TRANSFER_COMPLETED)
+			usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
+
+		usbi_dbg("detected operation aborted");
+		status = LIBUSB_TRANSFER_CANCELLED;
+		break;
+	case ERROR_FILE_NOT_FOUND:
+		usbi_dbg("detected device removed");
+		status = LIBUSB_TRANSFER_NO_DEVICE;
+		break;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result));
+		status = LIBUSB_TRANSFER_ERROR;
+		break;
+	}
+	backend->clear_transfer_priv(itransfer);	// Cancel polling
+	if (status == LIBUSB_TRANSFER_CANCELLED)
+		usbi_handle_transfer_cancellation(itransfer);
+	else
+		usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
+}
+
+static void windows_handle_callback(const struct windows_backend *backend,
+	struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+
+	switch (transfer->type) {
+	case LIBUSB_TRANSFER_TYPE_CONTROL:
+	case LIBUSB_TRANSFER_TYPE_BULK:
+	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+		windows_transfer_callback(backend, itransfer, io_result, io_size);
+		break;
+	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+		usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
+		break;
+	default:
+		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
+	}
+}
+
+static int windows_init(struct libusb_context *ctx)
+{
+	struct windows_context_priv *priv = _context_priv(ctx);
+	HANDLE semaphore;
+	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+	int r = LIBUSB_ERROR_OTHER;
+	bool winusb_backend_init = false;
+
+	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
+	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
+	if (semaphore == NULL) {
+		usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	// A successful wait brings our semaphore count to 0 (unsignaled)
+	// => any concurent wait stalls until the semaphore's release
+	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
+		usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
+		CloseHandle(semaphore);
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	// NB: concurrent usage supposes that init calls are equally balanced with
+	// exit calls. If init is called more than exit, we will not exit properly
+	if (++init_count == 1) { // First init?
+		// Load DLL imports
+		if (!windows_init_dlls()) {
+			usbi_err(ctx, "could not resolve DLL functions");
+			goto init_exit;
+		}
+
+		get_windows_version();
+
+		if (windows_version == WINDOWS_UNDEFINED) {
+			usbi_err(ctx, "failed to detect Windows version");
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+			goto init_exit;
+		}
+
+		if (!windows_init_clock(ctx))
+			goto init_exit;
+
+		if (!htab_create(ctx))
+			goto init_exit;
+
+		r = winusb_backend.init(ctx);
+		if (r != LIBUSB_SUCCESS)
+			goto init_exit;
+		winusb_backend_init = true;
+
+		r = usbdk_backend.init(ctx);
+		if (r == LIBUSB_SUCCESS) {
+			usbi_dbg("UsbDk backend is available");
+			usbdk_available = true;
+		} else {
+			usbi_info(ctx, "UsbDk backend is not available");
+			// Do not report this as an error
+			r = LIBUSB_SUCCESS;
+		}
+	}
+
+	// By default, new contexts will use the WinUSB backend
+	priv->backend = &winusb_backend;
+
+	r = LIBUSB_SUCCESS;
+
+init_exit: // Holds semaphore here
+	if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
+		if (winusb_backend_init)
+			winusb_backend.exit(ctx);
+		htab_destroy();
+		windows_destroy_clock();
+		windows_exit_dlls();
+		--init_count;
+	}
+
+	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
+	CloseHandle(semaphore);
+	return r;
+}
+
+static void windows_exit(struct libusb_context *ctx)
+{
+	HANDLE semaphore;
+	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+	UNUSED(ctx);
+
+	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
+	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
+	if (semaphore == NULL)
+		return;
+
+	// A successful wait brings our semaphore count to 0 (unsignaled)
+	// => any concurent wait stalls until the semaphore release
+	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
+		CloseHandle(semaphore);
+		return;
+	}
+
+	// Only works if exits and inits are balanced exactly
+	if (--init_count == 0) { // Last exit
+		if (usbdk_available) {
+			usbdk_backend.exit(ctx);
+			usbdk_available = false;
+		}
+		winusb_backend.exit(ctx);
+		htab_destroy();
+		windows_destroy_clock();
+		windows_exit_dlls();
+	}
+
+	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
+	CloseHandle(semaphore);
+}
+
+static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
+{
+	struct windows_context_priv *priv = _context_priv(ctx);
+
+	UNUSED(ap);
+
+	switch (option) {
+	case LIBUSB_OPTION_USE_USBDK:
+		if (usbdk_available) {
+			usbi_dbg("switching context %p to use UsbDk backend", ctx);
+			priv->backend = &usbdk_backend;
+		} else {
+			usbi_err(ctx, "UsbDk backend not available");
+			return LIBUSB_ERROR_NOT_FOUND;
+		}
+		return LIBUSB_SUCCESS;
+	}
+
+	return LIBUSB_ERROR_NOT_SUPPORTED;
+}
+
+static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
+{
+	struct windows_context_priv *priv = _context_priv(ctx);
+	return priv->backend->get_device_list(ctx, discdevs);
+}
+
+static int windows_open(struct libusb_device_handle *dev_handle)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->open(dev_handle);
+}
+
+static void windows_close(struct libusb_device_handle *dev_handle)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	priv->backend->close(dev_handle);
+}
+
+static int windows_get_device_descriptor(struct libusb_device *dev,
+	unsigned char *buffer, int *host_endian)
+{
+	struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
+	*host_endian = 0;
+	return priv->backend->get_device_descriptor(dev, buffer);
+}
+
+static int windows_get_active_config_descriptor(struct libusb_device *dev,
+	unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
+	*host_endian = 0;
+	return priv->backend->get_active_config_descriptor(dev, buffer, len);
+}
+
+static int windows_get_config_descriptor(struct libusb_device *dev,
+	uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
+{
+	struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
+	*host_endian = 0;
+	return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
+}
+
+static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
+	uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian)
+{
+	struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
+	*host_endian = 0;
+	return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
+}
+
+static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->get_configuration(dev_handle, config);
+}
+
+static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->set_configuration(dev_handle, config);
+}
+
+static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->claim_interface(dev_handle, interface_number);
+}
+
+static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->release_interface(dev_handle, interface_number);
+}
+
+static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
+	int interface_number, int altsetting)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
+}
+
+static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->clear_halt(dev_handle, endpoint);
+}
+
+static int windows_reset_device(struct libusb_device_handle *dev_handle)
+{
+	struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
+	return priv->backend->reset_device(dev_handle);
+}
+
+static void windows_destroy_device(struct libusb_device *dev)
+{
+	struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
+	priv->backend->destroy_device(dev);
+}
+
+static int windows_submit_transfer(struct usbi_transfer *itransfer)
+{
+	struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
+	return priv->backend->submit_transfer(itransfer);
+}
+
+static int windows_cancel_transfer(struct usbi_transfer *itransfer)
+{
+	struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
+	return priv->backend->cancel_transfer(itransfer);
+}
+
+static void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
+{
+	struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
+	priv->backend->clear_transfer_priv(itransfer);
+}
+
+static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
+{
+	struct windows_context_priv *priv = _context_priv(ctx);
+	struct usbi_transfer *itransfer;
+	DWORD io_size, io_result;
+	POLL_NFDS_TYPE i;
+	bool found;
+	int transfer_fd;
+	int r = LIBUSB_SUCCESS;
+
+	usbi_mutex_lock(&ctx->open_devs_lock);
+	for (i = 0; i < nfds && num_ready > 0; i++) {
+
+		usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
+
+		if (!fds[i].revents)
+			continue;
+
+		num_ready--;
+
+		// Because a Windows OVERLAPPED is used for poll emulation,
+		// a pollable fd is created and stored with each transfer
+		found = false;
+		transfer_fd = -1;
+		usbi_mutex_lock(&ctx->flying_transfers_lock);
+		list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+			transfer_fd = priv->backend->get_transfer_fd(itransfer);
+			if (transfer_fd == fds[i].fd) {
+				found = true;
+				break;
+			}
+		}
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
+		if (found) {
+			priv->backend->get_overlapped_result(itransfer, &io_result, &io_size);
+
+			usbi_remove_pollfd(ctx, transfer_fd);
+
+			// let handle_callback free the event using the transfer wfd
+			// If you don't use the transfer wfd, you run a risk of trying to free a
+			// newly allocated wfd that took the place of the one from the transfer.
+			windows_handle_callback(priv->backend, itransfer, io_result, io_size);
+		} else {
+			usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd);
+			r = LIBUSB_ERROR_NOT_FOUND;
+			break;
+		}
+	}
+	usbi_mutex_unlock(&ctx->open_devs_lock);
+
+	return r;
+}
+
+static int windows_clock_gettime(int clk_id, struct timespec *tp)
 {
 	struct timer_request request;
 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
@@ -472,147 +964,44 @@
 	}
 }
 
-static void windows_transfer_callback(struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
-{
-	int status, istatus;
-
-	usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size);
-
-	switch (io_result) {
-	case NO_ERROR:
-		status = windows_copy_transfer_data(itransfer, (uint32_t)io_size);
-		break;
-	case ERROR_GEN_FAILURE:
-		usbi_dbg("detected endpoint stall");
-		status = LIBUSB_TRANSFER_STALL;
-		break;
-	case ERROR_SEM_TIMEOUT:
-		usbi_dbg("detected semaphore timeout");
-		status = LIBUSB_TRANSFER_TIMED_OUT;
-		break;
-	case ERROR_OPERATION_ABORTED:
-		istatus = windows_copy_transfer_data(itransfer, (uint32_t)io_size);
-		if (istatus != LIBUSB_TRANSFER_COMPLETED)
-			usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
-
-		usbi_dbg("detected operation aborted");
-		status = LIBUSB_TRANSFER_CANCELLED;
-		break;
-	case ERROR_FILE_NOT_FOUND:
-		usbi_dbg("detected device removed");
-		status = LIBUSB_TRANSFER_NO_DEVICE;
-		break;
-	default:
-		usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result));
-		status = LIBUSB_TRANSFER_ERROR;
-		break;
-	}
-	windows_clear_transfer_priv(itransfer);	// Cancel polling
-	if (status == LIBUSB_TRANSFER_CANCELLED)
-		usbi_handle_transfer_cancellation(itransfer);
-	else
-		usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
-}
-
-/*
-* Make a transfer complete synchronously
-*/
-void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size)
-{
-	overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
-	overlapped->InternalHigh = size;
-	SetEvent(overlapped->hEvent);
-}
-
-void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
-	switch (transfer->type) {
-	case LIBUSB_TRANSFER_TYPE_CONTROL:
-	case LIBUSB_TRANSFER_TYPE_BULK:
-	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
-	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
-		windows_transfer_callback(itransfer, io_result, io_size);
-		break;
-	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
-		usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
-		break;
-	default:
-		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
-	}
-}
-
-int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
-{
-	struct usbi_transfer *itransfer;
-	DWORD io_size, io_result;
-	POLL_NFDS_TYPE i;
-	bool found;
-	int transfer_fd = -1;
-	int r = LIBUSB_SUCCESS;
-
-	usbi_mutex_lock(&ctx->open_devs_lock);
-	for (i = 0; i < nfds && num_ready > 0; i++) {
-
-		usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
-
-		if (!fds[i].revents)
-			continue;
-
-		num_ready--;
-
-		// Because a Windows OVERLAPPED is used for poll emulation,
-		// a pollable fd is created and stored with each transfer
-		found = false;
-		usbi_mutex_lock(&ctx->flying_transfers_lock);
-		list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
-			transfer_fd = windows_get_transfer_fd(itransfer);
-			if (transfer_fd == fds[i].fd) {
-				found = true;
-				break;
-			}
-		}
-		usbi_mutex_unlock(&ctx->flying_transfers_lock);
-
-		if (found) {
-			windows_get_overlapped_result(itransfer, &io_result, &io_size);
-
-			usbi_remove_pollfd(ctx, transfer_fd);
-
-			// let handle_callback free the event using the transfer wfd
-			// If you don't use the transfer wfd, you run a risk of trying to free a
-			// newly allocated wfd that took the place of the one from the transfer.
-			windows_handle_callback(itransfer, io_result, io_size);
-		} else {
-			usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
-			r = LIBUSB_ERROR_NOT_FOUND;
-			break;
-		}
-	}
-	usbi_mutex_unlock(&ctx->open_devs_lock);
-
-	return r;
-}
-
-int windows_common_init(struct libusb_context *ctx)
-{
-	if (!windows_init_clock(ctx))
-		goto error_roll_back;
-
-	if (!htab_create(ctx))
-		goto error_roll_back;
-
-	return LIBUSB_SUCCESS;
-
-error_roll_back:
-	windows_common_exit();
-	return LIBUSB_ERROR_NO_MEM;
-}
-
-void windows_common_exit(void)
-{
-	htab_destroy();
-	windows_destroy_clock();
-	windows_exit_dlls();
-}
+// NB: MSVC6 does not support named initializers.
+const struct usbi_os_backend usbi_backend = {
+	"Windows",
+	USBI_CAP_HAS_HID_ACCESS,
+	windows_init,
+	windows_exit,
+	windows_set_option,
+	windows_get_device_list,
+	NULL,	/* hotplug_poll */
+	windows_open,
+	windows_close,
+	windows_get_device_descriptor,
+	windows_get_active_config_descriptor,
+	windows_get_config_descriptor,
+	windows_get_config_descriptor_by_value,
+	windows_get_configuration,
+	windows_set_configuration,
+	windows_claim_interface,
+	windows_release_interface,
+	windows_set_interface_altsetting,
+	windows_clear_halt,
+	windows_reset_device,
+	NULL,	/* alloc_streams */
+	NULL,	/* free_streams */
+	NULL,	/* dev_mem_alloc */
+	NULL,	/* dev_mem_free */
+	NULL,	/* kernel_driver_active */
+	NULL,	/* detach_kernel_driver */
+	NULL,	/* attach_kernel_driver */
+	windows_destroy_device,
+	windows_submit_transfer,
+	windows_cancel_transfer,
+	windows_clear_transfer_priv,
+	windows_handle_events,
+	NULL,	/* handle_transfer_completion */
+	windows_clock_gettime,
+	sizeof(struct windows_context_priv),
+	sizeof(union windows_device_priv),
+	sizeof(union windows_device_handle_priv),
+	sizeof(union windows_transfer_priv),
+};
diff --git a/libusb/os/windows_nt_common.h b/libusb/os/windows_nt_common.h
index d3ac6bc..e155b5d 100644
--- a/libusb/os/windows_nt_common.h
+++ b/libusb/os/windows_nt_common.h
@@ -26,45 +26,84 @@
 
 #pragma once
 
-// Missing from MinGW
-#if !defined(FACILITY_SETUPAPI)
-#define FACILITY_SETUPAPI	15
-#endif
+#include "windows_nt_shared_types.h"
 
-#include <pshpack1.h>
+ /* Windows versions */
+enum windows_version {
+	WINDOWS_UNDEFINED,
+	WINDOWS_2000,
+	WINDOWS_XP,
+	WINDOWS_2003,	// Also XP x64
+	WINDOWS_VISTA,
+	WINDOWS_7,
+	WINDOWS_8,
+	WINDOWS_8_1,
+	WINDOWS_10,
+	WINDOWS_11_OR_LATER
+};
 
-typedef struct USB_CONFIGURATION_DESCRIPTOR {
-  UCHAR  bLength;
-  UCHAR  bDescriptorType;
-  USHORT wTotalLength;
-  UCHAR  bNumInterfaces;
-  UCHAR  bConfigurationValue;
-  UCHAR  iConfiguration;
-  UCHAR  bmAttributes;
-  UCHAR  MaxPower;
-} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
-
-#include <poppack.h>
-
-typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
+extern enum windows_version windows_version;
 
 /* This call is only available from Vista */
 extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED);
 
-int windows_common_init(struct libusb_context *ctx);
-void windows_common_exit(void);
+struct windows_backend {
+	int (*init)(struct libusb_context *ctx);
+	void (*exit)(struct libusb_context *ctx);
+	int (*get_device_list)(struct libusb_context *ctx,
+		struct discovered_devs **discdevs);
+	int (*open)(struct libusb_device_handle *dev_handle);
+	void (*close)(struct libusb_device_handle *dev_handle);
+	int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer);
+	int (*get_active_config_descriptor)(struct libusb_device *device,
+		unsigned char *buffer, size_t len);
+	int (*get_config_descriptor)(struct libusb_device *device,
+		uint8_t config_index, unsigned char *buffer, size_t len);
+	int (*get_config_descriptor_by_value)(struct libusb_device *device,
+		uint8_t bConfigurationValue, unsigned char **buffer);
+	int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config);
+	int (*set_configuration)(struct libusb_device_handle *dev_handle, int config);
+	int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number);
+	int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number);
+	int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
+		int interface_number, int altsetting);
+	int (*clear_halt)(struct libusb_device_handle *dev_handle,
+		unsigned char endpoint);
+	int (*reset_device)(struct libusb_device_handle *dev_handle);
+	void (*destroy_device)(struct libusb_device *dev);
+	int (*submit_transfer)(struct usbi_transfer *itransfer);
+	int (*cancel_transfer)(struct usbi_transfer *itransfer);
+	void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
+	int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size);
+	int (*get_transfer_fd)(struct usbi_transfer *itransfer);
+	void (*get_overlapped_result)(struct usbi_transfer *itransfer,
+		DWORD *io_result, DWORD *io_size);
+};
+
+struct windows_context_priv {
+	const struct windows_backend *backend;
+};
+
+union windows_device_priv {
+	struct usbdk_device_priv usbdk_priv;
+	struct winusb_device_priv winusb_priv;
+};
+
+union windows_device_handle_priv {
+	struct usbdk_device_handle_priv usbdk_priv;
+	struct winusb_device_handle_priv winusb_priv;
+};
+
+union windows_transfer_priv {
+	struct usbdk_transfer_priv usbdk_priv;
+	struct winusb_transfer_priv winusb_priv;
+};
+
+extern const struct windows_backend usbdk_backend;
+extern const struct windows_backend winusb_backend;
 
 unsigned long htab_hash(const char *str);
-int windows_clock_gettime(int clk_id, struct timespec *tp);
-
-void windows_clear_transfer_priv(struct usbi_transfer *itransfer);
-int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size);
-int windows_get_transfer_fd(struct usbi_transfer *itransfer);
-void windows_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size);
-
 void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size);
-void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size);
-int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
 
 #if defined(ENABLE_LOGGING)
 const char *windows_error_str(DWORD error_code);
diff --git a/libusb/os/windows_nt_shared_types.h b/libusb/os/windows_nt_shared_types.h
new file mode 100644
index 0000000..1f5cfbd
--- /dev/null
+++ b/libusb/os/windows_nt_shared_types.h
@@ -0,0 +1,137 @@
+#pragma once
+
+#include "windows_common.h"
+
+#include <pshpack1.h>
+
+typedef struct USB_DEVICE_DESCRIPTOR {
+	UCHAR  bLength;
+	UCHAR  bDescriptorType;
+	USHORT bcdUSB;
+	UCHAR  bDeviceClass;
+	UCHAR  bDeviceSubClass;
+	UCHAR  bDeviceProtocol;
+	UCHAR  bMaxPacketSize0;
+	USHORT idVendor;
+	USHORT idProduct;
+	USHORT bcdDevice;
+	UCHAR  iManufacturer;
+	UCHAR  iProduct;
+	UCHAR  iSerialNumber;
+	UCHAR  bNumConfigurations;
+} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
+
+typedef struct USB_CONFIGURATION_DESCRIPTOR {
+	UCHAR  bLength;
+	UCHAR  bDescriptorType;
+	USHORT wTotalLength;
+	UCHAR  bNumInterfaces;
+	UCHAR  bConfigurationValue;
+	UCHAR  iConfiguration;
+	UCHAR  bmAttributes;
+	UCHAR  MaxPower;
+} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
+
+#include <poppack.h>
+
+#define MAX_DEVICE_ID_LEN	200
+
+typedef struct USB_DK_DEVICE_ID {
+	WCHAR DeviceID[MAX_DEVICE_ID_LEN];
+	WCHAR InstanceID[MAX_DEVICE_ID_LEN];
+} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
+
+typedef struct USB_DK_DEVICE_INFO {
+	USB_DK_DEVICE_ID ID;
+	ULONG64 FilterID;
+	ULONG64 Port;
+	ULONG64 Speed;
+	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
+
+typedef struct USB_DK_ISO_TRANSFER_RESULT {
+	ULONG64 ActualLength;
+	ULONG64 TransferResult;
+} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;
+
+typedef struct USB_DK_GEN_TRANSFER_RESULT {
+	ULONG64 BytesTransferred;
+	ULONG64 UsbdStatus; // USBD_STATUS code
+} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;
+
+typedef struct USB_DK_TRANSFER_RESULT {
+	USB_DK_GEN_TRANSFER_RESULT GenResult;
+	PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
+} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;
+
+typedef struct USB_DK_TRANSFER_REQUEST {
+	ULONG64 EndpointAddress;
+	PVOID64 Buffer;
+	ULONG64 BufferLength;
+	ULONG64 TransferType;
+	ULONG64 IsochronousPacketsArraySize;
+	PVOID64 IsochronousPacketsArray;
+	USB_DK_TRANSFER_RESULT Result;
+} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
+
+struct usbdk_device_priv {
+	USB_DK_DEVICE_INFO info;
+	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
+	HANDLE redirector_handle;
+	HANDLE system_handle;
+	uint8_t active_configuration;
+};
+
+struct winusb_device_priv {
+	bool initialized;
+	bool root_hub;
+	uint8_t active_config;
+	uint8_t depth; // distance to HCD
+	const struct windows_usb_api_backend *apib;
+	char *dev_id;
+	char *path;  // device interface path
+	int sub_api; // for WinUSB-like APIs
+	struct {
+		char *path; // each interface needs a device interface path,
+		const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support),
+		int sub_api;
+		int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
+		uint8_t *endpoint;
+		bool restricted_functionality;  // indicates if the interface functionality is restricted
+						// by Windows (eg. HID keyboards or mice cannot do R/W)
+	} usb_interface[USB_MAXINTERFACES];
+	struct hid_device_priv *hid;
+	USB_DEVICE_DESCRIPTOR dev_descriptor;
+	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors
+};
+
+struct usbdk_device_handle_priv {
+	// Not currently used
+	char dummy;
+};
+
+struct winusb_device_handle_priv {
+	int active_interface;
+	struct {
+		HANDLE dev_handle; // WinUSB needs an extra handle for the file
+		HANDLE api_handle; // used by the API to communicate with the device
+	} interface_handle[USB_MAXINTERFACES];
+	int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
+};
+
+struct usbdk_transfer_priv {
+	USB_DK_TRANSFER_REQUEST request;
+	struct winfd pollable_fd;
+	HANDLE system_handle;
+	PULONG64 IsochronousPacketsArray;
+	PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
+};
+
+struct winusb_transfer_priv {
+	struct winfd pollable_fd;
+	HANDLE handle;
+	uint8_t interface_number;
+	uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
+	uint8_t *hid_dest;   // transfer buffer destination, required for HID
+	size_t hid_expected_size;
+};
diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c
index 5ace88b..089e2a5 100644
--- a/libusb/os/windows_usbdk.c
+++ b/libusb/os/windows_usbdk.c
@@ -23,19 +23,12 @@
 
 #include <config.h>
 
-#if defined(USE_USBDK)
-
 #include <windows.h>
-#include <cfgmgr32.h>
 #include <stdio.h>
 
 #include "libusbi.h"
 #include "windows_common.h"
 #include "windows_nt_common.h"
-
-typedef CONST WCHAR *PCWCHAR;
-#define wcsncpy_s wcsncpy
-
 #include "windows_usbdk.h"
 
 #if !defined(STATUS_SUCCESS)
@@ -63,24 +56,6 @@
 #define USBD_STATUS_CANCELED		((USBD_STATUS) 0xc0010000)
 #endif
 
-static int concurrent_usage = -1;
-
-struct usbdk_device_priv {
-	USB_DK_DEVICE_INFO info;
-	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
-	HANDLE redirector_handle;
-	HANDLE system_handle;
-	uint8_t active_configuration;
-};
-
-struct usbdk_transfer_priv {
-	USB_DK_TRANSFER_REQUEST request;
-	struct winfd pollable_fd;
-	HANDLE system_handle;
-	PULONG64 IsochronousPacketsArray;
-	PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
-};
-
 static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev)
 {
 	return (struct usbdk_device_priv *)dev->os_priv;
@@ -114,7 +89,7 @@
 	FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name);
 
 	if (api_ptr == NULL)
-		usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError());
+		usbi_err(ctx, "UsbDkHelper API %s not found: %s", api_name, windows_error_str(0));
 
 	return api_ptr;
 }
@@ -131,7 +106,7 @@
 {
 	usbdk_helper.module = LoadLibraryA("UsbDkHelper");
 	if (usbdk_helper.module == NULL) {
-		usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError());
+		usbi_err(ctx, "Failed to load UsbDkHelper.dll: %s", windows_error_str(0));
 		return LIBUSB_ERROR_NOT_FOUND;
 	}
 
@@ -197,30 +172,33 @@
 
 static int usbdk_init(struct libusb_context *ctx)
 {
-	int r;
+	SC_HANDLE managerHandle;
+	SC_HANDLE serviceHandle;
 
-	if (++concurrent_usage == 0) { // First init?
-		r = load_usbdk_helper_dll(ctx);
-		if (r)
-			goto init_exit;
-
-		r = windows_common_init(ctx);
-		if (r)
-			goto init_exit;
-	}
-	// At this stage, either we went through full init successfully, or didn't need to
-	r = LIBUSB_SUCCESS;
-
-init_exit:
-	if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
-		windows_common_exit();
-		unload_usbdk_helper_dll();
+	managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+	if (managerHandle == NULL) {
+		usbi_warn(ctx, "failed to open service control manager: %s", windows_error_str(0));
+		return LIBUSB_ERROR_OTHER;
 	}
 
-	if (r != LIBUSB_SUCCESS)
-		--concurrent_usage; // Not expected to call libusb_exit if we failed.
+	serviceHandle = OpenServiceA(managerHandle, "UsbDk", GENERIC_READ);
+	CloseServiceHandle(managerHandle);
 
-	return r;
+	if (serviceHandle == NULL) {
+		if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
+			usbi_warn(ctx, "failed to open UsbDk service: %s", windows_error_str(0));
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	CloseServiceHandle(serviceHandle);
+
+	return load_usbdk_helper_dll(ctx);
+}
+
+static void usbdk_exit(struct libusb_context *ctx)
+{
+	UNUSED(ctx);
+	unload_usbdk_helper_dll();
 }
 
 static int usbdk_get_session_id_for_device(struct libusb_context *ctx,
@@ -296,7 +274,7 @@
 	dev->device_address = (uint8_t)(info->Port + 1);
 
 	dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
-	dev->device_descriptor = info->DeviceDescriptor;
+	memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
 
 	switch (info->Speed) {
 	case LowSpeed:
@@ -326,7 +304,7 @@
 	ULONG dev_number;
 	PUSB_DK_DEVICE_INFO devices;
 
-	if(!usbdk_helper.GetDevicesList(&devices, &dev_number))
+	if (!usbdk_helper.GetDevicesList(&devices, &dev_number))
 		return LIBUSB_ERROR_OTHER;
 
 	for (i = 0; i < dev_number; i++) {
@@ -367,26 +345,16 @@
 	return r;
 }
 
-static void usbdk_exit(struct libusb_context *ctx)
-{
-	UNUSED(ctx);
-	if (--concurrent_usage < 0) {
-		windows_common_exit();
-		unload_usbdk_helper_dll();
-	}
-}
-
-static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
+static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer)
 {
 	struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
 
 	memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH);
-	*host_endian = 0;
 
 	return LIBUSB_SUCCESS;
 }
 
-static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
+static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len)
 {
 	struct usbdk_device_priv *priv = _usbdk_device_priv(dev);
 	PUSB_CONFIGURATION_DESCRIPTOR config_header;
@@ -399,15 +367,13 @@
 
 	size = min(config_header->wTotalLength, len);
 	memcpy(buffer, config_header, size);
-	*host_endian = 0;
-
 	return (int)size;
 }
 
-static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
+static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len)
 {
 	return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration,
-			buffer, len, host_endian);
+			buffer, len);
 }
 
 static int usbdk_open(struct libusb_device_handle *dev_handle)
@@ -508,7 +474,7 @@
 		usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations);
 }
 
-void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
+static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer)
 {
 	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@@ -678,7 +644,7 @@
 	r = transfer_fn(itransfer);
 	if (r != LIBUSB_SUCCESS) {
 		usbi_remove_pollfd(ctx, wfd.fd);
-		windows_clear_transfer_priv(itransfer);
+		usbdk_clear_transfer_priv(itransfer);
 		return r;
 	}
 
@@ -758,13 +724,13 @@
 	}
 }
 
-int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
+static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
 {
 	itransfer->transferred += io_size;
 	return LIBUSB_TRANSFER_COMPLETED;
 }
 
-int windows_get_transfer_fd(struct usbi_transfer *itransfer)
+static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer)
 {
 	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
 	return transfer_priv->pollable_fd.fd;
@@ -785,7 +751,7 @@
 	}
 }
 
-void windows_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size)
+static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size)
 {
 	struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
 	struct winfd *pollable_fd = &transfer_priv->pollable_fd;
@@ -821,57 +787,28 @@
 	}
 }
 
-const struct usbi_os_backend usbi_backend = {
-	"Windows",
-	USBI_CAP_HAS_HID_ACCESS,
+const struct windows_backend usbdk_backend = {
 	usbdk_init,
 	usbdk_exit,
-	NULL,	// set_option()
-
 	usbdk_get_device_list,
-	NULL,
 	usbdk_open,
 	usbdk_close,
-
 	usbdk_get_device_descriptor,
 	usbdk_get_active_config_descriptor,
 	usbdk_get_config_descriptor,
-	NULL,
-
+	NULL,//usbdk_get_config_descriptor_by_value,
 	usbdk_get_configuration,
 	usbdk_set_configuration,
 	usbdk_claim_interface,
 	usbdk_release_interface,
-
 	usbdk_set_interface_altsetting,
 	usbdk_clear_halt,
 	usbdk_reset_device,
-
-	NULL,
-	NULL,
-
-	NULL,	// dev_mem_alloc()
-	NULL,	// dev_mem_free()
-
-	NULL,	// kernel_driver_active()
-	NULL,	// detach_kernel_driver()
-	NULL,	// attach_kernel_driver()
-
 	usbdk_destroy_device,
-
 	usbdk_submit_transfer,
 	usbdk_cancel_transfer,
-	windows_clear_transfer_priv,
-
-	windows_handle_events,
-	NULL,
-
-	windows_clock_gettime,
-
-	0,
-	sizeof(struct usbdk_device_priv),
-	0,
-	sizeof(struct usbdk_transfer_priv),
+	usbdk_clear_transfer_priv,
+	usbdk_copy_transfer_data,
+	usbdk_get_transfer_fd,
+	usbdk_get_overlapped_result,
 };
-
-#endif /* USE_USBDK */
diff --git a/libusb/os/windows_usbdk.h b/libusb/os/windows_usbdk.h
index e6eca8b..0de2675 100644
--- a/libusb/os/windows_usbdk.h
+++ b/libusb/os/windows_usbdk.h
@@ -23,56 +23,19 @@
 
 #pragma once
 
-typedef struct tag_USB_DK_DEVICE_ID {
-	WCHAR DeviceID[MAX_DEVICE_ID_LEN];
-	WCHAR InstanceID[MAX_DEVICE_ID_LEN];
-} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
+#include "windows_nt_common.h"
 
-static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID)
+static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, const WCHAR *DeviceID, const WCHAR *InstanceID)
 {
-	wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN);
-	wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN);
+	wcsncpy(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN);
+	wcsncpy(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN);
 }
 
-typedef struct tag_USB_DK_DEVICE_INFO {
-	USB_DK_DEVICE_ID ID;
-	ULONG64 FilterID;
-	ULONG64 Port;
-	ULONG64 Speed;
-	USB_DEVICE_DESCRIPTOR DeviceDescriptor;
-} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;
-
-typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST {
+typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST {
 	USB_DK_DEVICE_ID ID;
 	ULONG64 Index;
 } USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST;
 
-typedef struct tag_USB_DK_ISO_TRANSFER_RESULT {
-	ULONG64 ActualLength;
-	ULONG64 TransferResult;
-} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;
-
-typedef struct tag_USB_DK_GEN_TRANSFER_RESULT {
-	ULONG64 BytesTransferred;
-	ULONG64 UsbdStatus; // USBD_STATUS code
-} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;
-
-typedef struct tag_USB_DK_TRANSFER_RESULT {
-	USB_DK_GEN_TRANSFER_RESULT GenResult;
-	PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
-} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;
-
-typedef struct tag_USB_DK_TRANSFER_REQUEST {
-	ULONG64 EndpointAddress;
-	PVOID64 Buffer;
-	ULONG64 BufferLength;
-	ULONG64 TransferType;
-	ULONG64 IsochronousPacketsArraySize;
-	PVOID64 IsochronousPacketsArray;
-
-	USB_DK_TRANSFER_RESULT Result;
-} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
-
 typedef enum {
 	TransferFailure = 0,
 	TransferSuccess,
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index 8ff815b..b07e67a 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -25,8 +25,6 @@
 
 #include <config.h>
 
-#if !defined(USE_USBDK)
-
 #include <windows.h>
 #include <setupapi.h>
 #include <ctype.h>
@@ -39,7 +37,8 @@
 #include <winioctl.h>
 
 #include "libusbi.h"
-#include "poll_windows.h"
+#include "windows_common.h"
+#include "windows_nt_common.h"
 #include "windows_winusb.h"
 
 #define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE))
@@ -102,12 +101,8 @@
 static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
 static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
 
-
-// Global variables
-int windows_version = WINDOWS_UNDEFINED;
-// Concurrency
-static int concurrent_usage = -1;
 static usbi_mutex_t autoclaim_lock;
+
 // API globals
 static HMODULE WinUSBX_handle = NULL;
 static struct winusb_interface WinUSBX[SUB_API_MAX];
@@ -186,9 +181,9 @@
 }
 
 /*
- * Cfgmgr32, OLE32 and SetupAPI DLL functions
+ * Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions
  */
-static int init_dlls(void)
+static BOOL init_dlls(void)
 {
 	DLL_GET_HANDLE(Cfgmgr32);
 	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE);
@@ -199,9 +194,6 @@
 	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
 	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
 
-	DLL_GET_HANDLE(Kernel32);
-	DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE);
-
 	DLL_GET_HANDLE(OLE32);
 	DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE);
 
@@ -216,14 +208,13 @@
 	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE);
 	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
 
-	return LIBUSB_SUCCESS;
+	return TRUE;
 }
 
 static void exit_dlls(void)
 {
 	DLL_FREE_HANDLE(Cfgmgr32);
 	DLL_FREE_HANDLE(AdvAPI32);
-	DLL_FREE_HANDLE(Kernel32);
 	DLL_FREE_HANDLE(OLE32);
 	DLL_FREE_HANDLE(SetupAPI);
 }
@@ -502,7 +493,7 @@
 static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
 	int i, r;
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	struct libusb_config_descriptor *conf_desc;
 	const struct libusb_interface_descriptor *if_desc;
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
@@ -579,9 +570,9 @@
 static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
 {
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(
 		transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface = *interface_number;
 	int r = LIBUSB_SUCCESS;
 
@@ -624,10 +615,10 @@
 
 static void auto_release(struct usbi_transfer *itransfer)
 {
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	libusb_device_handle *dev_handle = transfer->dev_handle;
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	int r;
 
 	usbi_mutex_lock(&autoclaim_lock);
@@ -645,233 +636,56 @@
 	usbi_mutex_unlock(&autoclaim_lock);
 }
 
-/* Windows version dtection */
-static BOOL is_x64(void)
-{
-	BOOL ret = FALSE;
-
-	// Detect if we're running a 32 or 64 bit system
-	if (sizeof(uintptr_t) < 8) {
-		if (pIsWow64Process != NULL)
-			pIsWow64Process(GetCurrentProcess(), &ret);
-	} else {
-		ret = TRUE;
-	}
-
-	return ret;
-}
-
-static void get_windows_version(void)
-{
-	OSVERSIONINFOEXA vi, vi2;
-	const char *arch, *w = NULL;
-	unsigned major, minor;
-	ULONGLONG major_equal, minor_equal;
-	BOOL ws;
-
-	memset(&vi, 0, sizeof(vi));
-	vi.dwOSVersionInfoSize = sizeof(vi);
-	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
-		memset(&vi, 0, sizeof(vi));
-		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
-		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
-			return;
-	}
-
-	if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-		if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
-			// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
-			// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
-
-			major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
-			for (major = vi.dwMajorVersion; major <= 9; major++) {
-				memset(&vi2, 0, sizeof(vi2));
-				vi2.dwOSVersionInfoSize = sizeof(vi2);
-				vi2.dwMajorVersion = major;
-				if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
-					continue;
-
-				if (vi.dwMajorVersion < major) {
-					vi.dwMajorVersion = major;
-					vi.dwMinorVersion = 0;
-				}
-
-				minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
-				for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
-					memset(&vi2, 0, sizeof(vi2));
-					vi2.dwOSVersionInfoSize = sizeof(vi2);
-					vi2.dwMinorVersion = minor;
-					if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
-						continue;
-
-					vi.dwMinorVersion = minor;
-					break;
-				}
-
-				break;
-			}
-		}
-
-		if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
-			ws = (vi.wProductType <= VER_NT_WORKSTATION);
-			windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
-			switch (windows_version) {
-			case 0x50: w = "2000"; break;
-			case 0x51: w = "XP"; break;
-			case 0x52: w = "2003"; break;
-			case 0x60: w = (ws ? "Vista" : "2008"); break;
-			case 0x61: w = (ws ? "7" : "2008_R2"); break;
-			case 0x62: w = (ws ? "8" : "2012"); break;
-			case 0x63: w = (ws ? "8.1" : "2012_R2"); break;
-			case 0x64: w = (ws ? "10" : "2015"); break;
-			default:
-				if (windows_version < 0x50)
-					windows_version = WINDOWS_UNSUPPORTED;
-				else
-					w = "11 or later";
-				break;
-			}
-		}
-	}
-
-	arch = is_x64() ? "64-bit" : "32-bit";
-
-	if (w == NULL)
-		usbi_dbg("Windows %s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"),
-			(unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, arch);
-	else if (vi.wServicePackMinor)
-		usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
-	else if (vi.wServicePackMajor)
-		usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
-	else
-		usbi_dbg("Windows %s %s", w, arch);
-}
-
 /*
  * init: libusb backend init function
- *
- * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list
- * In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed.
- * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?)
  */
-static int windows_init(struct libusb_context *ctx)
+static int winusb_init(struct libusb_context *ctx)
 {
-	int i, r = LIBUSB_ERROR_OTHER;
-	HANDLE semaphore;
-	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+	int i;
 
-	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
-	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
-	if (semaphore == NULL) {
-		usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
-		return LIBUSB_ERROR_NO_MEM;
+	// We need a lock for proper auto-release
+	usbi_mutex_init(&autoclaim_lock);
+
+	// Load DLL imports
+	if (!init_dlls()) {
+		usbi_err(ctx, "could not resolve DLL functions");
+		return LIBUSB_ERROR_OTHER;
 	}
 
-	// A successful wait brings our semaphore count to 0 (unsignaled)
-	// => any concurent wait stalls until the semaphore's release
-	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
-		usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
-		CloseHandle(semaphore);
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	// NB: concurrent usage supposes that init calls are equally balanced with
-	// exit calls. If init is called more than exit, we will not exit properly
-	if (++concurrent_usage == 0) { // First init?
-		get_windows_version();
-
-		if (windows_version == WINDOWS_UNSUPPORTED) {
-			usbi_err(ctx, "This version of Windows is NOT supported");
-			r = LIBUSB_ERROR_NOT_SUPPORTED;
-			goto init_exit;
-		}
-
-		// We need a lock for proper auto-release
-		usbi_mutex_init(&autoclaim_lock);
-
-		// Load DLL imports
-		if (init_dlls() != LIBUSB_SUCCESS) {
-			usbi_err(ctx, "could not resolve DLL functions");
-			goto init_exit;
-		}
-
-		// Initialize the low level APIs (we don't care about errors at this stage)
-		for (i = 0; i < USB_API_MAX; i++) {
-			if (usb_api_backend[i].init && usb_api_backend[i].init(ctx))
-				usbi_warn(ctx, "error initializing %s backend",
-					usb_api_backend[i].designation);
-		}
-
-		r = windows_common_init(ctx);
-		if (r)
-			goto init_exit;
-	}
-	// At this stage, either we went through full init successfully, or didn't need to
-	r = LIBUSB_SUCCESS;
-
-init_exit: // Holds semaphore here.
-	if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
-		for (i = 0; i < USB_API_MAX; i++) {
-			if (usb_api_backend[i].exit)
-				usb_api_backend[i].exit();
-		}
-		exit_dlls();
-		windows_common_exit();
-		usbi_mutex_destroy(&autoclaim_lock);
-	}
-
-	if (r != LIBUSB_SUCCESS)
-		--concurrent_usage; // Not expected to call libusb_exit if we failed.
-
-	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
-	CloseHandle(semaphore);
-	return r;
-}
-
-/*
- * HCD (root) hubs need to have their device descriptor manually populated
- *
- * Note that, like Microsoft does in the device manager, we populate the
- * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device.
- */
-static int force_hcd_device_descriptor(struct libusb_device *dev)
-{
-	struct windows_device_priv *parent_priv, *priv = _device_priv(dev);
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	int vid, pid;
-
-	dev->num_configurations = 1;
-	priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR);
-	priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE;
-	priv->dev_descriptor.bNumConfigurations = 1;
-	priv->active_config = 1;
-
-	if (dev->parent_dev == NULL) {
-		usbi_err(ctx, "program assertion failed - HCD hub has no parent");
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	parent_priv = _device_priv(dev->parent_dev);
-	if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) {
-		priv->dev_descriptor.idVendor = (uint16_t)vid;
-		priv->dev_descriptor.idProduct = (uint16_t)pid;
-	} else {
-		usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path);
-		priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
-		priv->dev_descriptor.idProduct = 1;
+	// Initialize the low level APIs (we don't care about errors at this stage)
+	for (i = 0; i < USB_API_MAX; i++) {
+		if (usb_api_backend[i].init && usb_api_backend[i].init(ctx))
+			usbi_warn(ctx, "error initializing %s backend",
+				usb_api_backend[i].designation);
 	}
 
 	return LIBUSB_SUCCESS;
 }
 
 /*
+* exit: libusb backend deinitialization function
+*/
+static void winusb_exit(struct libusb_context *ctx)
+{
+	int i;
+
+	for (i = 0; i < USB_API_MAX; i++) {
+		if (usb_api_backend[i].exit)
+			usb_api_backend[i].exit();
+	}
+
+	exit_dlls();
+	usbi_mutex_destroy(&autoclaim_lock);
+}
+
+/*
  * fetch and cache all the config descriptors through I/O
  */
 static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle)
 {
 	DWORD size, ret_size;
 	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 	int r;
 	uint8_t i;
 
@@ -981,7 +795,7 @@
 {
 	struct libusb_context *ctx;
 	struct libusb_device *tmp_dev;
-	struct windows_device_priv *priv, *parent_priv;
+	struct winusb_device_priv *priv, *parent_priv;
 	USB_NODE_CONNECTION_INFORMATION_EX conn_info;
 	USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
 	HANDLE hub_handle;
@@ -1115,7 +929,7 @@
 	uint8_t bus_number, DEVINST devinst)
 {
 	struct libusb_device *dev;
-	struct windows_device_priv *priv;
+	struct winusb_device_priv *priv;
 	unsigned long session_id;
 	DEVINST child_devinst;
 
@@ -1209,7 +1023,7 @@
 static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev,
 	char *dev_interface_path, char *device_id, int api, int sub_api)
 {
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 	int interface_number;
 	const char *mi_str;
 
@@ -1257,7 +1071,7 @@
 	char *dev_interface_path)
 {
 	int i;
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 
 	if (priv->hid == NULL) {
 		usbi_err(ctx, "program assertion failed: parent is not HID");
@@ -1284,7 +1098,7 @@
 /*
  * get_device_list: libusb backend device enumeration function
  */
-static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
+static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
 {
 	struct discovered_devs *discdevs;
 	HDEVINFO *dev_info, dev_info_intf, dev_info_enum;
@@ -1297,7 +1111,7 @@
 	char enumerator[16];
 	char dev_id[MAX_PATH_LENGTH];
 	struct libusb_device *dev, *parent_dev;
-	struct windows_device_priv *priv, *parent_priv;
+	struct winusb_device_priv *priv, *parent_priv;
 	char *dev_interface_path = NULL;
 	unsigned long session_id;
 	DWORD size, port_nr, reg_type, install_state;
@@ -1573,7 +1387,7 @@
 					if (dev == NULL)
 						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
 
-					priv = windows_device_priv_init(dev);
+					priv = winusb_device_priv_init(dev);
 					priv->dev_id = _strdup(dev_id);
 					if (priv->dev_id == NULL) {
 						libusb_unref_device(dev);
@@ -1708,56 +1522,17 @@
 	return r;
 }
 
-/*
- * exit: libusb backend deinitialization function
- */
-static void windows_exit(struct libusb_context *ctx)
+static int winusb_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer)
 {
-	int i;
-	HANDLE semaphore;
-	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
-	UNUSED(ctx);
-
-	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
-	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
-	if (semaphore == NULL)
-		return;
-
-	// A successful wait brings our semaphore count to 0 (unsignaled)
-	// => any concurent wait stalls until the semaphore release
-	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
-		CloseHandle(semaphore);
-		return;
-	}
-
-	// Only works if exits and inits are balanced exactly
-	if (--concurrent_usage < 0) { // Last exit
-		for (i = 0; i < USB_API_MAX; i++) {
-			if (usb_api_backend[i].exit)
-				usb_api_backend[i].exit();
-		}
-		exit_dlls();
-		windows_common_exit();
-		usbi_mutex_destroy(&autoclaim_lock);
-	}
-
-	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
-	CloseHandle(semaphore);
-}
-
-static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
-{
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 
 	memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH);
-	*host_endian = 0;
-
 	return LIBUSB_SUCCESS;
 }
 
-static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
+static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len)
 {
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 	PUSB_CONFIGURATION_DESCRIPTOR config_header;
 	size_t size;
 
@@ -1768,25 +1543,20 @@
 	if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
+	config_header = priv->config_descriptor[config_index];
 
 	size = MIN(config_header->wTotalLength, len);
 	memcpy(buffer, priv->config_descriptor[config_index], size);
-	*host_endian = 0;
-
 	return (int)size;
 }
 
-static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
-	unsigned char **buffer, int *host_endian)
+static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
+	unsigned char **buffer)
 {
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 	PUSB_CONFIGURATION_DESCRIPTOR config_header;
 	uint8_t index;
 
-	*buffer = NULL;
-	*host_endian = 0;
-
 	if (priv->config_descriptor == NULL)
 		return LIBUSB_ERROR_NOT_FOUND;
 
@@ -1804,16 +1574,16 @@
 /*
  * return the cached copy of the active config descriptor
  */
-static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
+static int winusb_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len)
 {
-	struct windows_device_priv *priv = _device_priv(dev);
+	struct winusb_device_priv *priv = _device_priv(dev);
 	unsigned char *config_desc;
 	int r;
 
 	if (priv->active_config == 0)
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian);
+	r = winusb_get_config_descriptor_by_value(dev, priv->active_config, &config_desc);
 	if (r < 0)
 		return r;
 
@@ -1822,9 +1592,9 @@
 	return (int)len;
 }
 
-static int windows_open(struct libusb_device_handle *dev_handle)
+static int winusb_open(struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	if (priv->apib->open == NULL) {
 		PRINT_UNSUPPORTED_API(open);
@@ -1833,17 +1603,17 @@
 	return priv->apib->open(SUB_API_NOTSET, dev_handle);
 }
 
-static void windows_close(struct libusb_device_handle *dev_handle)
+static void winusb_close(struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	if (priv->apib->close)
 		priv->apib->close(SUB_API_NOTSET, dev_handle);
 }
 
-static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
+static int winusb_get_configuration(struct libusb_device_handle *dev_handle, int *config)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	if (priv->active_config == 0) {
 		*config = 0;
@@ -1859,9 +1629,9 @@
  * does not currently expose a service that allows higher-level drivers to set
  * the configuration."
  */
-static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
+static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int config)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int r = LIBUSB_SUCCESS;
 
 	if (config >= USB_MAXCONFIG)
@@ -1878,9 +1648,9 @@
 	return r;
 }
 
-static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface)
+static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int r;
 
 	if (priv->apib->claim_interface == NULL) {
@@ -1898,9 +1668,9 @@
 	return r;
 }
 
-static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
+static int winusb_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int r;
 
 	if (priv->apib->set_interface_altsetting == NULL) {
@@ -1918,9 +1688,9 @@
 	return r;
 }
 
-static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface)
+static int winusb_release_interface(struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	if (priv->apib->release_interface == NULL) {
 		PRINT_UNSUPPORTED_API(release_interface);
@@ -1929,9 +1699,9 @@
 	return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface);
 }
 
-static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
+static int winusb_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	if (priv->apib->clear_halt == NULL) {
 		PRINT_UNSUPPORTED_API(clear_halt);
@@ -1940,9 +1710,9 @@
 	return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint);
 }
 
-static int windows_reset_device(struct libusb_device_handle *dev_handle)
+static int winusb_reset_device(struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	if (priv->apib->reset_device == NULL) {
 		PRINT_UNSUPPORTED_API(reset_device);
@@ -1951,14 +1721,14 @@
 	return priv->apib->reset_device(SUB_API_NOTSET, dev_handle);
 }
 
-static void windows_destroy_device(struct libusb_device *dev)
+static void winusb_destroy_device(struct libusb_device *dev)
 {
-	windows_device_priv_release(dev);
+	winusb_device_priv_release(dev);
 }
 
-void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
+static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
 {
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 
 	usbi_close(transfer_priv->pollable_fd.fd);
 	transfer_priv->pollable_fd = INVALID_WINFD;
@@ -1972,7 +1742,7 @@
 	int (*transfer_fn)(int, struct usbi_transfer *))
 {
 	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	struct winfd wfd;
 	int r;
 
@@ -2000,10 +1770,10 @@
 	return r;
 }
 
-static int windows_submit_transfer(struct usbi_transfer *itransfer)
+static int winusb_submit_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int (*transfer_fn)(int, struct usbi_transfer *);
 	short events;
 
@@ -2043,7 +1813,7 @@
 static int windows_abort_control(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 
 	if (priv->apib->abort_control == NULL) {
 		PRINT_UNSUPPORTED_API(abort_control);
@@ -2055,7 +1825,7 @@
 static int windows_abort_transfers(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 
 	if (priv->apib->abort_transfers == NULL) {
 		PRINT_UNSUPPORTED_API(abort_transfers);
@@ -2064,7 +1834,7 @@
 	return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
 }
 
-static int windows_cancel_transfer(struct usbi_transfer *itransfer)
+static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 
@@ -2083,22 +1853,23 @@
 	}
 }
 
-int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
+static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
 }
 
-int windows_get_transfer_fd(struct usbi_transfer *itransfer)
+static int winusb_get_transfer_fd(struct usbi_transfer *itransfer)
 {
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	return transfer_priv->pollable_fd.fd;
 }
 
-void windows_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size)
+static void winusb_get_overlapped_result(struct usbi_transfer *itransfer,
+	DWORD *io_result, DWORD *io_size)
 {
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	struct winfd *pollable_fd = &transfer_priv->pollable_fd;
 
 	if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) {
@@ -2113,60 +1884,32 @@
 }
 
 // NB: MSVC6 does not support named initializers.
-const struct usbi_os_backend usbi_backend = {
-	"Windows",
-	USBI_CAP_HAS_HID_ACCESS,
-	windows_init,
-	windows_exit,
-	NULL,				/* set_option */
-
-	windows_get_device_list,
-	NULL,				/* hotplug_poll */
-	windows_open,
-	windows_close,
-
-	windows_get_device_descriptor,
-	windows_get_active_config_descriptor,
-	windows_get_config_descriptor,
-	windows_get_config_descriptor_by_value,
-
-	windows_get_configuration,
-	windows_set_configuration,
-	windows_claim_interface,
-	windows_release_interface,
-
-	windows_set_interface_altsetting,
-	windows_clear_halt,
-	windows_reset_device,
-
-	NULL,				/* alloc_streams */
-	NULL,				/* free_streams */
-
-	NULL,				/* dev_mem_alloc */
-	NULL,				/* dev_mem_free */
-
-	NULL,				/* kernel_driver_active */
-	NULL,				/* detach_kernel_driver */
-	NULL,				/* attach_kernel_driver */
-
-	windows_destroy_device,
-
-	windows_submit_transfer,
-	windows_cancel_transfer,
-	windows_clear_transfer_priv,
-
-	windows_handle_events,
-	NULL,
-
-	windows_clock_gettime,
-
-	0,
-	sizeof(struct windows_device_priv),
-	sizeof(struct windows_device_handle_priv),
-	sizeof(struct windows_transfer_priv),
+const struct windows_backend winusb_backend = {
+	winusb_init,
+	winusb_exit,
+	winusb_get_device_list,
+	winusb_open,
+	winusb_close,
+	winusb_get_device_descriptor,
+	winusb_get_active_config_descriptor,
+	winusb_get_config_descriptor,
+	winusb_get_config_descriptor_by_value,
+	winusb_get_configuration,
+	winusb_set_configuration,
+	winusb_claim_interface,
+	winusb_release_interface,
+	winusb_set_interface_altsetting,
+	winusb_clear_halt,
+	winusb_reset_device,
+	winusb_destroy_device,
+	winusb_submit_transfer,
+	winusb_cancel_transfer,
+	winusb_clear_transfer_priv,
+	winusb_copy_transfer_data,
+	winusb_get_transfer_fd,
+	winusb_get_overlapped_result,
 };
 
-
 /*
  * USB API backends
  */
@@ -2347,8 +2090,8 @@
 static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HANDLE file_handle;
 	int i;
 
@@ -2380,8 +2123,8 @@
 
 static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE handle;
 	int i;
 
@@ -2425,8 +2168,8 @@
 
 static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
 	UCHAR policy;
 	ULONG timeout = 0;
@@ -2473,8 +2216,8 @@
 static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
 	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
 	HDEVINFO dev_info = INVALID_HANDLE_VALUE;
@@ -2585,8 +2328,8 @@
 
 static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
@@ -2606,8 +2349,8 @@
  */
 static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int i;
 
 	if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
@@ -2628,8 +2371,8 @@
 /*
  * Lookup interface by endpoint address. -1 if not found
  */
-static int interface_by_endpoint(struct windows_device_priv *priv,
-	struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address)
+static int interface_by_endpoint(struct winusb_device_priv *priv,
+	struct winusb_device_handle_priv *handle_priv, uint8_t endpoint_address)
 {
 	int i, j;
 
@@ -2651,9 +2394,9 @@
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
 	PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer;
 	ULONG size;
 	HANDLE winusb_handle;
@@ -2707,8 +2450,8 @@
 static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 
 	CHECK_WINUSBX_AVAILABLE(sub_api);
@@ -2734,9 +2477,9 @@
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	HANDLE winusb_handle;
 	OVERLAPPED *overlapped;
 	bool ret;
@@ -2780,8 +2523,8 @@
 static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 	int current_interface;
 
@@ -2820,9 +2563,9 @@
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	HANDLE handle;
 	int current_interface;
 
@@ -2869,8 +2612,8 @@
 static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE winusb_handle;
 	int i, j;
 
@@ -3209,7 +2952,7 @@
 }
 
 static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
-	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
+	struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
 {
 	uint8_t *buf;
 	DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
@@ -3287,7 +3030,7 @@
 }
 
 static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
-	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
+	struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
 {
 	uint8_t *buf = NULL;
 	DWORD ioctl_code, write_size = (DWORD)*size;
@@ -3358,7 +3101,7 @@
 }
 
 static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type,
-	int request, int value, int _index, void *data, struct windows_transfer_priv *tp,
+	int request, int value, int _index, void *data, struct winusb_transfer_priv *tp,
 	size_t *size, OVERLAPPED *overlapped)
 {
 	int report_type = (value >> 8) & 0xFF;
@@ -3414,8 +3157,8 @@
 static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HIDD_ATTRIBUTES hid_attributes;
 	PHIDP_PREPARSED_DATA preparsed_data = NULL;
 	HIDP_CAPS capabilities;
@@ -3564,8 +3307,8 @@
 
 static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HANDLE file_handle;
 	int i;
 
@@ -3583,8 +3326,8 @@
 
 static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	CHECK_HID_AVAILABLE;
 
@@ -3606,8 +3349,8 @@
 
 static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	CHECK_HID_AVAILABLE;
 
@@ -3642,9 +3385,9 @@
 static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
 	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
 	HANDLE hid_handle;
@@ -3681,7 +3424,7 @@
 				(setup->Value >> 8) & 0xFF, setup->Value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
 			break;
 		case LIBUSB_REQUEST_GET_CONFIGURATION:
-			r = windows_get_configuration(transfer->dev_handle, &config);
+			r = winusb_get_configuration(transfer->dev_handle, &config);
 			if (r == LIBUSB_SUCCESS) {
 				size = 1;
 				((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
@@ -3738,10 +3481,10 @@
 static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	HANDLE hid_handle;
 	OVERLAPPED *overlapped;
 	bool direction_in, ret;
@@ -3827,8 +3570,8 @@
 {
 	struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
 	HANDLE hid_handle;
 	int current_interface;
 
@@ -3858,7 +3601,7 @@
 
 static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
 	HANDLE hid_handle;
 	int current_interface;
 
@@ -3877,8 +3620,8 @@
 static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	HANDLE hid_handle;
 	int current_interface;
 
@@ -3909,7 +3652,7 @@
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
 	int r = LIBUSB_TRANSFER_COMPLETED;
 	uint32_t corrected_size = io_size;
 
@@ -3948,7 +3691,7 @@
  */
 static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int r = LIBUSB_ERROR_NOT_FOUND;
 	uint8_t i;
 	// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
@@ -3984,7 +3727,7 @@
 
 static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	uint8_t i;
 	// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
 	bool available[SUB_API_MAX + 1] = { 0 };
@@ -4014,7 +3757,7 @@
 
 static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->usb_interface[iface].apib->
 		claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
@@ -4022,7 +3765,7 @@
 
 static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->usb_interface[iface].apib->
 		set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting);
@@ -4030,7 +3773,7 @@
 
 static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 
 	return priv->usb_interface[iface].apib->
 		release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
@@ -4040,7 +3783,7 @@
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	struct libusb_config_descriptor *conf_desc;
 	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
 	int iface, pass, r;
@@ -4101,8 +3844,8 @@
 static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface;
 
 	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
@@ -4118,8 +3861,8 @@
 static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface;
 
 	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
@@ -4135,8 +3878,8 @@
 static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int current_interface;
 
 	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
@@ -4152,8 +3895,8 @@
 static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface = transfer_priv->interface_number;
 
 	if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
@@ -4168,8 +3911,8 @@
 static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 	int current_interface = transfer_priv->interface_number;
 
 	if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
@@ -4183,7 +3926,7 @@
 
 static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
 {
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
+	struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
 	int r;
 	uint8_t i;
 	bool available[SUB_API_MAX];
@@ -4211,11 +3954,9 @@
 static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+	struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
 
 	return priv->usb_interface[transfer_priv->interface_number].apib->
 		copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size);
 }
-
-#endif /* !USE_USBDK */
diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h
index fb0a4e7..9b4a0f6 100644
--- a/libusb/os/windows_winusb.h
+++ b/libusb/os/windows_winusb.h
@@ -195,37 +195,14 @@
 	uint8_t string_index[3]; // man, prod, ser
 };
 
-struct windows_device_priv {
-	bool initialized;
-	bool root_hub;
-	uint8_t active_config;
-	uint8_t depth;
-	const struct windows_usb_api_backend *apib;
-	char *dev_id;
-	char *path;  // device interface path
-	int sub_api; // for WinUSB-like APIs
-	struct {
-		char *path; // each interface needs a device interface path,
-		const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support),
-		int sub_api;
-		int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
-		uint8_t *endpoint;
-		bool restricted_functionality;  // indicates if the interface functionality is restricted
-                                                // by Windows (eg. HID keyboards or mice cannot do R/W)
-	} usb_interface[USB_MAXINTERFACES];
-	struct hid_device_priv *hid;
-	USB_DEVICE_DESCRIPTOR dev_descriptor;
-	PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors
-};
-
-static inline struct windows_device_priv *_device_priv(struct libusb_device *dev)
+static inline struct winusb_device_priv *_device_priv(struct libusb_device *dev)
 {
-	return (struct windows_device_priv *)dev->os_priv;
+	return (struct winusb_device_priv *)dev->os_priv;
 }
 
-static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev)
+static inline struct winusb_device_priv *winusb_device_priv_init(struct libusb_device *dev)
 {
-	struct windows_device_priv *p = _device_priv(dev);
+	struct winusb_device_priv *p = _device_priv(dev);
 	int i;
 
 	p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
@@ -238,9 +215,9 @@
 	return p;
 }
 
-static inline void windows_device_priv_release(struct libusb_device *dev)
+static inline void winusb_device_priv_release(struct libusb_device *dev)
 {
-	struct windows_device_priv *p = _device_priv(dev);
+	struct winusb_device_priv *p = _device_priv(dev);
 	int i;
 
 	free(p->dev_id);
@@ -257,33 +234,12 @@
 	}
 }
 
-struct interface_handle_t {
-	HANDLE dev_handle; // WinUSB needs an extra handle for the file
-	HANDLE api_handle; // used by the API to communicate with the device
-};
-
-struct windows_device_handle_priv {
-	int active_interface;
-	struct interface_handle_t interface_handle[USB_MAXINTERFACES];
-	int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
-};
-
-static inline struct windows_device_handle_priv *_device_handle_priv(
+static inline struct winusb_device_handle_priv *_device_handle_priv(
 	struct libusb_device_handle *handle)
 {
-	return (struct windows_device_handle_priv *)handle->os_priv;
+	return (struct winusb_device_handle_priv *)handle->os_priv;
 }
 
-// used for async polling functions
-struct windows_transfer_priv {
-	struct winfd pollable_fd;
-	HANDLE handle;
-	uint8_t interface_number;
-	uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
-	uint8_t *hid_dest;   // transfer buffer destination, required for HID
-	size_t hid_expected_size;
-};
-
 // used to match a device driver (including filter drivers) against a supported API
 struct driver_lookup {
 	char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names
@@ -315,11 +271,6 @@
 DLL_DECLARE_HANDLE(OLE32);
 DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, IIDFromString, (LPCOLESTR, LPIID));
 
-/* Kernel32 dependencies */
-DLL_DECLARE_HANDLE(Kernel32);
-/* This call is only available from XP SP2 */
-DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL));
-
 /* SetupAPI dependencies */
 DLL_DECLARE_HANDLE(SetupAPI);
 DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, PCSTR, HWND, DWORD));
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index ffbd254..fbe5f76 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11274
+#define LIBUSB_NANO 11275
diff --git a/msvc/libusb_dll_2005.vcproj b/msvc/libusb_dll_2005.vcproj
index 731c754..325a4d7 100644
--- a/msvc/libusb_dll_2005.vcproj
+++ b/msvc/libusb_dll_2005.vcproj
@@ -378,6 +378,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\libusb\os\windows_usbdk.c"
+				>
+			</File>
+			<File
 				RelativePath="..\libusb\os\windows_winusb.c"
 				>
 			</File>
@@ -428,6 +432,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\libusb\os\windows_nt_shared_types.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_usbdk.h"
+				>
+			</File>
+			<File
 				RelativePath="..\libusb\os\windows_winusb.h"
 				>
 			</File>
diff --git a/msvc/libusb_dll_2010.vcxproj b/msvc/libusb_dll_2010.vcxproj
index 3a37811..0663aa2 100644
--- a/msvc/libusb_dll_2010.vcxproj
+++ b/msvc/libusb_dll_2010.vcxproj
@@ -147,6 +147,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -160,6 +161,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_dll_2010.vcxproj.filters b/msvc/libusb_dll_2010.vcxproj.filters
index c77654b..ae65ec2 100644
--- a/msvc/libusb_dll_2010.vcxproj.filters
+++ b/msvc/libusb_dll_2010.vcxproj.filters
@@ -38,6 +38,12 @@
     <ClCompile Include="..\libusb\os\threads_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\os\windows_nt_common.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libusb\os\windows_usbdk.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\os\windows_winusb.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -61,12 +67,27 @@
     <ClInclude Include="..\libusb\os\threads_windows.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
+    <ClInclude Include="..\libusb\version.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\version_nano.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="..\libusb\os\windows_common.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_nt_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_usbdk.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\libusb\libusb-1.0.def">
diff --git a/msvc/libusb_dll_2012.vcxproj b/msvc/libusb_dll_2012.vcxproj
index 92a8baf..90a1a8b 100644
--- a/msvc/libusb_dll_2012.vcxproj
+++ b/msvc/libusb_dll_2012.vcxproj
@@ -151,6 +151,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -164,6 +165,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_dll_2012.vcxproj.filters b/msvc/libusb_dll_2012.vcxproj.filters
index 6120953..ae65ec2 100644
--- a/msvc/libusb_dll_2012.vcxproj.filters
+++ b/msvc/libusb_dll_2012.vcxproj.filters
@@ -20,6 +20,9 @@
     <ClCompile Include="..\libusb\descriptor.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\hotplug.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\io.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -35,10 +38,13 @@
     <ClCompile Include="..\libusb\os\threads_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
+    <ClCompile Include="..\libusb\os\windows_nt_common.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
+    <ClCompile Include="..\libusb\os\windows_usbdk.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libusb\os\windows_winusb.c">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
@@ -46,6 +52,9 @@
     <ClInclude Include=".\config.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\libusb\hotplug.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\libusb\libusb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -58,16 +67,25 @@
     <ClInclude Include="..\libusb\os\threads_windows.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\libusb\version.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="..\libusb\version_nano.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\hotplug.h">
+    <ClInclude Include="..\libusb\os\windows_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_nt_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_usbdk.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
   </ItemGroup>
diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll_2013.vcxproj
index 6a4ce16..f43a9c3 100644
--- a/msvc/libusb_dll_2013.vcxproj
+++ b/msvc/libusb_dll_2013.vcxproj
@@ -151,6 +151,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -164,6 +165,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_dll_2015.vcxproj b/msvc/libusb_dll_2015.vcxproj
index 0c1730a..f0744f6 100644
--- a/msvc/libusb_dll_2015.vcxproj
+++ b/msvc/libusb_dll_2015.vcxproj
@@ -151,6 +151,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -164,6 +165,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_dll_2017.vcxproj b/msvc/libusb_dll_2017.vcxproj
index 0d46d48..723c6b3 100644
--- a/msvc/libusb_dll_2017.vcxproj
+++ b/msvc/libusb_dll_2017.vcxproj
@@ -151,6 +151,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -164,6 +165,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/msvc/libusb_sources b/msvc/libusb_sources
index 591d7f6..56960f9 100644
--- a/msvc/libusb_sources
+++ b/msvc/libusb_sources
@@ -32,13 +32,13 @@
 
 SOURCES=..\core.c \
 	..\descriptor.c \
+	..\hotplug.c \
 	..\io.c \
 	..\strerror.c \
 	..\sync.c \
-	..\hotplug.c \
 	threads_windows.c \
 	poll_windows.c \
-	windows_winusb.c \
-	windows_usbdk.c \
 	windows_nt_common.c \
+	windows_usbdk.c \
+	windows_winusb.c \
 	..\libusb-1.0.rc
diff --git a/msvc/libusb_static_2005.vcproj b/msvc/libusb_static_2005.vcproj
index 7dd3d3e..901c499 100644
--- a/msvc/libusb_static_2005.vcproj
+++ b/msvc/libusb_static_2005.vcproj
@@ -318,6 +318,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\libusb\os\windows_usbdk.c"
+				>
+			</File>
+			<File
 				RelativePath="..\libusb\os\windows_winusb.c"
 				>
 			</File>
@@ -368,6 +372,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\libusb\os\windows_nt_shared_types.h"
+				>
+			</File>
+			<File
+				RelativePath="..\libusb\os\windows_usbdk.h"
+				>
+			</File>
+			<File
 				RelativePath="..\libusb\os\windows_winusb.h"
 				>
 			</File>
diff --git a/msvc/libusb_static_2010.vcxproj b/msvc/libusb_static_2010.vcxproj
index 78233c3..cb031fc 100644
--- a/msvc/libusb_static_2010.vcxproj
+++ b/msvc/libusb_static_2010.vcxproj
@@ -137,6 +137,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -150,6 +151,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/msvc/libusb_static_2010.vcxproj.filters b/msvc/libusb_static_2010.vcxproj.filters
index cce8001..c04af66 100644
--- a/msvc/libusb_static_2010.vcxproj.filters
+++ b/msvc/libusb_static_2010.vcxproj.filters
@@ -17,6 +17,9 @@
     <ClCompile Include="..\libusb\descriptor.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\hotplug.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\io.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -32,10 +35,13 @@
     <ClCompile Include="..\libusb\os\threads_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
+    <ClCompile Include="..\libusb\os\windows_nt_common.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
+    <ClCompile Include="..\libusb\os\windows_usbdk.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libusb\os\windows_winusb.c">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
@@ -43,6 +49,9 @@
     <ClInclude Include=".\config.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\libusb\hotplug.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\libusb\libusb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -55,19 +64,25 @@
     <ClInclude Include="..\libusb\os\threads_windows.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
+    <ClInclude Include="..\libusb\version.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="..\libusb\version_nano.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
+    <ClInclude Include="..\libusb\os\windows_common.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\hotplug.h">
+    <ClInclude Include="..\libusb\os\windows_nt_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_usbdk.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
   </ItemGroup>
diff --git a/msvc/libusb_static_2012.vcxproj b/msvc/libusb_static_2012.vcxproj
index 7df832d..3e91df2 100644
--- a/msvc/libusb_static_2012.vcxproj
+++ b/msvc/libusb_static_2012.vcxproj
@@ -141,6 +141,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -154,6 +155,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/msvc/libusb_static_2012.vcxproj.filters b/msvc/libusb_static_2012.vcxproj.filters
index cce8001..c04af66 100644
--- a/msvc/libusb_static_2012.vcxproj.filters
+++ b/msvc/libusb_static_2012.vcxproj.filters
@@ -17,6 +17,9 @@
     <ClCompile Include="..\libusb\descriptor.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\hotplug.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\io.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -32,10 +35,13 @@
     <ClCompile Include="..\libusb\os\threads_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\libusb\os\windows_winusb.c">
+    <ClCompile Include="..\libusb\os\windows_nt_common.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\libusb\hotplug.c">
+    <ClCompile Include="..\libusb\os\windows_usbdk.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libusb\os\windows_winusb.c">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
@@ -43,6 +49,9 @@
     <ClInclude Include=".\config.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\libusb\hotplug.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\libusb\libusb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -55,19 +64,25 @@
     <ClInclude Include="..\libusb\os\threads_windows.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_winusb.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\libusb\os\windows_common.h">
+    <ClInclude Include="..\libusb\version.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="..\libusb\version_nano.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\version.h">
+    <ClInclude Include="..\libusb\os\windows_common.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\libusb\hotplug.h">
+    <ClInclude Include="..\libusb\os\windows_nt_common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_usbdk.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libusb\os\windows_winusb.h">
       <Filter>Header Files</Filter>
     </ClInclude>
   </ItemGroup>
diff --git a/msvc/libusb_static_2013.vcxproj b/msvc/libusb_static_2013.vcxproj
index fa3caac..813686f 100644
--- a/msvc/libusb_static_2013.vcxproj
+++ b/msvc/libusb_static_2013.vcxproj
@@ -141,6 +141,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -154,6 +155,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/msvc/libusb_static_2015.vcxproj b/msvc/libusb_static_2015.vcxproj
index b9c5850..2b9af09 100644
--- a/msvc/libusb_static_2015.vcxproj
+++ b/msvc/libusb_static_2015.vcxproj
@@ -145,6 +145,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -158,6 +159,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/msvc/libusb_static_2017.vcxproj b/msvc/libusb_static_2017.vcxproj
index 3a6fa13..e8a08cf 100644
--- a/msvc/libusb_static_2017.vcxproj
+++ b/msvc/libusb_static_2017.vcxproj
@@ -145,6 +145,7 @@
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_nt_common.c" />
+    <ClCompile Include="..\libusb\os\windows_usbdk.c" />
     <ClCompile Include="..\libusb\os\windows_winusb.c" />
   </ItemGroup>
   <ItemGroup>
@@ -158,6 +159,8 @@
     <ClInclude Include="..\libusb\version_nano.h" />
     <ClInclude Include="..\libusb\os\windows_common.h" />
     <ClInclude Include="..\libusb\os\windows_nt_common.h" />
+    <ClInclude Include="..\libusb\os\windows_nt_shared_types.h" />
+    <ClInclude Include="..\libusb\os\windows_usbdk.h" />
     <ClInclude Include="..\libusb\os\windows_winusb.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />