diff --git a/UsbDk/FilterDevice.cpp b/UsbDk/FilterDevice.cpp index c5228b7..eb345f1 100644 --- a/UsbDk/FilterDevice.cpp +++ b/UsbDk/FilterDevice.cpp @@ -170,6 +170,51 @@ void CDeviceRelations::PushBack(PDEVICE_OBJECT Relation) m_Relations->Objects[m_PushPosition++] = Relation; } +void CUsbDkFilterDevice::DropRemovedDevices(const CDeviceRelations &Relations) +{ + m_ChildrenDevices.ForEachDetachedIf([&Relations](CUsbDkChildDevice *Child) { return !Relations.Contains(*Child); }, + [](CUsbDkChildDevice *Child) -> bool { delete Child; return true; }); +} + +void CUsbDkFilterDevice::AddNewDevices(const CDeviceRelations &Relations) +{ + Relations.ForEachIf([this](PDEVICE_OBJECT PDO){ return !IsChildRegistered(PDO); }, + [this](PDEVICE_OBJECT PDO){ RegisterNewChild(PDO); return true; }); +} + +void CUsbDkFilterDevice::RegisterNewChild(PDEVICE_OBJECT PDO) +{ + CWdmDeviceAccess pdoAccess(PDO); + CObjHolder DevID(pdoAccess.GetDeviceID()); + + if (!DevID || DevID->empty()) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! No Device IDs read"); + return; + } + + CObjHolder InstanceID(pdoAccess.GetInstanceID()); + + if (!InstanceID || InstanceID->empty()) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! No Instance ID read"); + return; + } + + CUsbDkChildDevice *Device = new CUsbDkChildDevice(DevID, InstanceID, PDO); + + if (Device == nullptr) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Cannot allocate child device instance"); + return; + } + + DevID.detach(); + InstanceID.detach(); + + m_ChildrenDevices.PushBack(Device); +} + void CUsbDkFilterDevice::ClearChildrenList() { m_ChildrenDevices.ForEachDetached([](CUsbDkChildDevice* Child) { delete Child; return true; }); diff --git a/UsbDk/FilterDevice.h b/UsbDk/FilterDevice.h index 9e9f7f5..2164acc 100644 --- a/UsbDk/FilterDevice.h +++ b/UsbDk/FilterDevice.h @@ -34,9 +34,12 @@ public: PCWCHAR InstanceID() const { return *m_InstanceID->begin(); } PDEVICE_OBJECT PDO() const { ObReferenceObject(m_PDO); return m_PDO; } - bool Match(PCWCHAR deviceID, PCWCHAR instanceID) + bool Match(PCWCHAR deviceID, PCWCHAR instanceID) const { return m_DeviceID->Match(deviceID) && m_InstanceID->Match(instanceID); } + bool Match(PDEVICE_OBJECT PDO) const + { return m_PDO == PDO; } + void Dump(); PLIST_ENTRY GetListEntry() @@ -55,6 +58,8 @@ private: CUsbDkChildDevice& operator= (const CUsbDkChildDevice&) = delete; }; +class CDeviceRelations; + class CUsbDkFilterDevice : private CWdfDevice, public CAllocatable { public: @@ -101,6 +106,12 @@ private: bool ShouldAttach(); void ClearChildrenList(); + void DropRemovedDevices(const CDeviceRelations &Relations); + void AddNewDevices(const CDeviceRelations &Relations); + bool IsChildRegistered(PDEVICE_OBJECT PDO) + { return !m_ChildrenDevices.ForEachIf([PDO](CUsbDkChildDevice *Child){ return Child->Match(PDO); }, ConstFalse); } + void RegisterNewChild(PDEVICE_OBJECT PDO); + CWdfWorkitem m_QDRCompletionWorkItem; PIRP m_QDRIrp = nullptr;