diff --git a/UsbDk/ControlDevice.cpp b/UsbDk/ControlDevice.cpp index 00c38b4..203f073 100644 --- a/UsbDk/ControlDevice.cpp +++ b/UsbDk/ControlDevice.cpp @@ -271,6 +271,49 @@ ULONG CUsbDkControlDevice::CountDevices() return numberDevices; } +void CUsbDkControlDevice::RegisterHiddenDevice(CUsbDkFilterDevice &FilterDevice) +{ + // Windows recognizes USB devices by PID/VID/SN combination, + // for each new USB device plugged in it generates a new + // cached driver information entry in the registry. + // + // When UsbDk hides or redirects a device it creates a virtual + // device with UsbDk VID / PID and a generated serial number. + // + // On one hand, this serial number should be unique because + // there should be no multiple devices with the same PID/VID/SN + // combination at any given moment of time. On the other hand, + // UsbDk should re-use serial numbers of unplugged devices, + // because we don't want Windows to cache one more driver + // information entry each time we redirect of hide a device. + // + // This function implements a simple but efficient mechanism + // for serial number generation for virtual UsbDk devices + + CLockedContext Ctx(m_HiddenDevicesLock); + + bool NoSuchSN = false; + + for (ULONG MinSN = 0; !NoSuchSN; MinSN++) + { + NoSuchSN = m_HiddenDevices.ForEach([MinSN](CUsbDkFilterDevice *Filter) + { return (Filter->GetSerialNumber() != MinSN); }); + + if (NoSuchSN) + { + FilterDevice.SetSerialNumber(MinSN); + } + } + + m_HiddenDevices.PushBack(&FilterDevice); +} + +void CUsbDkControlDevice::UnregisterHiddenDevice(CUsbDkFilterDevice &FilterDevice) +{ + CLockedContext Ctx(m_HiddenDevicesLock); + m_HiddenDevices.Remove(&FilterDevice); +} + bool CUsbDkControlDevice::ShouldHide(const USB_DEVICE_DESCRIPTOR &DevDescriptor) const { auto Hide = false; diff --git a/UsbDk/ControlDevice.h b/UsbDk/ControlDevice.h index 28842fc..759479c 100644 --- a/UsbDk/ControlDevice.h +++ b/UsbDk/ControlDevice.h @@ -246,6 +246,9 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable m_FilterDevices; + CWdmList m_HiddenDevices; + CWdmSpinLock m_HiddenDevicesLock; + typedef CWdmSet RedirectionsSet; RedirectionsSet m_Redirections;