Compare commits

...

39 commits

Author SHA1 Message Date
Yan Vugenfirer
af46b7ee33 Fix appveyor badge in Readme
Signed-off-by: Yan Vugenfirer <yan@daynix.com>
2020-10-05 15:14:09 +03:00
Yuri Benditovich
84752c3003 build: fix build of Debug_NoSign
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-02-27 17:34:04 +02:00
Yuri Benditovich
3b80562684 build: remove binary DLL from the repository
Collect all the 'before-build' actions in single batch file.
Download the DLL required for AppVeyor during the build.
Remove the DLL from the repository.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-27 20:00:38 +02:00
Yuri Benditovich
3d2e5a6272 driver: bring device to D0 before redirection
Device redirection often fails when the device is in D3/D2 when
we start redirecting it. Current commit brings the device to
D0 before sending 'cycle power' command to the device port if
the device is in low power mode at the moment of starting
redirection.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-27 19:49:45 +02:00
Yuri Benditovich
c565bd513e driver: add procedure for getting power data by PDO
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-27 19:49:45 +02:00
Yuri Benditovich
c736f5d8be driver: fix driver verifier assertion in FileCreate callback
Previous commit 4de57a9ff causes driver verifier assertion with
latest Windows builds. Note that this assertion is not in latest
WDF sources on GitHub. The verifier does not allow to forward
the MJ_CREATE requestto local IO target using "send-and-forget".
It requires the request to set completion callback.
There is an option to remove the file create callback at all, but
we prefer to have printout on file open for better diagnostics.
So we add completion callback for forwarded request and complete
the request in it.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-27 19:49:45 +02:00
Yuri Benditovich
617f89695e build: adjust appveyor script
Discard wdf folder renaming, it is not needed.
Discard WiX renaming, we use WIX environment variable.
Populate proper VS2015 build DLL.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-26 13:01:08 +02:00
Yuri Benditovich
7ed2a59030 build: fix build of TMF files
tracepdb utility does not work as expected, it overrides
TMF file with each processed PDB file. Build each TMF
file separately and concatenate all the TMF files to one.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
669d8cbddd installer: Use WIX environment variable
Use %WIX% instead of absolute path

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
4de57a9ff6 driver: pass current process id in file close flow
https://github.com/daynix/UsbDk/issues/81
OnClose -> RemoveRedirect -> NotifyRedirectorRemovalStarted
NotifyRedirectorRemovalStarted passes process id to ModifyOne
in order to avoid stopping redirection if another not related
process just opens the filter device and then closes it.
Example (before this commit):
Start VM and use remote-viewer to it.
Separate application 'App' registers notification on USB
device interface arrival. When new device comes, the application
opens a file using symbolic link name and closes it.
Redirect USB device to VM.
The UsbDk forces device to be reenumerated.
Open-close operation from the 'App' unexpectedly discards
device redirection.
After this commit: because the 'App' process is not an owner
of the redirection, OnClose will not cause removal of the
redirection.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
14dd054ae3 driver: extend ModifyOne template
Add optional process id parameter to the template
arguments. If process id is provided, the entry will be
additionally checked for match of owner process id saved in
the redirection object and caller process id.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
427b3f0106 driver: maintain owner process id field of CUsbDkRedirection
Set owner process id when device redirection successfully
established (i.e. filter device is open and respective user
mode handle created for the process).

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
db6c11f48a driver: add log on filter file close
Currently we stop redirection when filter device file handle
closed. This might be incorrect if some application just opens
and closes the file. Log entry with process id will help
diagnosing such problems.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
26a3619666 driver: add file open callback for tracing
Add callback when filter device receives file open request.
Propagate open operation down the stack and log it.
ETW log will contain process id of open request.
It is possible that more than one process opens the device.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
65f7251d2c driver: prevent access to already deleted object
https://github.com/daynix/UsbDk/issues/81
If during redirection the redirection object is deleted
we may try accessing the deleted object in the loop of
attempts to create the redirection handle.
To avoid this we reference the redirection object until
the redirection request completely satisfied or failed.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
7c93e05e60 driver: add printout on redirection object deletion
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
b08ff21f7b driver: add optional message to Dump() procedure
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2020-01-02 21:47:41 +02:00
Yuri Benditovich
b7acf791dc Hider API: add ability to delete all persistent rules
The application that uses Hider API does not have an ability
to query which persistent rules exist. So in order to use
UsbDk_DeletePersistentHideRule the application shall guess
which rule it needs to delete. Current commit adds ability to
delete all existing the persistent rules. This API requires
administrative privileges as all APIs related to persistent
hide rules.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
a07a062167 Add documention for extended Hider feature
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
08ad758943 Use also extended rules to decide whether device should be hidden
Extended rules processing uses bitmask OR between device type
determination bitmap and class/type bitmap provided in 'Class'
parameter of the extended rule.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
916f797c89 Load extended rules in the driver
Load dynamic and persistent rules with type == 1
to extended rules sets.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
68500dc8c3 Add ability to dump rules with configurable trace level
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
29b556b0ea hider: calculate device type bitmask for each child device
Device type bitmask is calculated for device class and classes
of all its interfaces by narrowing set of device classes to set
of device types.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
ad8a8836ab hider: maintain additional extended hiding rules
Add set of dynamic and persistent rules for advanced
device hiding feature.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
4ebf0da3e9 implement UsbDkController operations for extended rules
Extending UsbDkController commands by adding 'Type' parameter.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
12f71a300b implement read/write/compare operations for extended rules
This commit adds implementation of registry operation for
extended rules in user-mode. Kernel driver still recognizes
all the entries as default ones (it ignores the Type value).

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
fe0a2ca005 extend Hider API by adding extended hide rules
Added:
UsbDk_AddExtendedHideRule
UsbDk_AddExtendedPersistentHideRule
UsbDk_DeleteExtendedPersistentHideRule
All existing APIs continue working as before.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
3652e2a34d Preparation for extended rules for device hide
Extend structure USB_DK_HIDE_RULE by adding 'Type'
member derived from backward-compatible structure
USB_DK_HIDE_RULE_PUBLIC. Public API procedures of UsbDkHelper
receive USB_DK_HIDE_RULE_PUBLIC describing hiding rules.
Internally UsbDk works with extended structure.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:19:13 +03:00
Yuri Benditovich
7ad99b074c MSI installer: add ability to suppress message boxes
Added option MSGBOX=n to MSI package that forces the
installer to run without pop-up message boxes in case
of failure or request to reboot.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:02:48 +03:00
Yuri Benditovich
4c33964158 InstallHelper: optionally suppress message boxes
Add optional command-line parameter to suppress message
box in case the installation requires reboot or aborted.
This supports use case when the UsbDk is installed along
with other product and restart is required regardless
installation status of UsbDk. When installation helper
runs with -in or -iN, the message boxes are suppressed.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-04-15 11:02:48 +03:00
Yuri Benditovich
46c80bad84 Populate initial packet length in ISOCH OUT URB
https://github.com/daynix/UsbDk/issues/66
According to interface definition, the UsbDk shall return
actual length on transfer completion. For isoch OUT transfers
the controller does not return it on respective URB field on
Win10 and the updated WDK documentation states this field is
not used for ISOCH OUT transfers. Current commit populates
the initial packet length in the URB, making the result
consistent on both Win7 and Win10.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-01-29 11:10:55 +02:00
Yuri Benditovich
9ebf772799 Updated MAINTAINERS file
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-01-27 11:57:49 +02:00
Yuri Benditovich
4473e41ab3 Update project files for build with higher WDK installed
When higher WDK than 14393 is installed on the machine, the modified
files related to build of drivers and driver-related applications may
produce errors on build using VS2015. Fixed project files solve this.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2019-01-27 11:57:49 +02:00
Yuri Benditovich
4d1ecea50d Report superspeed properly on Win7
Win7 with USB 3.0 stack might not report superspeed
the same way as Win8 does. Use bcdUSB field of device
descriptor for that (USB 3.0 device connected to USB 2.x
port usually falls to USB 2 compatible configuration).
Getting the speed from HUB driver via IOCTL is more
complicated.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2018-10-17 15:52:34 +03:00
Yuri Benditovich
960f44ed2c Prevent USB operation with non-USB devices
This commit aims to address
https://bugzilla.redhat.com/show_bug.cgi?id=1575043
The driver definitely may try accessing USB device where
it is not USB and sending 'Submit URB' IOCTL down the stack
may cause unpredictable result. Current commit change
the order of checks when the device is enumerated by its
parent device: first ensure this is USB device, then try
to get USB-specific information.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2018-10-10 11:31:56 +03:00
Yuri Benditovich
19667102ee Revert commit f2dae22029
This reverts previous commit that actually has removed the check
that the driver is accessible. Prior to removal this at least should
be investigated in corner cases which are also to be defined
(like UsbDk uninstall when it has active redirected device).

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2018-10-10 11:31:56 +03:00
golden
f2dae22029 Delete unused local variable
Closes #56
2018-04-11 13:46:36 +03:00
Yuri Benditovich
2910063697 Use lower device for queries during initialization
It is more correct to use lower device in stack for queries
during filter initialization. Lower device is in initialized
state and can process all kinds of requests, when current one is
not ready yet.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
2017-07-12 16:58:03 +03:00
Dmitry Fleytman
db09883b27 ci: Integrate with AppVeyor
Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
2017-06-07 12:58:53 +03:00
35 changed files with 896 additions and 112 deletions

18
.appveyor.yml Normal file
View file

@ -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

83
Documentation/Hider.txt Normal file
View file

@ -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.

View file

@ -1,4 +1,6 @@
Maintained by Dmitry Fleytman
Maintained by Daynix Computing
------------------------------
M: Dmitry Fleytman <dfleytma@redhat.com>
M: Dmitry Fleytman <dmitry@daynix.com>
M: Yuri Benditovich <yuri.benditovich@daynix.com>
M: Yuri Benditovich <ybendito@redhat.com>
M: Yan Vugenfirer <yan@daynix.com>
M: Yan Vugenfirer <yvugenfi@redhat.com>

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,31 @@
<!--
***********************************************************************************************
Driver.Initial.props
Should be imported just after Microsoft.Cpp.Default.props
and after target Windows versions defined for configurations
Common property definitions used by all drivers:
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" TreatAsLocalProperty="Platform">
<Target Name="IntermediateNotify" BeforeTargets="PrepareForBuild" AfterTargets="DriverBuildNotifications">
<!-- Indicate to users what they are building -->
<Message Importance="high" Text="Driver.Initial.props: TargetVersion=$(TargetVersion) _NT_TARGET_VERSION=$(_NT_TARGET_VERSION) SUBSYSTEM_NATVER=$(SUBSYSTEM_NATVER) mismatch=$(MidlTargetMismatch)" />
</Target>
<PropertyGroup Condition="'$(TargetVersion)'=='Windows10'">
<_NT_TARGET_VERSION>0x0A00</_NT_TARGET_VERSION>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetVersion)'=='WindowsV6.3'">
<_NT_TARGET_VERSION>0x0603</_NT_TARGET_VERSION>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetVersion)'=='Windows8'">
<_NT_TARGET_VERSION>0x0602</_NT_TARGET_VERSION>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetVersion)'=='Windows7'">
<_NT_TARGET_VERSION>0x0601</_NT_TARGET_VERSION>
</PropertyGroup>
</Project>

View file

@ -117,9 +117,11 @@
</Directory>
</Directory>
<Property Id="MSGBOX" Value=" " />
<CustomAction Id="InstallDriver"
Directory="UsbDk_Directory"
ExeCommand="[UsbDk_Directory]\UsbDkInstHelper.exe i"
ExeCommand="[UsbDk_Directory]\UsbDkInstHelper.exe i[MSGBOX]"
Execute="deferred"
Impersonate="no"
Return="check">

View file

@ -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

View file

@ -381,6 +381,7 @@
<DriverType>Package</DriverType>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<Import Project="..\Tools\Driver.Initial.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>

View file

@ -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<HideRulesSet*>(&m_HideRules)->ForEach(HideVisitor);
const_cast<HideRulesSet*>(&m_PersistentHideRules)->ForEach(HideVisitor);
if (!Hide)
{
const_cast<HideRulesSet*>(&m_ExtHideRules)->ForEach(HideVisitorExt);
const_cast<HideRulesSet*>(&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<CUsbDkRedirection, CRefCountingDeleter> 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;
}

View file

@ -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 <typename TDevID>
void NotifyRedirectionRemoved(const TDevID &Dev) const
@ -320,6 +331,8 @@ private:
typedef CWdmSet<CUsbDkHideRule, CLockedAccess, CNonCountingObject> HideRulesSet;
HideRulesSet m_HideRules;
HideRulesSet m_PersistentHideRules;
HideRulesSet m_ExtHideRules;
HideRulesSet m_PersistentExtHideRules;
NTSTATUS AddHideRuleToSet(const USB_DK_HIDE_RULE &UsbDkRule, HideRulesSet &Set);

View file

@ -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))

View file

@ -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);

View file

@ -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<CRegText> DevID;
CObjHolder<CRegText> 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<CRegText> DevID;
CObjHolder<CRegText> 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);
}

View file

@ -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()
{

View file

@ -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("\\") \

View file

@ -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))

View file

@ -71,5 +71,16 @@ NTSTATUS CIsochronousUrb::Create(Direction TransferDirection, PVOID TransferBuff
m_Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer;
m_Urb->UrbIsochronousTransfer.NumberOfPackets = static_cast<ULONG>(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<ULONG>(PacketSizes[i]);
}
}
return FillOffsetsArray(NumberOfPackets, PacketSizes, TransferBufferSize);
}

View file

@ -1178,6 +1178,7 @@
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<KMDF_VERSION_MINOR>11</KMDF_VERSION_MINOR>
</PropertyGroup>
<Import Project="..\Tools\Driver.Initial.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>

View file

@ -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

View file

@ -0,0 +1,38 @@
/**********************************************************************
* Copyright (c) 2013-2014 Red Hat, Inc.
*
* Developed by Daynix Computing LTD.
*
* Authors:
* Dmitry Fleytman <dmitry@daynix.com>
* Kirill Moizik <kirill@daynix.com>
*
* 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

View file

@ -411,10 +411,18 @@ public:
}
template <typename TEntryId, typename TModifier>
bool ModifyOne(TEntryId *Id, TModifier ModifierFunc)
bool ModifyOne(TEntryId *Id, TModifier ModifierFunc, ULONG process = 0)
{
CLockedContext<TAccessStrategy> 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; });
}

View file

@ -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()

View file

@ -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;
};

View file

@ -16,7 +16,20 @@ extern "C"
#include <usb.h>
#if !TARGET_OS_WIN_XP
#include <initguid.h>
#include <UsbSpec.h>
#include <devpkey.h>
#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 <wdfusb.h>

View file

@ -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(" <VID PID BCD Class> May be specific value or -1 to match all") << endl;
tcout << TEXT(" <Hide> Should be 0 or 1, if 0, the rule is terminal") << endl;
tcout << TEXT(" <TYPE> 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, &notDone);
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
{

View file

@ -127,6 +127,7 @@
<Keyword>Win32Proj</Keyword>
<RootNamespace>UsbDkController</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<TargetVersion>Windows7</TargetVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
@ -322,6 +323,7 @@
<CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
</PropertyGroup>
<Import Project="..\Tools\Driver.Initial.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>

View file

@ -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<ULONG>(Rule.Type));
WriteDword(RuleName, USBDK_HIDE_RULE_SHOULD_HIDE, static_cast<ULONG>(Rule.Hide));
WriteDword(RuleName, USBDK_HIDE_RULE_VID, static_cast<ULONG>(Rule.VID));
WriteDword(RuleName, USBDK_HIDE_RULE_PID, static_cast<ULONG>(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<wstring> 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;
}

View file

@ -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 <typename TFunctor>
bool FindRule(const USB_DK_HIDE_RULE &Rule, TFunctor Functor);

View file

@ -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<REDIRECTED_DEVICE_HANDLE> deviceHandle(unpackHandle<REDIRECTED_DEVICE_HANDLE>(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<UsbDkHiderAccess>(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;
}
}

View file

@ -127,6 +127,7 @@
<Keyword>Win32Proj</Keyword>
<RootNamespace>UsbDkHelper</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<TargetVersion>Windows7</TargetVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
@ -322,6 +323,7 @@
<CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
</PropertyGroup>
<Import Project="..\Tools\Driver.Initial.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>

View file

@ -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

View file

@ -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();
}

View file

@ -127,6 +127,7 @@
<Keyword>Win32Proj</Keyword>
<RootNamespace>UsbDkController</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<TargetVersion>Windows7</TargetVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
@ -322,6 +323,7 @@
<CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
</PropertyGroup>
<Import Project="..\Tools\Driver.Initial.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>

View file

@ -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