Skip to content

Commit

Permalink
Fix for daynix/UsbDk daynix#124, "UsbDk_StartRedirect hangs if no nor…
Browse files Browse the repository at this point in the history
…mal USB driver". Add filter driver to device with no normal USB driver that sets Raw mode.
  • Loading branch information
gwgill committed Oct 25, 2023
1 parent af46b7e commit 2233fde
Show file tree
Hide file tree
Showing 15 changed files with 987 additions and 15 deletions.
395 changes: 395 additions & 0 deletions UsbDk/ControlDevice.cpp

Large diffs are not rendered by default.

49 changes: 48 additions & 1 deletion UsbDk/ControlDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ class CUsbDkRedirection : public CAllocatable<USBDK_NON_PAGED_POOL, 'NRHR'>, pub
bool MatchProcess(ULONG pid);

NTSTATUS WaitForAttachment()
{ return m_RedirectionCreated.Wait(true, -SecondsTo100Nanoseconds(120)); }
{ return m_RedirectionCreated.Wait(true, -SecondsTo100Nanoseconds(15)); }

bool WaitForDetachment();

Expand Down Expand Up @@ -225,6 +225,41 @@ class CUsbDkRedirection : public CAllocatable<USBDK_NON_PAGED_POOL, 'NRHR'>, pub
DECLARE_CWDMLIST_ENTRY(CUsbDkRedirection);
};

class CUsbDkFDriverRule : public CAllocatable < USBDK_NON_PAGED_POOL, 'FDRR' >
{
public:

CUsbDkFDriverRule(ULONG VidPid, ULONG PortHub, CString &KeyName)
: m_VidPid(VidPid)
, m_PortHub(PortHub)
{
m_KeyName.Swap(KeyName);
}

bool Match(const ULONG VidPid, const ULONG PortHub) const
{
return m_VidPid == VidPid && m_PortHub == PortHub;
}

bool operator ==(const CUsbDkFDriverRule &Other) const
{
return m_VidPid == Other.m_VidPid &&
m_PortHub == Other.m_PortHub;
}

void Dump(LONG traceLevel = m_defaultDumpLevel) const;

CString& KeyName() { return m_KeyName; }

private:
ULONG m_VidPid;
ULONG m_PortHub;
CString m_KeyName; /* HKLM/CCS/Enum/USB/VidPid/Location Registry key path */

static LONG m_defaultDumpLevel;
DECLARE_CWDMLIST_ENTRY(CUsbDkFDriverRule);
};

class CDriverParamsRegistryPath final
{
public:
Expand Down Expand Up @@ -301,6 +336,9 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<USBDK
bool ShouldHideDevice(CUsbDkChildDevice &Device) const;
bool ShouldHide(const USB_DK_DEVICE_ID &DevId);

bool ShouldRawFiltDevice(CUsbDkChildDevice &Device, bool Is2ndCall);
bool ShouldRawFilt(const USB_DK_DEVICE_ID &DevId);

template <typename TDevID>
void NotifyRedirectionRemoved(const TDevID &Dev) const
{
Expand All @@ -312,6 +350,8 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<USBDK
bool NotifyRedirectorRemovalStarted(const USB_DK_DEVICE_ID &ID);
bool WaitForDetachment(const USB_DK_DEVICE_ID &ID);

NTSTATUS ReloadHasDriverList();

private:
NTSTATUS ReloadPersistentHideRules();

Expand All @@ -336,6 +376,13 @@ class CUsbDkControlDevice : private CWdfControlDevice, public CAllocatable<USBDK

NTSTATUS AddHideRuleToSet(const USB_DK_HIDE_RULE &UsbDkRule, HideRulesSet &Set);

/* DeviceID + LocationID list of "Function Driver" registry keys */
//typedef CWdmSet<CUsbDkFDriverRule, CLockedAccess, CNonCountingObject> FDriverRulesSet;
typedef CWdmSet<CUsbDkFDriverRule, CLockedAccess, CCountingObject> FDriverRulesSet;
FDriverRulesSet m_FDriversRules;
CString m_RootName;
bool m_FDriverInited = false; /* Set after m_RootName created. */

template <typename TPredicate, typename TFunctor>
bool UsbDevicesForEachIf(TPredicate Predicate, TFunctor Functor)
{ return m_FilterDevices.ForEach([&](CUsbDkFilterDevice* Dev){ return Dev->EnumerateChildrenIf(Predicate, Functor); }); }
Expand Down
74 changes: 73 additions & 1 deletion UsbDk/DeviceAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,41 @@ NTSTATUS CWdmDeviceAccess::QueryCapabilities(DEVICE_CAPABILITIES &Capabilities)
return status;
}

/* txType can be DeviceTextDescription or DeviceTextLocationInformation */
PWCHAR CWdmDeviceAccess::QueryDeviceText(DEVICE_TEXT_TYPE txType)
{
CIrp irp;

auto status = irp.Create(m_DevObj);

if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS! during IRP creation", status);
return nullptr;
}

irp.Configure([txType] (PIO_STACK_LOCATION s)
{
s->MajorFunction = IRP_MJ_PNP;
s->MinorFunction = IRP_MN_QUERY_DEVICE_TEXT;
s->Parameters.QueryDeviceText.DeviceTextType = txType;
});

status = irp.SendSynchronously();

if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS! during %!devtx! query", status, txType);
return nullptr;
}

PWCHAR txData;
irp.ReadResult([&txData](ULONG_PTR information)
{ txData = reinterpret_cast<PWCHAR>(information); });

return (txData != nullptr) ? MakeNonPagedDuplicateSz(txData) : nullptr;
}

SIZE_T CWdmDeviceAccess::GetIdBufferLength(BUS_QUERY_ID_TYPE idType, PWCHAR idData)
{
switch (idType)
Expand Down Expand Up @@ -186,6 +221,7 @@ bool CWdmDeviceAccess::QueryPowerData(CM_POWER_DATA& powerData)
#endif
}

#if 0
static void PowerRequestCompletion(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ UCHAR MinorFunction,
Expand All @@ -202,6 +238,7 @@ static void PowerRequestCompletion(
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVACCESS, "%!FUNC! -> D%d", PowerState.DeviceState - 1);
pev->Set();
}
#endif

PWCHAR CWdmDeviceAccess::MakeNonPagedDuplicate(BUS_QUERY_ID_TYPE idType, PWCHAR idData)
{
Expand All @@ -221,6 +258,24 @@ PWCHAR CWdmDeviceAccess::MakeNonPagedDuplicate(BUS_QUERY_ID_TYPE idType, PWCHAR
return static_cast<PWCHAR>(newIdData);
}

PWCHAR CWdmDeviceAccess::MakeNonPagedDuplicateSz(PWCHAR txData)
{
auto bufferLength = CRegSz::GetBufferLength(txData);

auto newIdData = ExAllocatePoolWithTag(USBDK_NON_PAGED_POOL, bufferLength, 'IDHR');
if (newIdData != nullptr)
{
RtlCopyMemory(newIdData, txData, bufferLength);
}
else
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Failed to allocate non-paged buffer for Sz");
}

ExFreePool(txData);
return static_cast<PWCHAR>(newIdData);
}

NTSTATUS CWdmDeviceAccess::QueryForInterface(const GUID &guid, __out INTERFACE &intf,
USHORT intfSize, USHORT intfVer, __in_opt PVOID intfCtx)
{
Expand Down Expand Up @@ -253,6 +308,7 @@ NTSTATUS CWdmDeviceAccess::QueryForInterface(const GUID &guid, __out INTERFACE &
NTSTATUS CWdmUsbDeviceAccess::Reset(bool ForceD0)
{
CIoControlIrp Irp;
#if 0 // #115 reports that this can cause a WDF_VIOLATION (10d) error code with some devices.
CM_POWER_DATA powerData;
if (ForceD0 && QueryPowerData(powerData) && powerData.PD_MostRecentPowerState != PowerDeviceD0)
{
Expand All @@ -266,6 +322,11 @@ NTSTATUS CWdmUsbDeviceAccess::Reset(bool ForceD0)
Event.Wait();
}
}
#else
ForceD0;
#endif

TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! About to sed IOCTL_INTERNAL_USB_CYCLE_PORT");

auto status = Irp.Create(m_DevObj, IOCTL_INTERNAL_USB_CYCLE_PORT);

Expand Down Expand Up @@ -362,7 +423,8 @@ USB_DK_DEVICE_SPEED UsbDkWdmUsbDeviceGetSpeed(PDEVICE_OBJECT DevObj, PDRIVER_OBJ

bool UsbDkGetWdmDeviceIdentity(const PDEVICE_OBJECT PDO,
CObjHolder<CRegText> *DeviceID,
CObjHolder<CRegText> *InstanceID)
CObjHolder<CRegText> *InstanceID,
CObjHolder<CRegText> *LocationID)
{
CWdmDeviceAccess pdoAccess(PDO);

Expand All @@ -386,6 +448,16 @@ bool UsbDkGetWdmDeviceIdentity(const PDEVICE_OBJECT PDO,
}
}

if (LocationID != nullptr)
{
*LocationID = pdoAccess.GetLocationID();
if (!(*LocationID) || (*LocationID)->empty())
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! No Location ID read");
return false;
}
}

return true;
}

Expand Down
6 changes: 5 additions & 1 deletion UsbDk/DeviceAccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,18 @@ class CWdmDeviceAccess
ULONG GetAddress();
CRegText *GetDeviceID() { return new CRegSz(QueryBusID(BusQueryDeviceID)); }
CRegText *GetInstanceID() { return new CRegSz(QueryBusID(BusQueryInstanceID)); }
CRegText *GetLocationID() { return new CRegSz(QueryDeviceText(DeviceTextLocationInformation)); }
bool QueryPowerData(CM_POWER_DATA& powerData);
protected:
PDEVICE_OBJECT m_DevObj;

private:
PWCHAR QueryBusID(BUS_QUERY_ID_TYPE idType);
NTSTATUS QueryCapabilities(DEVICE_CAPABILITIES &Capabilities);
PWCHAR QueryDeviceText(DEVICE_TEXT_TYPE txType);

static PWCHAR MakeNonPagedDuplicate(BUS_QUERY_ID_TYPE idType, PWCHAR idData);
static PWCHAR MakeNonPagedDuplicateSz(PWCHAR txData);
static SIZE_T GetIdBufferLength(BUS_QUERY_ID_TYPE idType, PWCHAR idData);
};

Expand Down Expand Up @@ -118,7 +121,8 @@ class CWdmUSBD

bool UsbDkGetWdmDeviceIdentity(const PDEVICE_OBJECT PDO,
CObjHolder<CRegText> *DeviceID,
CObjHolder<CRegText> *InstanceID = nullptr);
CObjHolder<CRegText> *InstanceID = nullptr,
CObjHolder<CRegText> *LocationID = nullptr);

USB_DK_DEVICE_SPEED UsbDkWdmUsbDeviceGetSpeed(PDEVICE_OBJECT PDO, PDRIVER_OBJECT DriverObject);

Expand Down
Loading

0 comments on commit 2233fde

Please sign in to comment.