The install fast path treated an openable VHCI interface as 'driver
present', but the interface GUID is identical across all usbip-win2
releases while PLUGIN_HARDWARE_ONCE and STOP_ATTACH_ATTEMPTS only exist
since 0.9.7.5 — a machine with an older community release passed the
check and then failed every Plugin forever. The fast path now probes
STOP_ATTACH_ATTEMPTS and falls through to the (in-place, FORCE) install
when the driver lacks it. The probe's empty location doubles as
cleanup, discarding ghost reattach attempts left by a previous process.
PLUGIN_HARDWARE_ONCE only suppresses retries of the initial attach;
when an established connection later drops, wsk_receive.cpp
unconditionally schedules background reattach attempts (~20 tries over
~2 hours) toward this session's dead one-shot loopback port. With
ephemeral port reuse those ghost connects steal a later session's
Accept and fail its Plugin. Wire up STOP_ATTACH_ATTEMPTS (0x805,
present in both bundled driver builds) and cancel the session's exact
host/service/busid location before plugout.
Implement the Windows importer over vadimgrn/usbip-win2's UDE (USB Device
Emulation) driver. The driver does the TCP connect and import handshake
in-kernel via WSK, so it cannot take sing-box's already-dialed (and
possibly proxied) socket. Instead each Attach runs a one-shot loopback
listener, points the driver at it with PLUGIN_HARDWARE_ONCE, answers the
driver's in-kernel OP_REQ_IMPORT from the cached device info, and splices
the loopback stream to the proxied server connection -- so all dialer and
proxy behavior stays in userspace.
The Microsoft-signed driver is bundled and auto-installed like
common/vboxusb: amd64 from usbip-win2 0.9.7.7, arm64 from 0.9.7.5 (the
newest release with an arm64 build; identical ABI). EnsureDriver extracts
the package, registers the upper-filter, and creates the root-enumerated
UDE devnode via SetupAPI.
Also fix the control-channel fallback to treat a standard server's
connection reset (ECONNRESET on Windows) the same as a clean EOF, so the
client falls back to standard usbip discovery instead of retrying forever.
Verified on Win11 x64: self-installs the driver on a clean machine and
imports a device; behaves byte-identically to the official usbip-win2
client.