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); }
void windows_common_exit(void) { htab_destroy(); windows_destroy_clock(); windows_exit_dlls(); }
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; }