diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..2a8aefc --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,18 @@ +image: Visual Studio 2015 + +version: build-{build}-{branch} + +before_build: + - tools\AppVeyor\before-build.cmd + +build_script: buildAll.bat + +skip_commits: + message: /\[ci skip\]/ + +notifications: + - provider: Email + to: devel@daynix.com + on_build_success: false + on_build_failure: false + on_build_status_changed: true diff --git a/Documentation/Hider.txt b/Documentation/Hider.txt new file mode 100644 index 0000000..2a70f5b --- /dev/null +++ b/Documentation/Hider.txt @@ -0,0 +1,83 @@ +Short description of Device Hider feature: +The interface is described in UsbDkHelperHider.h +It includes basic and extended interfaces: + +1. Basic interface: +UsbDk_AddPersistentHideRule +UsbDk_DeletePersistentHideRule +UsbDk_AddHideRule +UsbDk_ClearHideRules + +Rule structure includes: +Class +BCD +Vendor ID +Product ID +Hide specifier (0 or 1), 0 is terminal, 1 continues for next rule + +Class describes device class as specified in device descriptor. +Checkers for these rules do not check classes of interfaces in multifunction devices, +i.e. +class match = (device class == rule class) or (rule class == -1) + +2. Extended interface +UsbDk_AddExtendedHideRule +UsbDk_AddExtendedPersistentHideRule +UsbDk_DeleteExtendedPersistentHideRule + +These API calls receive the same rule structure as basic API and +an additional parameter 'Rule Type', which can be +0 (USBDK_HIDER_RULE_DEFAULT) or 1 (USBDK_HIDER_RULE_DETERMINATIVE_TYPES) + +Using extended API with USBDK_HIDER_RULE_DEFAULT produces exactly the +same result as using basic API. + +Using USBDK_HIDER_RULE_DETERMINATIVE_TYPES forces different processing +of hiding rules: + +Rule structure includes the same fields: +Class (bitmask of device types to match) +BCD +Vendor ID +Product ID +Hide specifier (0 or 1), 0 is terminal, 1 continues for next rule + +Device type for each specific device is determined from device class as specified +in device descriptor and 'class' field in all the interface descriptors of all +device's configurations. + +Supported classes are: +USB_DEVICE_CLASS_AUDIO (0x1) -> USB_DEVICE_CLASS_AUDIO + +USB_DEVICE_CLASS_COMMUNICATIONS(0x2) +USB_DEVICE_CLASS_CDC_DATA(0xA) +USB_DEVICE_CLASS_WIRELESS_CONTROLLER(0xE0) -> USB_DEVICE_CLASS_COMMUNICATIONS + +USB_DEVICE_CLASS_PRINTER(0x7) -> USB_DEVICE_CLASS_PRINTER +USB_DEVICE_CLASS_STORAGE(0x8) -> USB_DEVICE_CLASS_STORAGE +USB_DEVICE_CLASS_VIDEO(0xE) -> USB_DEVICE_CLASS_VIDEO +USB_DEVICE_CLASS_AUDIO_VIDEO(0x10) -> USB_DEVICE_CLASS_AUDIO, USB_DEVICE_CLASS_VIDEO +USB_DEVICE_CLASS_HUMAN_INTERFACE(0x3) -> USB_DEVICE_CLASS_HUMAN_INTERFACE + +All other classes -> OTHER (31) + +Following classes are determinative (if the device belongs to one +of determinative types, all device types except of +determinative one are removed from device type bitmask): +The order of determinative types is: +USB_DEVICE_CLASS_PRINTER +USB_DEVICE_CLASS_COMMUNICATIONS +USB_DEVICE_CLASS_AUDIO +USB_DEVICE_CLASS_VIDEO + +Checkers for these rules check resulting set of device type and +device types of interfaces in multifunction devices, i.e. +Class match = (device type bitmask) & (rule class bitmask) != 0 + +Example of usage: +Rule.BCD = Rule.VID = Rule.PID = -1; +Rule.Hide = 1; +Rule.Class = (1 << USB_DEVICE_CLASS_STORAGE) | (1 << USB_DEVICE_CLASS_PRINTER); +UsbDk_AddExtendedPersistentHideRule(&Rule, USBDK_HIDER_RULE_DETERMINATIVE_TYPES); +This call will Hide all the device that determined as being mass storage +devices or printer devices. diff --git a/MAINTAINERS b/MAINTAINERS index 1446076..4e1b503 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,4 +1,6 @@ -Maintained by Dmitry Fleytman +Maintained by Daynix Computing ------------------------------ -M: Dmitry Fleytman -M: Dmitry Fleytman +M: Yuri Benditovich +M: Yuri Benditovich +M: Yan Vugenfirer +M: Yan Vugenfirer diff --git a/README.md b/README.md index 238f57e..f8317f1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://ci.appveyor.com/api/projects/status/p3s6bdbx8mq8o0hu?svg=true)](https://ci.appveyor.com/api/projects/status/p3s6bdbx8mq8o0hu?svg=true) + # UsbDk UsbDk (USB Development Kit) is a open-source library for Windows meant diff --git a/Tools/AppVeyor/before-build.cmd b/Tools/AppVeyor/before-build.cmd new file mode 100644 index 0000000..c3258d1 --- /dev/null +++ b/Tools/AppVeyor/before-build.cmd @@ -0,0 +1,5 @@ +@echo off +pushd "%~dp0" +curl -L -s https://drive.google.com/uc?id=17ZK6a1kxhTR-YOkWpAOqNJZA7UBUGkmu --output Microsoft.DriverKit.Build.Tasks.14.0.dll +copy /y Microsoft.DriverKit.Build.Tasks.14.0.dll "C:\Program Files (x86)\Windows Kits\10\build\bin" +popd diff --git a/Tools/Driver.Initial.props b/Tools/Driver.Initial.props new file mode 100644 index 0000000..20189b1 --- /dev/null +++ b/Tools/Driver.Initial.props @@ -0,0 +1,31 @@ + + + + + + + + + + + <_NT_TARGET_VERSION>0x0A00 + + + <_NT_TARGET_VERSION>0x0603 + + + <_NT_TARGET_VERSION>0x0602 + + + <_NT_TARGET_VERSION>0x0601 + + + diff --git a/Tools/Installer/UsbDkInstaller.wxs b/Tools/Installer/UsbDkInstaller.wxs index 677060f..3c3105f 100644 --- a/Tools/Installer/UsbDkInstaller.wxs +++ b/Tools/Installer/UsbDkInstaller.wxs @@ -117,9 +117,11 @@ + + diff --git a/Tools/Installer/buildmsi.bat b/Tools/Installer/buildmsi.bat index 06d9647..a0f5c9b 100644 --- a/Tools/Installer/buildmsi.bat +++ b/Tools/Installer/buildmsi.bat @@ -9,9 +9,9 @@ pushd ..\..\Install_Debug\x86 del *.msi *.wixobj *.wixpdb -"C:\Program Files (x86)\WiX Toolset v3.8\bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk_Debug.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=%DEBUG_CFG% +"%WIX%bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk_Debug.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=%DEBUG_CFG% if !ERRORLEVEL! NEQ 0 exit /B 1 -"C:\Program Files (x86)\WiX Toolset v3.8\bin\light.exe" UsbDk_Debug.wixobj -out UsbDk_Debug_%UsbDkVersion%_x86.msi -sw1076 +"%WIX%bin\light.exe" UsbDk_Debug.wixobj -out UsbDk_Debug_%UsbDkVersion%_x86.msi -sw1076 if !ERRORLEVEL! NEQ 0 exit /B 1 popd @@ -20,9 +20,9 @@ pushd ..\..\Install_Debug\x64 del *.msi *.wixobj *.wixpdb -"C:\Program Files (x86)\WiX Toolset v3.8\bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk_Debug.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=%DEBUG_CFG% -dUsbDk64Bit=1 +"%WIX%bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk_Debug.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=%DEBUG_CFG% -dUsbDk64Bit=1 if !ERRORLEVEL! NEQ 0 exit /B 1 -"C:\Program Files (x86)\WiX Toolset v3.8\bin\light.exe" UsbDk_Debug.wixobj -out UsbDk_Debug_%UsbDkVersion%_x64.msi -sw1076 +"%WIX%bin\light.exe" UsbDk_Debug.wixobj -out UsbDk_Debug_%UsbDkVersion%_x64.msi -sw1076 if !ERRORLEVEL! NEQ 0 exit /B 1 popd @@ -31,9 +31,9 @@ pushd ..\..\Install\x86 del *.msi *.wixobj *.wixpdb -"C:\Program Files (x86)\WiX Toolset v3.8\bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=Release +"%WIX%bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=Release if !ERRORLEVEL! NEQ 0 exit /B 1 -"C:\Program Files (x86)\WiX Toolset v3.8\bin\light.exe" UsbDk.wixobj -out UsbDk_%UsbDkVersion%_x86.msi -sw1076 +"%WIX%bin\light.exe" UsbDk.wixobj -out UsbDk_%UsbDkVersion%_x86.msi -sw1076 if !ERRORLEVEL! NEQ 0 exit /B 1 popd @@ -42,9 +42,9 @@ pushd ..\..\Install\x64 del *.msi *.wixobj *.wixpdb -"C:\Program Files (x86)\WiX Toolset v3.8\bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=Release -dUsbDk64Bit=1 +"%WIX%bin\candle.exe" ..\..\Tools\Installer\UsbDkInstaller.wxs -out UsbDk.wixobj -dUsbDkVersion=%UsbDkVersion% -dConfig=Release -dUsbDk64Bit=1 if !ERRORLEVEL! NEQ 0 exit /B 1 -"C:\Program Files (x86)\WiX Toolset v3.8\bin\light.exe" UsbDk.wixobj -out UsbDk_%UsbDkVersion%_x64.msi -sw1076 +"%WIX%bin\light.exe" UsbDk.wixobj -out UsbDk_%UsbDkVersion%_x64.msi -sw1076 if !ERRORLEVEL! NEQ 0 exit /B 1 popd diff --git a/UsbDk Package/UsbDk Package.vcxproj b/UsbDk Package/UsbDk Package.vcxproj index e726e30..621b988 100644 --- a/UsbDk Package/UsbDk Package.vcxproj +++ b/UsbDk Package/UsbDk Package.vcxproj @@ -381,6 +381,7 @@ Package true + diff --git a/UsbDk/ControlDevice.cpp b/UsbDk/ControlDevice.cpp index 203f073..a244a31 100644 --- a/UsbDk/ControlDevice.cpp +++ b/UsbDk/ControlDevice.cpp @@ -314,15 +314,35 @@ void CUsbDkControlDevice::UnregisterHiddenDevice(CUsbDkFilterDevice &FilterDevic m_HiddenDevices.Remove(&FilterDevice); } -bool CUsbDkControlDevice::ShouldHide(const USB_DEVICE_DESCRIPTOR &DevDescriptor) const +bool CUsbDkControlDevice::ShouldHideDevice(CUsbDkChildDevice &Device) const { + const USB_DEVICE_DESCRIPTOR &DevDescriptor = Device.DeviceDescriptor(); auto Hide = false; - + ULONG classes = Device.ClassesBitMask(); const auto &HideVisitor = [&DevDescriptor, &Hide](CUsbDkHideRule *Entry) -> bool { + Entry->Dump(TRACE_LEVEL_VERBOSE); + TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_FILTERDEVICE, + "checking old hide rules %X:%X", DevDescriptor.idVendor, DevDescriptor.idProduct); if (Entry->Match(DevDescriptor)) { Hide = Entry->ShouldHide(); + TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_FILTERDEVICE, "Match: hide = %d", Hide); + return !Entry->ForceDecision(); + } + + return true; + }; + + const auto &HideVisitorExt = [&DevDescriptor, &Hide, classes](CUsbDkHideRule *Entry) -> bool + { + Entry->Dump(TRACE_LEVEL_VERBOSE); + TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_FILTERDEVICE, + "checking ext hide rules %X:%X", DevDescriptor.idVendor, DevDescriptor.idProduct); + if (Entry->Match(classes, DevDescriptor)) + { + Hide = Entry->ShouldHide(); + TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_FILTERDEVICE, "Match: hide = %d", Hide); return !Entry->ForceDecision(); } @@ -332,9 +352,29 @@ bool CUsbDkControlDevice::ShouldHide(const USB_DEVICE_DESCRIPTOR &DevDescriptor) const_cast(&m_HideRules)->ForEach(HideVisitor); const_cast(&m_PersistentHideRules)->ForEach(HideVisitor); + if (!Hide) + { + const_cast(&m_ExtHideRules)->ForEach(HideVisitorExt); + const_cast(&m_PersistentExtHideRules)->ForEach(HideVisitorExt); + } + return Hide; } +bool CUsbDkControlDevice::ShouldHide(const USB_DK_DEVICE_ID &DevId) +{ + bool b = false; + + EnumUsbDevicesByID(DevId, + [&b, this](CUsbDkChildDevice *Child) -> bool + { + b = ShouldHideDevice(*Child); + return false; + }); + + return b; +} + bool CUsbDkControlDevice::EnumerateDevices(USB_DK_DEVICE_INFO *outBuff, size_t numberAllocatedDevices, size_t &numberExistingDevices) { numberExistingDevices = 0; @@ -411,7 +451,7 @@ PDEVICE_OBJECT CUsbDkControlDevice::GetPDOByDeviceID(const USB_DK_DEVICE_ID &Dev return PDO; } -NTSTATUS CUsbDkControlDevice::ResetUsbDevice(const USB_DK_DEVICE_ID &DeviceID) +NTSTATUS CUsbDkControlDevice::ResetUsbDevice(const USB_DK_DEVICE_ID &DeviceID, bool ForceD0) { PDEVICE_OBJECT PDO = GetPDOByDeviceID(DeviceID); if (PDO == nullptr) @@ -420,7 +460,7 @@ NTSTATUS CUsbDkControlDevice::ResetUsbDevice(const USB_DK_DEVICE_ID &DeviceID) } CWdmUsbDeviceAccess pdoAccess(PDO); - auto status = pdoAccess.Reset(); + auto status = pdoAccess.Reset(ForceD0); ObDereferenceObject(PDO); return status; @@ -667,7 +707,7 @@ void CUsbDkControlDevice::AddRedirectRollBack(const USB_DK_DEVICE_ID &DeviceId, return; } - auto resetRes = ResetUsbDevice(DeviceId); + auto resetRes = ResetUsbDevice(DeviceId, false); if (!NT_SUCCESS(resetRes)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! Roll-back reset failed. %!STATUS!", resetRes); @@ -691,11 +731,13 @@ NTSTATUS CUsbDkControlDevice::AddRedirect(const USB_DK_DEVICE_ID &DeviceId, HAND { return addRes; } + Redirection->AddRef(); + CObjHolder dereferencer(Redirection); TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "%!FUNC! Success. New redirections list:"); m_Redirections.Dump(); - auto resetRes = ResetUsbDevice(DeviceId); + auto resetRes = ResetUsbDevice(DeviceId, true); if (!NT_SUCCESS(resetRes)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! Reset after start redirection failed. %!STATUS!", resetRes); @@ -815,6 +857,14 @@ public: return status; } + DWORD32 val; + status = ReadDwordValue(USBDK_HIDE_RULE_TYPE, val); + if (!NT_SUCCESS(status)) + { + return status; + } + Rule.Type = val; + status = ReadDwordMaskValue(USBDK_HIDE_RULE_VID, Rule.VID); if (!NT_SUCCESS(status)) { @@ -911,6 +961,7 @@ private: NTSTATUS CUsbDkControlDevice::ReloadPersistentHideRules() { m_PersistentHideRules.Clear(); + m_PersistentExtHideRules.Clear(); CHideRulesRegKey RulesKey; auto status = RulesKey.Open(); @@ -978,7 +1029,7 @@ NTSTATUS CUsbDkControlDevice::RemoveRedirect(const USB_DK_DEVICE_ID &DeviceId) { if (NotifyRedirectorRemovalStarted(DeviceId)) { - auto res = ResetUsbDevice(DeviceId); + auto res = ResetUsbDevice(DeviceId, false); if (NT_SUCCESS(res)) { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, @@ -1030,7 +1081,8 @@ bool CUsbDkControlDevice::NotifyRedirectorAttached(CRegText *DeviceID, CRegText bool CUsbDkControlDevice::NotifyRedirectorRemovalStarted(const USB_DK_DEVICE_ID &ID) { - return m_Redirections.ModifyOne(&ID, [](CUsbDkRedirection *R){ R->NotifyRedirectionRemovalStarted(); }); + ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId(); + return m_Redirections.ModifyOne(&ID, [](CUsbDkRedirection *R){ R->NotifyRedirectionRemovalStarted(); }, pid); } bool CUsbDkControlDevice::WaitForDetachment(const USB_DK_DEVICE_ID &ID) @@ -1061,13 +1113,20 @@ NTSTATUS CUsbDkRedirection::Create(const USB_DK_DEVICE_ID &Id) return m_InstanceID.Create(Id.InstanceID); } -void CUsbDkRedirection::Dump() const +void CUsbDkRedirection::Dump(LPCSTR message) const { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, - "%!FUNC! Redirect: DevID: %wZ, InstanceID: %wZ", + "%!FUNC! %s DevID: %wZ, InstanceID: %wZ", + message, m_DeviceID, m_InstanceID); } +bool CUsbDkRedirection::MatchProcess(ULONG pid) +{ + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_WDFDEVICE, "%!FUNC! pid 0x%X, owner 0x%X", pid, m_OwnerPid); + return pid == m_OwnerPid; +} + void CUsbDkRedirection::NotifyRedirectorCreated(CUsbDkFilterDevice *RedirectorDevice) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! Redirector created for"); @@ -1148,9 +1207,18 @@ NTSTATUS CUsbDkRedirection::CreateRedirectorHandle(HANDLE RequestorProcess, PHAN do { + if (IsPreparedForRemove()) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_WDFDEVICE, "%!FUNC!: device already marked for removal"); + status = STATUS_DEVICE_REMOVED; + break; + } status = m_RedirectorDevice->CreateUserModeHandle(RequestorProcess, ObjectHandle); if (NT_SUCCESS(status)) { + ULONG pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId(); + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_WDFDEVICE, "%!FUNC! done for process 0x%X", pid); + m_OwnerPid = pid; return status; } @@ -1161,9 +1229,10 @@ NTSTATUS CUsbDkRedirection::CreateRedirectorHandle(HANDLE RequestorProcess, PHAN return status; } -void CUsbDkHideRule::Dump() const +LONG CUsbDkHideRule::m_defaultDumpLevel = TRACE_LEVEL_INFORMATION; +void CUsbDkHideRule::Dump(LONG traceLevel) const { - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "%!FUNC! Hide: %!bool!, C: %08X, V: %08X, P: %08X, BCD: %08X", + TraceEvents(traceLevel, TRACE_CONTROLDEVICE, "%!FUNC! Hide: %!bool!, C: %08X, V: %08X, P: %08X, BCD: %08X", m_Hide, m_Class, m_VID, m_PID, m_BCD); } @@ -1198,3 +1267,29 @@ void CDriverParamsRegistryPath::Destroy() } CDriverParamsRegistryPath::CAllocatablePath *CDriverParamsRegistryPath::m_Path = nullptr; + +NTSTATUS CUsbDkControlDevice::AddHideRule(const USB_DK_HIDE_RULE &UsbDkRule) +{ + if (UsbDkRule.Type == USBDK_HIDER_RULE_DEFAULT) + { + return AddHideRuleToSet(UsbDkRule, m_HideRules); + } + else if (UsbDkRule.Type == USBDK_HIDER_RULE_DETERMINATIVE_TYPES) + { + return AddHideRuleToSet(UsbDkRule, m_ExtHideRules); + } + return STATUS_INVALID_PARAMETER; +} + +NTSTATUS CUsbDkControlDevice::AddPersistentHideRule(const USB_DK_HIDE_RULE &UsbDkRule) +{ + if (UsbDkRule.Type == USBDK_HIDER_RULE_DEFAULT) + { + return AddHideRuleToSet(UsbDkRule, m_PersistentHideRules); + } + else if (UsbDkRule.Type == USBDK_HIDER_RULE_DETERMINATIVE_TYPES) + { + return AddHideRuleToSet(UsbDkRule, m_PersistentExtHideRules); + } + return STATUS_INVALID_PARAMETER; +} diff --git a/UsbDk/ControlDevice.h b/UsbDk/ControlDevice.h index 2747136..9223036 100644 --- a/UsbDk/ControlDevice.h +++ b/UsbDk/ControlDevice.h @@ -117,6 +117,14 @@ public: MatchCharacteristic(m_BCD, Descriptor.bcdDevice); } + bool Match(ULONG UsbClassesBitmask, const USB_DEVICE_DESCRIPTOR &Descriptor) const + { + return (UsbClassesBitmask & m_Class) && + MatchCharacteristic(m_VID, Descriptor.idVendor) && + MatchCharacteristic(m_PID, Descriptor.idProduct) && + MatchCharacteristic(m_BCD, Descriptor.bcdDevice); + } + bool ShouldHide() const { return m_Hide; @@ -138,7 +146,7 @@ public: } - void Dump() const; + void Dump(LONG traceLevel = m_defaultDumpLevel) const; private: bool MatchCharacteristic(ULONG CharacteristicFilter, ULONG CharacteristicValue) const @@ -152,7 +160,7 @@ private: ULONG m_VID; ULONG m_PID; ULONG m_BCD; - + static LONG m_defaultDumpLevel; DECLARE_CWDMLIST_ENTRY(CUsbDkHideRule); }; @@ -170,7 +178,7 @@ public: bool operator==(const CUsbDkChildDevice &Dev) const; bool operator==(const CUsbDkRedirection &Other) const; - void Dump() const; + void Dump(LPCSTR message = " ") const; void NotifyRedirectorCreated(CUsbDkFilterDevice *RedirectorDevice); void NotifyRedirectionRemoved(); @@ -182,6 +190,8 @@ public: bool IsPreparedForRemove() const { return m_RemovalInProgress; } + bool MatchProcess(ULONG pid); + NTSTATUS WaitForAttachment() { return m_RedirectionCreated.Wait(true, -SecondsTo100Nanoseconds(120)); } @@ -192,6 +202,7 @@ public: private: ~CUsbDkRedirection() { + Dump("Deleting "); if (m_RedirectorDevice != nullptr) { m_RedirectorDevice->Release(); @@ -207,6 +218,7 @@ private: CWdmEvent m_RedirectionCreated; CWdmEvent m_RedirectionRemoved; CUsbDkFilterDevice *m_RedirectorDevice = nullptr; + ULONG m_OwnerPid = 0; bool m_RemovalInProgress = false; @@ -254,13 +266,11 @@ public: { return ReloadPersistentHideRules(); } bool EnumerateDevices(USB_DK_DEVICE_INFO *outBuff, size_t numberAllocatedDevices, size_t &numberExistingDevices); - NTSTATUS ResetUsbDevice(const USB_DK_DEVICE_ID &DeviceId); + NTSTATUS ResetUsbDevice(const USB_DK_DEVICE_ID &DeviceId, bool ForceD0); NTSTATUS AddRedirect(const USB_DK_DEVICE_ID &DeviceId, HANDLE RequestorProcess, PHANDLE ObjectHandle); - NTSTATUS AddHideRule(const USB_DK_HIDE_RULE &UsbDkRule) - { return AddHideRuleToSet(UsbDkRule, m_HideRules); } - NTSTATUS AddPersistentHideRule(const USB_DK_HIDE_RULE &UsbDkRule) - { return AddHideRuleToSet(UsbDkRule, m_PersistentHideRules); } + NTSTATUS AddHideRule(const USB_DK_HIDE_RULE &UsbDkRule); + NTSTATUS AddPersistentHideRule(const USB_DK_HIDE_RULE &UsbDkRule); void ClearHideRules(); @@ -288,7 +298,8 @@ public: return !DontRedirect; } - bool ShouldHide(const USB_DEVICE_DESCRIPTOR &DevDescriptor) const; + bool ShouldHideDevice(CUsbDkChildDevice &Device) const; + bool ShouldHide(const USB_DK_DEVICE_ID &DevId); template void NotifyRedirectionRemoved(const TDevID &Dev) const @@ -320,6 +331,8 @@ private: typedef CWdmSet HideRulesSet; HideRulesSet m_HideRules; HideRulesSet m_PersistentHideRules; + HideRulesSet m_ExtHideRules; + HideRulesSet m_PersistentExtHideRules; NTSTATUS AddHideRuleToSet(const USB_DK_HIDE_RULE &UsbDkRule, HideRulesSet &Set); diff --git a/UsbDk/DeviceAccess.cpp b/UsbDk/DeviceAccess.cpp index 657c0b9..6810a18 100644 --- a/UsbDk/DeviceAccess.cpp +++ b/UsbDk/DeviceAccess.cpp @@ -168,6 +168,41 @@ SIZE_T CWdmDeviceAccess::GetIdBufferLength(BUS_QUERY_ID_TYPE idType, PWCHAR idDa } } +bool CWdmDeviceAccess::QueryPowerData(CM_POWER_DATA& powerData) +{ + powerData.PD_Size = sizeof(powerData); +#if !TARGET_OS_WIN_XP + ULONG dummy; + DEVPROPTYPE propType; + auto status = IoGetDevicePropertyData(m_DevObj, &DEVPKEY_Device_PowerData, LOCALE_NEUTRAL, 0, + sizeof(powerData), &powerData, &dummy, &propType); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS!", status); + } + return NT_SUCCESS(status); +#else + return false; +#endif +} + +static void PowerRequestCompletion( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ UCHAR MinorFunction, + _In_ POWER_STATE PowerState, + _In_opt_ PVOID Context, + _In_ PIO_STATUS_BLOCK IoStatus +) +{ + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(MinorFunction); + UNREFERENCED_PARAMETER(PowerState); + UNREFERENCED_PARAMETER(IoStatus); + CWdmEvent *pev = (CWdmEvent *)Context; + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVACCESS, "%!FUNC! -> D%d", PowerState.DeviceState - 1); + pev->Set(); +} + PWCHAR CWdmDeviceAccess::MakeNonPagedDuplicate(BUS_QUERY_ID_TYPE idType, PWCHAR idData) { auto bufferLength = GetIdBufferLength(idType, idData); @@ -215,9 +250,23 @@ NTSTATUS CWdmDeviceAccess::QueryForInterface(const GUID &guid, __out INTERFACE & return status; } -NTSTATUS CWdmUsbDeviceAccess::Reset() +NTSTATUS CWdmUsbDeviceAccess::Reset(bool ForceD0) { CIoControlIrp Irp; + CM_POWER_DATA powerData; + if (ForceD0 && QueryPowerData(powerData) && powerData.PD_MostRecentPowerState != PowerDeviceD0) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVACCESS, "%!FUNC! device power state D%d", powerData.PD_MostRecentPowerState - 1); + POWER_STATE PowerState; + CWdmEvent Event; + PowerState.DeviceState = PowerDeviceD0; + auto status = PoRequestPowerIrp(m_DevObj, IRP_MN_SET_POWER, PowerState, PowerRequestCompletion, &Event, NULL); + if (NT_SUCCESS(status)) + { + Event.Wait(); + } + } + auto status = Irp.Create(m_DevObj, IOCTL_INTERNAL_USB_CYCLE_PORT); if (!NT_SUCCESS(status)) diff --git a/UsbDk/DeviceAccess.h b/UsbDk/DeviceAccess.h index 5520210..0749102 100644 --- a/UsbDk/DeviceAccess.h +++ b/UsbDk/DeviceAccess.h @@ -52,7 +52,7 @@ public: ULONG GetAddress(); CRegText *GetDeviceID() { return new CRegSz(QueryBusID(BusQueryDeviceID)); } CRegText *GetInstanceID() { return new CRegSz(QueryBusID(BusQueryInstanceID)); } - + bool QueryPowerData(CM_POWER_DATA& powerData); protected: PDEVICE_OBJECT m_DevObj; @@ -71,7 +71,7 @@ public: : CWdmDeviceAccess(WdmDevice) { } - NTSTATUS Reset(); + NTSTATUS Reset(bool ForceD0); NTSTATUS GetDeviceDescriptor(USB_DEVICE_DESCRIPTOR &Descriptor); NTSTATUS GetConfigurationDescriptor(UCHAR Index, USB_CONFIGURATION_DESCRIPTOR &Descriptor, size_t Length); diff --git a/UsbDk/FilterDevice.cpp b/UsbDk/FilterDevice.cpp index ee04720..22d4383 100644 --- a/UsbDk/FilterDevice.cpp +++ b/UsbDk/FilterDevice.cpp @@ -83,7 +83,11 @@ NTSTATUS CUsbDkFilterDeviceInit::Configure(ULONG InstanceNumber) SetIoInCallerContextCallback([](_In_ WDFDEVICE Device, WDFREQUEST Request) { return Strategy(Device)->IoInCallerContext(Device, Request); }); - SetFileEventCallbacks(WDF_NO_EVENT_CALLBACK, + SetFileEventCallbacks([](_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDFFILEOBJECT FileObject) + { + UNREFERENCED_PARAMETER(FileObject); + UsbDkFilterGetContext(Device)->UsbDkFilter->OnFileCreate(Request); + }, [](_In_ WDFFILEOBJECT FileObject) { WDFDEVICE Device = WdfFileObjectGetDevice(FileObject); @@ -314,8 +318,33 @@ void CUsbDkHubFilterStrategy::RegisterNewChild(PDEVICE_OBJECT PDO) { CWdmUsbDeviceAccess pdoAccess(PDO); - auto Port = pdoAccess.GetAddress(); + // in case when the device is composite and one of interfaces installed + // under USB class and creates child device (example is composite USB with + // more than one interface and one of them is CD) the PDO can be non-USB + // device. Sending USB requests to it may be problematic as sending URB + // is just internal device control with trivial IOCTL code. + // Before trying to initialize it as USB device we check it is really one. + CObjHolder DevID; + CObjHolder InstanceID; + if (!UsbDkGetWdmDeviceIdentity(PDO, &DevID, &InstanceID)) + { + TraceEvents(TRACE_LEVEL_ERROR, TRACE_FILTERDEVICE, "%!FUNC! Cannot query device identity"); + return; + } + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Registering new child (PDO: %p):", PDO); + DevID->Dump(); + InstanceID->Dump(); + + // Not a USB device -> do not register + if (!DevID->MatchPrefix(L"USB\\")) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Not a usb device, skip child registration"); + return; + } + + auto Port = pdoAccess.GetAddress(); if (Port == CWdmDeviceAccess::NO_ADDRESS) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_FILTERDEVICE, "%!FUNC! Cannot read device port number"); @@ -337,24 +366,14 @@ void CUsbDkHubFilterStrategy::RegisterNewChild(PDEVICE_OBJECT PDO) return; } - CObjHolder DevID; - CObjHolder InstanceID; - if (!UsbDkGetWdmDeviceIdentity(PDO, &DevID, &InstanceID)) +#if (NTDDI_VERSION == NTDDI_WIN7) + // recheck on Win7, superspeed indication as on Win8 might be not available + if (Speed == HighSpeed && DevDescriptor.bcdUSB >= 0x300) { - TraceEvents(TRACE_LEVEL_ERROR, TRACE_FILTERDEVICE, "%!FUNC! Cannot query device identity"); - return; - } - - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Registering new child (PDO: %p):", PDO); - DevID->Dump(); - InstanceID->Dump(); - - // Not a USB device -> do not register - if (!DevID->MatchPrefix(L"USB\\")) - { - TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Not a usb device, skip child registration"); - return; + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! superspeed assigned according to BCD field"); + Speed = SuperSpeed; } +#endif CUsbDkChildDevice::TDescriptorsCache CfgDescriptors(DevDescriptor.bNumConfigurations); @@ -424,7 +443,7 @@ bool CUsbDkHubFilterStrategy::FetchConfigurationDescriptors(CWdmUsbDeviceAccess void CUsbDkHubFilterStrategy::ApplyRedirectionPolicy(CUsbDkChildDevice &Device) { if (m_ControlDevice->ShouldRedirect(Device) || - m_ControlDevice->ShouldHide(Device.DeviceDescriptor())) + m_ControlDevice->ShouldHideDevice(Device)) { if (Device.AttachToDeviceStack()) { @@ -460,6 +479,23 @@ bool CUsbDkChildDevice::AttachToDeviceStack() return true; } +void CUsbDkFilterDevice::OnFileCreate(WDFREQUEST Request) +{ + CWdfRequest r(Request); + WdfRequestFormatRequestUsingCurrentType(Request); + // in the log we'll see which process created the file + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC!"); + r.SendWithCompletion(IOTarget(), [](WDFREQUEST Request, WDFIOTARGET Target, PWDF_REQUEST_COMPLETION_PARAMS Params, WDFCONTEXT Context) + { + UNREFERENCED_PARAMETER(Target); + CWdfRequest r(Request); + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%s: completed", (LPCSTR)Context); + r.SetStatus(Params->IoStatus.Status); + r.SetBytesWritten(Params->IoStatus.Information); + }, + __FUNCTION__); +} + NTSTATUS CUsbDkFilterDevice::AttachToStack(WDFDRIVER Driver) { PAGED_CODE(); @@ -486,7 +522,7 @@ NTSTATUS CUsbDkFilterDevice::DefineStrategy() return status; } - if (!m_Strategy.SelectStrategy(WdmObject())) + if (!m_Strategy.SelectStrategy(LowerDeviceObject())) { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Not attached"); return STATUS_NOT_SUPPORTED; @@ -525,6 +561,11 @@ NTSTATUS CUsbDkFilterDevice::Create(PWDFDEVICE_INIT DevInit) TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Failed to create device"); return status; } + if (!LowerDeviceObject()) + { + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! No lower device, skip"); + return STATUS_INVALID_DEVICE_STATE; + } auto deviceContext = UsbDkFilterGetContext(m_Device); deviceContext->UsbDkFilter = this; @@ -626,7 +667,7 @@ bool CUsbDkFilterDevice::CStrategist::SelectStrategy(PDEVICE_OBJECT DevObj) } // Should be hidden -> hider strategy - if (m_Strategy->GetControlDevice()->ShouldHide(DevDescr)) + if (m_Strategy->GetControlDevice()->ShouldHide(ID)) { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Assigning hidden USB device strategy"); m_Strategy->Delete(); @@ -646,3 +687,115 @@ size_t CUsbDkFilterDevice::CStrategist::GetRequestContextSize() max(CUsbDkHubFilterStrategy::GetRequestContextSize(), CUsbDkRedirectorStrategy::GetRequestContextSize())); } + +static ULONG InterfaceTypeMask(UCHAR bClass) { + switch (bClass) { + case USB_DEVICE_CLASS_AUDIO: + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class 0x%X -> audio", bClass); + return 1 << USB_DEVICE_CLASS_AUDIO; + case USB_DEVICE_CLASS_COMMUNICATIONS: + case USB_DEVICE_CLASS_CDC_DATA: + case USB_DEVICE_CLASS_WIRELESS_CONTROLLER: + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class 0x%X -> network", bClass); + return 1 << USB_DEVICE_CLASS_COMMUNICATIONS; + case USB_DEVICE_CLASS_PRINTER: + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class 0x%X -> printer", bClass); + return 1 << USB_DEVICE_CLASS_PRINTER; + case USB_DEVICE_CLASS_STORAGE: + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class 0x%X -> storage", bClass); + return 1 << USB_DEVICE_CLASS_STORAGE; + case USB_DEVICE_CLASS_VIDEO: + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class 0x%X -> video", bClass); + return 1 << USB_DEVICE_CLASS_VIDEO; + case USB_DEVICE_CLASS_AUDIO_VIDEO: + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class 0x%X -> audio/video", bClass); + return (1 << USB_DEVICE_CLASS_VIDEO) | + (1 << USB_DEVICE_CLASS_AUDIO); + case USB_DEVICE_CLASS_HUB: + return (1 << USB_DEVICE_CLASS_HUB); + case USB_DEVICE_CLASS_HUMAN_INTERFACE: + return (1 << USB_DEVICE_CLASS_HUMAN_INTERFACE); + default: + return 1U << 31; + } +} + +static PUSB_INTERFACE_DESCRIPTOR FindNextInterface(PUSB_CONFIGURATION_DESCRIPTOR cfg, ULONG& offset) +{ + PUSB_COMMON_DESCRIPTOR desc; + if (offset >= cfg->wTotalLength) + return NULL; + do { + if (offset + sizeof(*desc) > cfg->wTotalLength) + return NULL; + desc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)cfg + offset); + if (desc->bLength + offset > cfg->wTotalLength) + return NULL; + offset += desc->bLength; + if (desc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { + return (PUSB_INTERFACE_DESCRIPTOR)desc; + } + } while (1); +} + +void CUsbDkChildDevice::DetermineDeviceClasses() +{ + if (m_DevDescriptor.bDeviceClass) + { + m_ClassMaskForExtHider |= InterfaceTypeMask(m_DevDescriptor.bDeviceClass); + } + + USB_CONFIGURATION_DESCRIPTOR cfg; + for (UCHAR index = 0; index < m_CfgDescriptors.Size(); ++index) + { + if (ConfigurationDescriptor(index, cfg, sizeof(cfg))) + { + PVOID buffer = ExAllocatePoolWithTag(USBDK_NON_PAGED_POOL, cfg.wTotalLength, 'CFGD'); + if (buffer) + { + USB_CONFIGURATION_DESCRIPTOR *p = (USB_CONFIGURATION_DESCRIPTOR *)buffer; + if (ConfigurationDescriptor(index, *p, cfg.wTotalLength)) + { + ULONG offset = 0; + PUSB_INTERFACE_DESCRIPTOR intf_desc; + while (true) + { + intf_desc = FindNextInterface(p, offset); + if (!intf_desc) + break; + m_ClassMaskForExtHider |= InterfaceTypeMask(intf_desc->bInterfaceClass); + } + } + ExFreePool(buffer); + } + } + } +#define SINGLE_DETERMINATIVE_CLASS +#if defined(SINGLE_DETERMINATIVE_CLASS) + // only one determinative type present in final mask + if (m_ClassMaskForExtHider & (1 << USB_DEVICE_CLASS_PRINTER)) + { + m_ClassMaskForExtHider = 1 << USB_DEVICE_CLASS_PRINTER; + } + else if (m_ClassMaskForExtHider & (1 << USB_DEVICE_CLASS_COMMUNICATIONS)) + { + m_ClassMaskForExtHider = 1 << USB_DEVICE_CLASS_COMMUNICATIONS; + } + else if (m_ClassMaskForExtHider & ((1 << USB_DEVICE_CLASS_AUDIO) | (1 << USB_DEVICE_CLASS_VIDEO))) + { + m_ClassMaskForExtHider &= (1 << USB_DEVICE_CLASS_AUDIO) | (1 << USB_DEVICE_CLASS_VIDEO); + } +#else + // all the determinative types present in final mask + ULONG determinativeMask = + (1 << USB_DEVICE_CLASS_PRINTER) | + (1 << USB_DEVICE_CLASS_COMMUNICATIONS) | + (1 << USB_DEVICE_CLASS_AUDIO) | + (1 << USB_DEVICE_CLASS_VIDEO); + if (m_ClassMaskForExtHider & determinativeMask) + { + m_ClassMaskForExtHider &= determinativeMask; + } +#endif + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "Class mask %08X", m_ClassMaskForExtHider); +} diff --git a/UsbDk/FilterDevice.h b/UsbDk/FilterDevice.h index 71d3d63..76b38ca 100644 --- a/UsbDk/FilterDevice.h +++ b/UsbDk/FilterDevice.h @@ -65,8 +65,10 @@ public: , m_CfgDescriptors(CfgDescriptors) , m_ParentDevice(ParentDevice) , m_PDO(PDO) - {} - + , m_ClassMaskForExtHider(0) + { + DetermineDeviceClasses(); + } ULONG ParentID() const; PCWCHAR DeviceID() const { return *m_DeviceID->begin(); } PCWCHAR InstanceID() const { return *m_InstanceID->begin(); } @@ -77,6 +79,8 @@ public: const USB_DEVICE_DESCRIPTOR &DeviceDescriptor() const { return m_DevDescriptor; } PDEVICE_OBJECT PDO() const { return m_PDO; } + ULONG ClassesBitMask() const + { return m_ClassMaskForExtHider; } bool ConfigurationDescriptor(UCHAR Index, USB_CONFIGURATION_DESCRIPTOR &Buffer, size_t BufferLength) { @@ -107,10 +111,12 @@ private: TDescriptorsCache m_CfgDescriptors; PDEVICE_OBJECT m_PDO; const CUsbDkFilterDevice &m_ParentDevice; - + ULONG m_ClassMaskForExtHider; CUsbDkChildDevice(const CUsbDkChildDevice&) = delete; CUsbDkChildDevice& operator= (const CUsbDkChildDevice&) = delete; + void DetermineDeviceClasses(); + DECLARE_CWDMLIST_ENTRY(CUsbDkChildDevice); }; @@ -169,6 +175,7 @@ public: void SetSerialNumber(ULONG Number) { m_SerialNumber = Number; } + void OnFileCreate(WDFREQUEST Request); private: ~CUsbDkFilterDevice() { diff --git a/UsbDk/HideRulesRegPublic.h b/UsbDk/HideRulesRegPublic.h index 1a028e0..ecd3a9a 100644 --- a/UsbDk/HideRulesRegPublic.h +++ b/UsbDk/HideRulesRegPublic.h @@ -31,6 +31,7 @@ #define USBDK_HIDE_RULE_PID TEXT("PID") #define USBDK_HIDE_RULE_BCD TEXT("BCD") #define USBDK_HIDE_RULE_CLASS TEXT("Class") +#define USBDK_HIDE_RULE_TYPE TEXT("Type") #define USBDK_HIDE_RULES_PATH TEXT("SYSTEM\\CurrentControlSet\\Services\\") \ USBDK_DRIVER_NAME TEXT("\\") \ diff --git a/UsbDk/RedirectorStrategy.cpp b/UsbDk/RedirectorStrategy.cpp index ff36933..f8755f3 100644 --- a/UsbDk/RedirectorStrategy.cpp +++ b/UsbDk/RedirectorStrategy.cpp @@ -630,6 +630,7 @@ void CUsbDkRedirectorStrategy::OnClose() { USB_DK_DEVICE_ID ID; UsbDkFillIDStruct(&ID, *m_DeviceID->begin(), *m_InstanceID->begin()); + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_REDIRECTOR, "%!FUNC!"); auto status = m_ControlDevice->RemoveRedirect(ID); if (!NT_SUCCESS(status)) diff --git a/UsbDk/Urb.cpp b/UsbDk/Urb.cpp index baabc50..ecbd9d0 100644 --- a/UsbDk/Urb.cpp +++ b/UsbDk/Urb.cpp @@ -71,5 +71,16 @@ NTSTATUS CIsochronousUrb::Create(Direction TransferDirection, PVOID TransferBuff m_Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer; m_Urb->UrbIsochronousTransfer.NumberOfPackets = static_cast(NumberOfPackets); + + if (TransferDirection == URB_DIRECTION_OUT) + { + // initialize Length with initial packet length + // USB controller driver may override it (Win7) + for (size_t i = 0; i < NumberOfPackets; i++) + { + m_Urb->UrbIsochronousTransfer.IsoPacket[i].Length = static_cast(PacketSizes[i]); + } + } + return FillOffsetsArray(NumberOfPackets, PacketSizes, TransferBufferSize); } diff --git a/UsbDk/UsbDk.vcxproj b/UsbDk/UsbDk.vcxproj index 4a82622..94c01a6 100644 --- a/UsbDk/UsbDk.vcxproj +++ b/UsbDk/UsbDk.vcxproj @@ -1178,6 +1178,7 @@ 1 11 + diff --git a/UsbDk/UsbDkDataHider.h b/UsbDk/UsbDkDataHider.h index b2a7e55..73c60a7 100644 --- a/UsbDk/UsbDkDataHider.h +++ b/UsbDk/UsbDkDataHider.h @@ -23,13 +23,26 @@ #pragma once -#define USB_DK_HIDE_RULE_MATCH_ALL ((ULONG64)(-1)) +#include "UsbDkDataHiderPublic.h" -typedef struct tag_USB_DK_HIDE_RULE +#ifdef __cplusplus +class USB_DK_HIDE_RULE : public USB_DK_HIDE_RULE_PUBLIC { - ULONG64 Hide; - ULONG64 Class; - ULONG64 VID; - ULONG64 PID; - ULONG64 BCD; -} USB_DK_HIDE_RULE, *PUSB_DK_HIDE_RULE; +public: + USB_DK_HIDE_RULE(PUSB_DK_HIDE_RULE_PUBLIC PublicRule = NULL, ULONG RuleType = USBDK_HIDER_RULE_DEFAULT) : + Type(RuleType) + { + if (PublicRule) + { + Hide = PublicRule->Hide; + Class = PublicRule->Class; + VID = PublicRule->VID; + PID = PublicRule->PID; + BCD = PublicRule->BCD; + } + } + ULONG64 Type; +}; + +typedef USB_DK_HIDE_RULE *PUSB_DK_HIDE_RULE; +#endif diff --git a/UsbDk/UsbDkDataHiderPublic.h b/UsbDk/UsbDkDataHiderPublic.h new file mode 100644 index 0000000..ef8393b --- /dev/null +++ b/UsbDk/UsbDkDataHiderPublic.h @@ -0,0 +1,38 @@ +/********************************************************************** +* Copyright (c) 2013-2014 Red Hat, Inc. +* +* Developed by Daynix Computing LTD. +* +* Authors: +* Dmitry Fleytman +* Kirill Moizik +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +**********************************************************************/ + +#pragma once + +#define USB_DK_HIDE_RULE_MATCH_ALL ((ULONG64)(-1)) + +typedef struct tag_USB_DK_HIDE_RULE_PUBLIC +{ + ULONG64 Hide; + ULONG64 Class; + ULONG64 VID; + ULONG64 PID; + ULONG64 BCD; +} USB_DK_HIDE_RULE_PUBLIC, *PUSB_DK_HIDE_RULE_PUBLIC; + +#define USBDK_HIDER_RULE_DEFAULT 0 +#define USBDK_HIDER_RULE_DETERMINATIVE_TYPES 1 diff --git a/UsbDk/UsbDkUtil.h b/UsbDk/UsbDkUtil.h index 11c114b..ff599ea 100644 --- a/UsbDk/UsbDkUtil.h +++ b/UsbDk/UsbDkUtil.h @@ -411,10 +411,18 @@ public: } template - bool ModifyOne(TEntryId *Id, TModifier ModifierFunc) + bool ModifyOne(TEntryId *Id, TModifier ModifierFunc, ULONG process = 0) { CLockedContext LockedContext(*this); - return !m_Objects.ForEachIf([Id](TEntryType *ExistingEntry) { return *ExistingEntry == *Id; }, + return !m_Objects.ForEachIf([Id,process](TEntryType *ExistingEntry) + { + bool match = *ExistingEntry == *Id; + if (process && match) + { + match = ExistingEntry->MatchProcess(process); + } + return match; + }, [&ModifierFunc](TEntryType *Entry) { ModifierFunc(Entry); return false; }); } diff --git a/UsbDk/WdfDevice.cpp b/UsbDk/WdfDevice.cpp index fe09930..566a078 100644 --- a/UsbDk/WdfDevice.cpp +++ b/UsbDk/WdfDevice.cpp @@ -125,6 +125,8 @@ NTSTATUS CWdfDevice::Create(CPreAllocatedDeviceInit &DeviceInit, WDF_OBJECT_ATTR TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! Device name caching failed %!STATUS!", status); } + m_LowerDeviceObj = IoGetLowerDeviceObject(WdmObject()); + return status; } @@ -170,6 +172,10 @@ void CWdfSpecificQueue::InitConfig(WDF_IO_QUEUE_CONFIG &QueueConfig) CWdfDevice::~CWdfDevice() { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_WDFDEVICE, "%!FUNC! Deleting device %wZ", m_CachedName); + if (m_LowerDeviceObj) + { + ObDereferenceObject(m_LowerDeviceObj); + } } NTSTATUS CWdfDevice::CacheDeviceName() diff --git a/UsbDk/WdfDevice.h b/UsbDk/WdfDevice.h index a044801..978c3c9 100644 --- a/UsbDk/WdfDevice.h +++ b/UsbDk/WdfDevice.h @@ -139,6 +139,7 @@ public: WDFDEVICE WdfObject() const { return m_Device; } PDEVICE_OBJECT WdmObject() const { return WdfDeviceWdmGetDeviceObject(m_Device); }; + PDEVICE_OBJECT LowerDeviceObject() const { return m_LowerDeviceObj; } WDFIOTARGET IOTarget() const { return WdfDeviceGetIoTarget(m_Device); } @@ -155,6 +156,7 @@ private: NTSTATUS AddQueue(WDF_IO_QUEUE_CONFIG &Config, WDF_OBJECT_ATTRIBUTES &Attributes, WDFQUEUE &Queue); NTSTATUS CacheDeviceName(); CString m_CachedName; + PDEVICE_OBJECT m_LowerDeviceObj = nullptr; friend class CWdfQueue; }; diff --git a/UsbDk/stdafx.h b/UsbDk/stdafx.h index 11b8af7..dc32ba2 100644 --- a/UsbDk/stdafx.h +++ b/UsbDk/stdafx.h @@ -16,7 +16,20 @@ extern "C" #include #if !TARGET_OS_WIN_XP +#include #include +#include +#else +#define USB_DEVICE_CLASS_AUDIO 0x01 +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#define USB_DEVICE_CLASS_PRINTER 0x07 +#define USB_DEVICE_CLASS_STORAGE 0x08 +#define USB_DEVICE_CLASS_HUB 0x09 +#define USB_DEVICE_CLASS_CDC_DATA 0x0A +#define USB_DEVICE_CLASS_VIDEO 0x0E +#define USB_DEVICE_CLASS_AUDIO_VIDEO 0x10 +#define USB_DEVICE_CLASS_WIRELESS_CONTROLLER 0xE0 #endif #include diff --git a/UsbDkController/UsbDkController.cpp b/UsbDkController/UsbDkController.cpp index e47c443..0b399d0 100644 --- a/UsbDkController/UsbDkController.cpp +++ b/UsbDkController/UsbDkController.cpp @@ -45,12 +45,15 @@ static void ShowUsage() tcout << endl; tcout << TEXT(" Hider API:") << endl; tcout << endl; - tcout << TEXT(" UsbDkController -H VID PID BCD Class Hide - add dynamic hide rule") << endl; - tcout << TEXT(" UsbDkController -P VID PID BCD Class Hide - add persistent hide rule") << endl; - tcout << TEXT(" UsbDkController -D VID PID BCD Class Hide - delete persistent hide rule") << endl; + tcout << TEXT(" UsbDkController -H TYPE VID PID BCD Class Hide - add dynamic hide rule") << endl; + tcout << TEXT(" UsbDkController -P TYPE VID PID BCD Class Hide - add persistent hide rule") << endl; + tcout << TEXT(" UsbDkController -D TYPE VID PID BCD Class Hide - delete persistent hide rule") << endl; + tcout << TEXT(" UsbDkController -Z - delete all persistent hide rules") << endl; tcout << endl; tcout << TEXT(" May be specific value or -1 to match all") << endl; tcout << TEXT(" Should be 0 or 1, if 0, the rule is terminal") << endl; + tcout << TEXT(" Should be 0 for backward-compatible hide") << endl; + tcout << TEXT(" 1 for hide by determinative type") << endl; tcout << endl; } @@ -229,48 +232,53 @@ static bool Controller_ParseBoolRuleField(const TCHAR *Name, const TCHAR * Str, return true; } -static bool Controller_ParseRule(TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide, USB_DK_HIDE_RULE &Rule) +static bool Controller_ParseRule(TCHAR *Type, TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide, USB_DK_HIDE_RULE &Rule) { return Controller_ParseIntRuleField(TEXT("VID"), VID, Rule.VID) && Controller_ParseIntRuleField(TEXT("PID"), PID, Rule.PID) && Controller_ParseIntRuleField(TEXT("BCD"), BCD, Rule.BCD) && Controller_ParseIntRuleField(TEXT("Class"), UsbClass, Rule.Class) && - Controller_ParseBoolRuleField(TEXT("Hide"), Hide, Rule.Hide); + Controller_ParseBoolRuleField(TEXT("Hide"), Hide, Rule.Hide) && + Controller_ParseIntRuleField(TEXT("Type"), Type, Rule.Type); } -static int Controller_AddPersistentHideRule(TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide) +static int Controller_AddPersistentHideRule(TCHAR *Type, TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide) { USB_DK_HIDE_RULE Rule; - if (!Controller_ParseRule(VID, PID, BCD, UsbClass, Hide, Rule)) + if (!Controller_ParseRule(Type, VID, PID, BCD, UsbClass, Hide, Rule)) { tcout << TEXT("Persistent hide rule parsing failed") << endl; return false; } - auto res = UsbDk_AddPersistentHideRule(&Rule); + auto res = Type == USBDK_HIDER_RULE_DEFAULT ? + UsbDk_AddPersistentHideRule(&Rule) : + UsbDk_AddExtendedPersistentHideRule(&Rule, (ULONG)Rule.Type); return Controller_AnalyzeInstallResult(res, TEXT("Persistent hide rule creation")); } -static int Controller_DeletePersistentHideRule(TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide) +static int Controller_DeletePersistentHideRule(TCHAR *Type, TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide) { USB_DK_HIDE_RULE Rule; - if (!Controller_ParseRule(VID, PID, BCD, UsbClass, Hide, Rule)) + if (!Controller_ParseRule(Type, VID, PID, BCD, UsbClass, Hide, Rule)) { tcout << TEXT("Persistent hide rule parsing failed") << endl; return false; } - auto res = UsbDk_DeletePersistentHideRule(&Rule); + auto res = Type == USBDK_HIDER_RULE_DEFAULT ? + UsbDk_DeletePersistentHideRule(&Rule) : + UsbDk_DeleteExtendedPersistentHideRule(&Rule, (ULONG)Rule.Type); return Controller_AnalyzeInstallResult(res, TEXT("Persistent hide rule removal")); } -static void Controller_HideDevice(TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide) +static void Controller_HideDevice(TCHAR *Type, TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *UsbClass, TCHAR *Hide) { USB_DK_HIDE_RULE Rule; - if (!Controller_ParseRule(VID, PID, BCD, UsbClass, Hide, Rule)) + if (!Controller_ParseRule(Type, VID, PID, BCD, UsbClass, Hide, Rule)) { tcout << TEXT("Hide rule parsing failed") << endl; return; @@ -283,7 +291,11 @@ static void Controller_HideDevice(TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *Usb return; } - if (UsbDk_AddHideRule(hiderHandle, &Rule)) + BOOL bResult = Rule.Type == USBDK_HIDER_RULE_DEFAULT ? + UsbDk_AddHideRule(hiderHandle, &Rule) : + UsbDk_AddExtendedHideRule(hiderHandle, &Rule, (ULONG)Rule.Type); + + if (bResult) { tcout << endl << TEXT("Hide rule loaded succesfully. ") @@ -308,6 +320,15 @@ static void Controller_HideDevice(TCHAR *VID, TCHAR *PID, TCHAR *BCD, TCHAR *Usb UsbDk_CloseHiderHandle(hiderHandle); } +static int Controller_DeleteAllPersistentHideRules() +{ + ULONG done = 0, notDone = 0; + auto res = UsbDk_DeleteAllPersistentRules(&done, ¬Done); + tcout << TEXT("Cleaning persistent rules: done ") << dec << done + << TEXT(", not done ") << notDone << endl; + return Controller_AnalyzeInstallResult(res, TEXT("Clean persistent hide rules")); +} + static bool Controller_ChdirToPackageFolder() { TCHAR PackagePath[MAX_PATH]; @@ -374,30 +395,34 @@ int __cdecl _tmain(int argc, TCHAR* argv[]) } else if (_tcscmp(L"-H", argv[1]) == 0) { - if (argc < 7) + if (argc < 8) { ShowUsage(); return -3; } - Controller_HideDevice(argv[2], argv[3], argv[4], argv[5], argv[6]); + Controller_HideDevice(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); } else if (_tcscmp(L"-P", argv[1]) == 0) { - if (argc < 7) + if (argc < 8) { ShowUsage(); return -4; } - return Controller_AddPersistentHideRule(argv[2], argv[3], argv[4], argv[5], argv[6]); + return Controller_AddPersistentHideRule(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); } else if (_tcscmp(L"-D", argv[1]) == 0) { - if (argc < 7) + if (argc < 8) { ShowUsage(); return -5; } - return Controller_DeletePersistentHideRule(argv[2], argv[3], argv[4], argv[5], argv[6]); + return Controller_DeletePersistentHideRule(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); + } + else if (_tcscmp(L"-Z", argv[1]) == 0) + { + return Controller_DeleteAllPersistentHideRules(); } else { diff --git a/UsbDkController/UsbDkController.vcxproj b/UsbDkController/UsbDkController.vcxproj index 10fdaa1..dc3ff61 100644 --- a/UsbDkController/UsbDkController.vcxproj +++ b/UsbDkController/UsbDkController.vcxproj @@ -127,6 +127,7 @@ Win32Proj UsbDkController $(LatestTargetPlatformVersion) + Windows7 @@ -322,6 +323,7 @@ Unicode Desktop + diff --git a/UsbDkHelper/RuleManager.cpp b/UsbDkHelper/RuleManager.cpp index 80fe36c..3b20489 100644 --- a/UsbDkHelper/RuleManager.cpp +++ b/UsbDkHelper/RuleManager.cpp @@ -16,7 +16,8 @@ static bool operator == (const USB_DK_HIDE_RULE& r1, const USB_DK_HIDE_RULE& r2) (r1.PID == r2.PID) && (r1.BCD == r2.BCD) && (r1.Class == r2.Class) && - (r1.Hide == r2.Hide); + (r1.Hide == r2.Hide) && + (r1.Type == r2.Type); } DWORD CRulesManager::ReadDword(LPCTSTR RuleName, LPCTSTR ValueName) const @@ -53,6 +54,7 @@ ULONG64 CRulesManager::ReadBool(LPCTSTR RuleName, LPCTSTR ValueName) const void CRulesManager::ReadRule(LPCTSTR RuleName, USB_DK_HIDE_RULE &Rule) const { + Rule.Type = ReadDword(RuleName, USBDK_HIDE_RULE_TYPE); Rule.Hide = ReadBool(RuleName, USBDK_HIDE_RULE_SHOULD_HIDE); Rule.VID = ReadDwordMask(RuleName, USBDK_HIDE_RULE_VID); Rule.PID = ReadDwordMask(RuleName, USBDK_HIDE_RULE_PID); @@ -106,6 +108,7 @@ void CRulesManager::AddRule(const USB_DK_HIDE_RULE &Rule) throw UsbDkRuleManagerException(TEXT("Failed to create rule key"), ERROR_FUNCTION_FAILED); } + WriteDword(RuleName, USBDK_HIDE_RULE_TYPE, static_cast(Rule.Type)); WriteDword(RuleName, USBDK_HIDE_RULE_SHOULD_HIDE, static_cast(Rule.Hide)); WriteDword(RuleName, USBDK_HIDE_RULE_VID, static_cast(Rule.VID)); WriteDword(RuleName, USBDK_HIDE_RULE_PID, static_cast(Rule.PID)); @@ -125,3 +128,20 @@ void CRulesManager::DeleteRule(const USB_DK_HIDE_RULE &Rule) } } } + +ULONG CRulesManager::DeleteAllRules(ULONG& notDeleted) +{ + ULONG deleted = 0; + notDeleted = 0; + vector subkeys; + + for (const auto &SubKey : m_RegAccess) + subkeys.push_back(SubKey); + + while (subkeys.size()) + { + m_RegAccess.DeleteKey(subkeys.front().c_str()) ? deleted++ : notDeleted++; + subkeys.erase(subkeys.begin()); + } + return deleted; +} diff --git a/UsbDkHelper/RuleManager.h b/UsbDkHelper/RuleManager.h index 424b565..70b100a 100644 --- a/UsbDkHelper/RuleManager.h +++ b/UsbDkHelper/RuleManager.h @@ -18,6 +18,7 @@ public: void AddRule(const USB_DK_HIDE_RULE &Rule); void DeleteRule(const USB_DK_HIDE_RULE &Rule); + ULONG DeleteAllRules(ULONG& notDeleted); private: template bool FindRule(const USB_DK_HIDE_RULE &Rule, TFunctor Functor); diff --git a/UsbDkHelper/UsbDkHelper.cpp b/UsbDkHelper/UsbDkHelper.cpp index f9f66d3..b6fa183 100644 --- a/UsbDkHelper/UsbDkHelper.cpp +++ b/UsbDkHelper/UsbDkHelper.cpp @@ -173,7 +173,11 @@ BOOL UsbDk_StopRedirect(HANDLE DeviceHandle) { try { - UsbDkDriverAccess driverAccess; + // if the driver is unaccessible the constructor raises exception + // there is a question whether this check is required and whether this is correct thing to do + // for now we leave it as is with TODO to investigate it in corner case flow + // (for example UsbDk uninstall when there is active redirection) + UsbDkDriverAccess checkDriverAccess; unique_ptr deviceHandle(unpackHandle(DeviceHandle)); deviceHandle->RedirectorAccess.reset(); return TRUE; @@ -301,12 +305,13 @@ HANDLE UsbDk_CreateHiderHandle() } } -BOOL UsbDk_AddHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE Rule) +DLL BOOL UsbDk_AddExtendedHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE_PUBLIC PublicRule, ULONG Type) { + USB_DK_HIDE_RULE Rule(PublicRule, Type); try { auto HiderAccess = unpackHandle(HiderHandle); - HiderAccess->AddHideRule(*Rule); + HiderAccess->AddHideRule(Rule); return TRUE; } catch (const exception &e) @@ -316,6 +321,11 @@ BOOL UsbDk_AddHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE Rule) } } +BOOL UsbDk_AddHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE_PUBLIC PublicRule) +{ + return UsbDk_AddExtendedHideRule(HiderHandle, PublicRule, USBDK_HIDER_RULE_DEFAULT); +} + BOOL UsbDk_ClearHideRules(HANDLE HiderHandle) { try @@ -370,12 +380,50 @@ InstallResult ModifyPersistentHideRules(const USB_DK_HIDE_RULE &Rule, } } -DLL InstallResult UsbDk_AddPersistentHideRule(PUSB_DK_HIDE_RULE Rule) +DLL InstallResult UsbDk_AddExtendedPersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC PublicRule, ULONG Type) { - return ModifyPersistentHideRules(*Rule, &CRulesManager::AddRule); + USB_DK_HIDE_RULE Rule(PublicRule, Type); + return ModifyPersistentHideRules(Rule, &CRulesManager::AddRule); } -DLL InstallResult UsbDk_DeletePersistentHideRule(PUSB_DK_HIDE_RULE Rule) +DLL InstallResult UsbDk_AddPersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC PublicRule) { - return ModifyPersistentHideRules(*Rule, &CRulesManager::DeleteRule); + return UsbDk_AddExtendedPersistentHideRule(PublicRule, USBDK_HIDER_RULE_DEFAULT); +} + +DLL InstallResult UsbDk_DeleteExtendedPersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC PublicRule, ULONG Type) +{ + USB_DK_HIDE_RULE Rule(PublicRule, Type); + return ModifyPersistentHideRules(Rule, &CRulesManager::DeleteRule); +} + +DLL InstallResult UsbDk_DeletePersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC PublicRule) +{ + return UsbDk_DeleteExtendedPersistentHideRule(PublicRule, USBDK_HIDER_RULE_DEFAULT); +} + +DLL InstallResult UsbDk_DeleteAllPersistentRules(OUT PULONG pDeleted, OUT PULONG pNotDeleted) +{ + try + { + CRulesManager Manager; + + *pDeleted = *pNotDeleted = 0; + *pDeleted = Manager.DeleteAllRules(*pNotDeleted); + + UsbDkDriverAccess driver; + driver.UpdateRegistryParameters(); + + return *pNotDeleted ? InstallFailure : InstallSuccess; + } + catch (const UsbDkDriverFileException &e) + { + printExceptionString(e.what()); + return InstallSuccessNeedReboot; + } + catch (const exception &e) + { + printExceptionString(e.what()); + return InstallFailure; + } } diff --git a/UsbDkHelper/UsbDkHelper.vcxproj b/UsbDkHelper/UsbDkHelper.vcxproj index 2e8da91..bfdc94b 100644 --- a/UsbDkHelper/UsbDkHelper.vcxproj +++ b/UsbDkHelper/UsbDkHelper.vcxproj @@ -127,6 +127,7 @@ Win32Proj UsbDkHelper $(LatestTargetPlatformVersion) + Windows7 @@ -322,6 +323,7 @@ Unicode Desktop + diff --git a/UsbDkHelper/UsbDkHelperHider.h b/UsbDkHelper/UsbDkHelperHider.h index d4f4521..ee1e7b0 100644 --- a/UsbDkHelper/UsbDkHelperHider.h +++ b/UsbDkHelper/UsbDkHelperHider.h @@ -35,7 +35,7 @@ #endif #endif -#include "UsbDkDataHider.h" +#include "UsbDkDataHiderPublic.h" #ifdef __cplusplus extern "C" { #endif @@ -79,7 +79,29 @@ extern "C" { * UsbDk_ClearHideRules() called * */ - DLL BOOL UsbDk_AddHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE Rule); + DLL BOOL UsbDk_AddHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE_PUBLIC Rule); + + /* Add extended rule for detaching USB devices from OS stack. + * The rule definition is the same as for UsbDk_AddHideRule + * + * Processing of the rule depend on exact Type parameter + * For existing extended rules see Documentation/Hider.txt + * + * @params + * IN - HiderHandle Handle to UsbDk driver + * - Rule - pointer to hide rule + * - Type - type of the rule + * OUT - None + * + * @return + * TRUE if function succeeds + * + * @note + * Hide rule stays until HiderHandle is closed, client process exits or + * UsbDk_ClearHideRules() called + * + */ + DLL BOOL UsbDk_AddExtendedHideRule(HANDLE HiderHandle, PUSB_DK_HIDE_RULE_PUBLIC Rule, ULONG Type); /* Clear all hider rules * @@ -121,18 +143,43 @@ extern "C" { * * @note * 1. Persistent rule stays until explicitly deleted by - * UsbDk_DeletePersistentHideRule() + * UsbDk_DeletePersistentHideRule or UsbDk_DeleteAllPersistentRules * 2. This API requires administrative privileges * 3. For already attached devices the rule will be applied after * device re-plug or system reboot. * */ - DLL InstallResult UsbDk_AddPersistentHideRule(PUSB_DK_HIDE_RULE Rule); + DLL InstallResult UsbDk_AddPersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC Rule); - /* Delete specific persistent hide rule + /* Add extended rule for detaching USB devices from OS stack persistently. + * The rule definition is the same as for UsbDk_AddPersistentHideRule + * + * Processing of the rule depend on exact Type parameter + * For existing extended rules see Documentation/Hider.txt * * @params * IN - Rule - pointer to hide rule + * - Type - type of the rule + * OUT - None + * + * @return + * Rule installation status + * + * @note + * 1. Persistent rule stays until explicitly deleted by + * UsbDk_DeleteExtendedPersistentHideRule() or UsbDk_DeleteAllPersistentRules + * 2. This API requires administrative privileges + * 3. For already attached devices the rule will be applied after + * device re-plug or system reboot. + * + */ + DLL InstallResult UsbDk_AddExtendedPersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC Rule, ULONG Type); + + /* Delete specific persistent hide rule (rule type is default) + * + * @params + * IN - Rule - pointer to hide rule + * - Type - type of the rule * OUT - None * * @return @@ -144,7 +191,44 @@ extern "C" { * device re-plug or system reboot. * */ - DLL InstallResult UsbDk_DeletePersistentHideRule(PUSB_DK_HIDE_RULE Rule); + DLL InstallResult UsbDk_DeletePersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC Rule); + + /* Delete specific persistent hide rule + * + * @params + * IN - Rule - pointer to hide rule + * - Type - type of the rule + * OUT - None + * + * @return + * Rule removal status + * + * @note + * 1. This API requires administrative privileges + * 2. For already attached devices the rule will be applied after + * device re-plug or system reboot. + * + */ + DLL InstallResult UsbDk_DeleteExtendedPersistentHideRule(PUSB_DK_HIDE_RULE_PUBLIC Rule, ULONG Type); + + /* Delete all persistent hide rules + * + * @params + * IN - None + * OUT - PULONG pDeleted - number of deleted rules + * PULONG pNotDeleted - number of not deleted rules + * + * @return + * Rule removal status + * + * @note + * 1. This API requires administrative privileges + * 2. For already attached devices the rules become inactive after + * device re-plug or system reboot. + * + */ + DLL InstallResult UsbDk_DeleteAllPersistentRules(OUT PULONG pDeleted, OUT PULONG pNotDeleted); + #ifdef __cplusplus } #endif diff --git a/UsbDkInstHelper/UsbDkInstHelper.cpp b/UsbDkInstHelper/UsbDkInstHelper.cpp index 617a26b..4a64466 100644 --- a/UsbDkInstHelper/UsbDkInstHelper.cpp +++ b/UsbDkInstHelper/UsbDkInstHelper.cpp @@ -27,6 +27,8 @@ using namespace std; +static BOOL suppressInstallMessageBox = FALSE; + static int Controller_InstallDriver() { //Clean up any previous versions before reinstalling @@ -40,14 +42,28 @@ static int Controller_InstallDriver() case InstallFailure: return 1; case InstallAborted: - MessageBox(NULL, - TEXT("Failed to start the driver on the system, installation aborted!\nPlease make sure you are installing a signed version of UsbDk or else try to disable \"driver signature enforcement\" on the system"), - TEXT("UsbDk Runtime Libraries Installer"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_SYSTEMMODAL); + if (!suppressInstallMessageBox) + { + MessageBox(NULL, + TEXT("Failed to start the driver on the system, installation aborted!\nPlease make sure you are installing a signed version of UsbDk or else try to disable \"driver signature enforcement\" on the system"), + TEXT("UsbDk Runtime Libraries Installer"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_SYSTEMMODAL); + } + else + { + OutputDebugString(TEXT("UsbDkInstHelper: Installation aborted")); + } return 4; case InstallSuccessNeedReboot: - MessageBox(NULL, - TEXT("Please restart your computer to complete the installation"), - TEXT("UsbDk Runtime Libraries Installer"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_SYSTEMMODAL); + if (!suppressInstallMessageBox) + { + MessageBox(NULL, + TEXT("Please restart your computer to complete the installation"), + TEXT("UsbDk Runtime Libraries Installer"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_SYSTEMMODAL); + } + else + { + OutputDebugString(TEXT("UsbDkInstHelper: reboot required to complete the installation")); + } return 0; default: assert(0); @@ -101,6 +117,10 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi if (lpCmdLine[0] == 'i') { + if (lpCmdLine[1] == 'n' || lpCmdLine[1] == 'N') + { + suppressInstallMessageBox = TRUE; + } OutputDebugString(TEXT("UsbDkInstHelper: Install")); return Controller_InstallDriver(); } diff --git a/UsbDkInstHelper/UsbDkInstHelper.vcxproj b/UsbDkInstHelper/UsbDkInstHelper.vcxproj index cda36cf..7b4cda8 100644 --- a/UsbDkInstHelper/UsbDkInstHelper.vcxproj +++ b/UsbDkInstHelper/UsbDkInstHelper.vcxproj @@ -127,6 +127,7 @@ Win32Proj UsbDkController $(LatestTargetPlatformVersion) + Windows7 @@ -322,6 +323,7 @@ Unicode Desktop + diff --git a/buildAll.bat b/buildAll.bat index 9408e23..3e8f563 100644 --- a/buildAll.bat +++ b/buildAll.bat @@ -2,6 +2,7 @@ SETLOCAL EnableExtensions EnableDelayedExpansion +set _f=UsbDk if [%1] EQU [MSIONLY] goto BUILD_MSI if [%2] EQU [NOSIGN] (SET DEBUG_CFG=Debug_NoSign) ELSE (SET DEBUG_CFG=Debug) @@ -17,16 +18,40 @@ for %%x in (Win7, Win8, Win8.1, Win10, XP) do ( ) pushd Install -"C:\Program Files (x86)\Windows Kits\10\bin\x86\tracepdb.exe" -s -o .\UsbDk.tmf +call :maketmf Release if !ERRORLEVEL! NEQ 0 exit /B 1 popd pushd Install_Debug -"C:\Program Files (x86)\Windows Kits\10\bin\x86\tracepdb.exe" -s -o .\UsbDk.tmf +call :maketmf %DEBUG_CFG% if !ERRORLEVEL! NEQ 0 exit /B 1 popd if [%1] EQU [NOMSI] goto NOMSI +goto BUILD_MSI + +:maketmf +del *.tmf *.mof +call :make1tmf x64\Win10%1 +call :make1tmf x86\Win10%1 +call :make1tmf x64\Win8.1%1 +call :make1tmf x86\Win8.1%1 +call :make1tmf x64\Win8%1 +call :make1tmf x86\Win8%1 +call :make1tmf x64\Win7%1 +call :make1tmf x86\Win7%1 +call :make1tmf x64\XP%1 +call :make1tmf x86\XP%1 +goto :eof + +:make1tmf +pushd %1 +echo Making TMF in %1 +"C:\Program Files (x86)\Windows Kits\10\bin\x86\tracepdb.exe" -s -o .\%_f%.tmf +popd +type %1\%_f%.tmf >> %_f%.tmf +del %1\%_f%.??f +goto :eof :BUILD_MSI