Skip to content

Commit

Permalink
ControlDevice: Generate serial numbers for UsbDk devices
Browse files Browse the repository at this point in the history
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 patch introduces a simple but efficient mechanism
for serial number generation for virtual UsbDk devices.

Signed-off-by: Dmitry Fleytman <[email protected]>
  • Loading branch information
Dmitry Fleytman committed Feb 19, 2017
1 parent 2e945fe commit a4bf95a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
43 changes: 43 additions & 0 deletions UsbDk/ControlDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CWdmSpinLock> 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<CWdmSpinLock> Ctx(m_HiddenDevicesLock);
m_HiddenDevices.Remove(&FilterDevice);
}

bool CUsbDkControlDevice::ShouldHide(const USB_DEVICE_DESCRIPTOR &DevDescriptor) const
{
auto Hide = false;
Expand Down
6 changes: 6 additions & 0 deletions UsbDk/ControlDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<NonPa
void UnregisterFilter(CUsbDkFilterDevice &FilterDevice)
{ m_FilterDevices.Remove(&FilterDevice); }

void RegisterHiddenDevice(CUsbDkFilterDevice &FilterDevice);
void UnregisterHiddenDevice(CUsbDkFilterDevice &FilterDevice);

ULONG CountDevices();
NTSTATUS RescanRegistry()
{ return ReloadPersistentHideRules(); }
Expand Down Expand Up @@ -308,6 +311,9 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<NonPa

CWdmList<CUsbDkFilterDevice, CLockedAccess, CNonCountingObject, CRefCountingDeleter> m_FilterDevices;

CWdmList<CUsbDkFilterDevice, CRawAccess, CNonCountingObject, CRefCountingDeleter> m_HiddenDevices;
CWdmSpinLock m_HiddenDevicesLock;

typedef CWdmSet<CUsbDkRedirection, CLockedAccess, CNonCountingObject, CRefCountingDeleter> RedirectionsSet;
RedirectionsSet m_Redirections;

Expand Down

0 comments on commit a4bf95a

Please sign in to comment.