1
0
Fork 0

Initial commit

This commit is contained in:
Benjamin Höglinger-Stelzer 2023-01-21 01:45:10 +01:00
commit 32256494e9
20 changed files with 2120 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

385
.gitignore vendored Normal file
View File

@ -0,0 +1,385 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
/TEMP/nssidswap/nssidswap.cat
/TEMP/nssidswap/nssidswap.inf
/TEMP/nssidswap/nssidswap.sys
/setup.inf
/setup.rpt
/v2.0.1.0/Signed_1152921505695688239.zip
/v2.0.1.0/disk1/nssidswap_x64.cab
/v2.0.1.0/drivers/nssidswap_x64/LICENSE
/v2.0.1.0/drivers/nssidswap_x64/nssidswap.cat
/v2.0.1.0/drivers/nssidswap_x64/nssidswap.inf
/v2.0.1.0/drivers/nssidswap_x64/nssidswap.man
/v2.0.1.0/drivers/nssidswap_x64/nssidswap.sys
/v2.0.1.0/nssidswap_unsigned_v2.0.1.0.zip
/v2.0.1.0/nssidswap_v2.0.1.0.zip
/v2.0.2.0/Signed_1152921505695690331.zip
/v2.0.2.0/disk1/nssidswap_x64.cab
/v2.0.2.0/drivers/nssidswap_x64/LICENSE
/v2.0.2.0/drivers/nssidswap_x64/nssidswap.cat
/v2.0.2.0/drivers/nssidswap_x64/nssidswap.inf
/v2.0.2.0/drivers/nssidswap_x64/nssidswap.man
/v2.0.2.0/drivers/nssidswap_x64/nssidswap.sys
/v2.0.2.0/nssidswap_v2.0.2.0.zip

40
LICENSE Normal file
View File

@ -0,0 +1,40 @@
nssudeaudio - USB Bus Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
Copyright (c) 2022-2023, Nefarius Software Solutions e.U.
All rights reserved.
Redistribution and use in bytecode or binary forms, without modification,
are permitted provided that the following conditions are met:
* Redistributions in bytecode or binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution. This includes repository READMEs for open-source projects
interfacing with this product, websites or in-application credits.
* Neither the name of the nssudeaudio.sys nor the names of its contributors may
be used to endorse or promote products derived from or distributed
with this software without specific prior written permission.
* Bundling or otherwise redistributing copies of binaries signed by
Nefarius Software Solutions e.U. is prohibited without specific prior
written permission.
* Personal use for research, experiment, and testing for
the benefit of public knowledge, personal study, private
entertainment, hobby projects, amateur pursuits, or religious
observance, without any anticipated commercial application,
is use for a permitted purpose.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
Demo USB class filter driver to [fix UDE compatibility with USBAUDIO.SYS](https://fosstodon.org/@Nefarius/110089542325783941) in the lab.
## Dependencies
[DmfBusFilterExtension](https://git.nefarius.at/nefarius/DmfBusFilterExtension)

44
nssudeaudio.sln Normal file
View File

@ -0,0 +1,44 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33122.133
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nssudeaudiofix", "src\nssudeaudio.vcxproj", "{AE58270A-E8BC-4805-9A09-23E91D4A21D5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ABA785CC-A32A-48DE-9EDD-43BCB226530F}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
nssidswap_ARM64.ddf = nssidswap_ARM64.ddf
nssidswap_x64.ddf = nssidswap_x64.ddf
nssidswap_x86.ddf = nssidswap_x86.ddf
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Debug|ARM64.ActiveCfg = Debug|ARM64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Debug|ARM64.Build.0 = Debug|ARM64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Debug|ARM64.Deploy.0 = Debug|ARM64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Debug|x64.ActiveCfg = Debug|x64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Debug|x64.Build.0 = Debug|x64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Debug|x64.Deploy.0 = Debug|x64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Release|ARM64.ActiveCfg = Release|ARM64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Release|ARM64.Build.0 = Release|ARM64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Release|ARM64.Deploy.0 = Release|ARM64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Release|x64.ActiveCfg = Release|x64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Release|x64.Build.0 = Release|x64
{AE58270A-E8BC-4805-9A09-23E91D4A21D5}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {471FE4BF-6C4E-4A41-B16F-0FFA7BD410B3}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,18 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=bytecode/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=iosb/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=irql/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nefarius/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nssudeaudio/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ntstatus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NTSTRSAFE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PBUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCHILD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PDEVICE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PPARENT/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PWDM/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=READM/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ssidswap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ssudeaudio/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=USBAUDIO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=USBDI/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

370
src/Device.c Normal file
View File

@ -0,0 +1,370 @@
/*
* nssudeaudio - USB Bus Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
*
* Copyright (c) 2022-2023, Nefarius Software Solutions e.U.
* All rights reserved.
*
* Redistribution and use in bytecode or binary forms, without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions in bytecode or binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution. This includes repository READMEs for open-source projects
* interfacing with this product, websites or in-application credits.
*
* * Neither the name of the nssudeaudio.sys nor the names of its contributors may
* be used to endorse or promote products derived from or distributed
* with this software without specific prior written permission.
*
* * Bundling or otherwise redistributing copies of binaries signed by
* Nefarius Software Solutions e.U. is prohibited without specific prior
* written permission.
*
* * Personal use for research, experiment, and testing for
* the benefit of public knowledge, personal study, private
* entertainment, hobby projects, amateur pursuits, or religious
* observance, without any anticipated commercial application,
* is use for a permitted purpose.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "Driver.h"
#include "Device.tmh"
#include <usbbusif.h>
static
VOID
UsbInterfaceReference(
_In_ PVOID Context
)
{
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(Context);
pCtx->OriginalInterface.InterfaceReference(pCtx->OriginalInterface.BusContext);
}
static
VOID
UsbInterfaceDereference(
_In_ PVOID Context
)
{
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(Context);
pCtx->OriginalInterface.InterfaceDereference(pCtx->OriginalInterface.BusContext);
}
static
NTSTATUS
USB_BUSIFFN
UsbInterfaceQueryBusTime(
IN PVOID BusContext,
IN OUT PULONG CurrentUsbFrame
)
{
FuncEntry(TRACE_DEVICE);
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(BusContext);
NTSTATUS status = pCtx->OriginalInterface.QueryBusTime(
pCtx->OriginalInterface.BusContext,
CurrentUsbFrame
);
if (CurrentUsbFrame)
{
TraceInformation(
TRACE_DEVICE,
"UsbInterfaceQueryBusTime.CurrentUsbFrame = %d",
*CurrentUsbFrame
);
}
// fake-succeed the call
if (CurrentUsbFrame && status == STATUS_NOT_SUPPORTED)
{
*CurrentUsbFrame = 0;
status = STATUS_SUCCESS;
}
FuncExit(TRACE_DEVICE, "status=%!STATUS!", status);
return status;
}
static
NTSTATUS
USB_BUSIFFN
UsbInterfaceSubmitIsoOutUrb(
IN PVOID BusContext,
IN PURB Urb
)
{
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(BusContext);
return pCtx->OriginalInterface.SubmitIsoOutUrb(
pCtx->OriginalInterface.BusContext,
Urb
);
}
BOOLEAN
USB_BUSIFFN
UsbInterfaceIsDeviceHighSpeed(
IN PVOID BusContext
)
{
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(BusContext);
return pCtx->OriginalInterface.IsDeviceHighSpeed(
pCtx->OriginalInterface.BusContext
);
}
NTSTATUS
USB_BUSIFFN
UsbInterfaceQueryBusInformation(
IN PVOID BusContext,
IN ULONG Level,
IN OUT PVOID BusInformationBuffer,
IN OUT PULONG BusInformationBufferLength,
OUT PULONG BusInformationActualLength
)
{
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(BusContext);
return pCtx->OriginalInterface.QueryBusInformation(
pCtx->OriginalInterface.BusContext,
Level,
BusInformationBuffer,
BusInformationBufferLength,
BusInformationActualLength
);
}
VOID
USB_BUSIFFN
UsbInterfaceGetUSBDIVersion(
IN PVOID BusContext,
IN OUT PUSBD_VERSION_INFORMATION VersionInformation,
IN OUT PULONG HcdCapabilities
)
{
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(BusContext);
pCtx->OriginalInterface.GetUSBDIVersion(
pCtx->OriginalInterface.BusContext,
VersionInformation,
HcdCapabilities
);
}
NTSTATUS
EvtChildDeviceAdded(
_In_ WDFDEVICE Device,
_In_ DMFBUSCHILDDEVICE ChildDevice
)
{
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
PCHILD_DEVICE_CONTEXT childContext = NULL;
FuncEntry(TRACE_DEVICE);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CHILD_DEVICE_CONTEXT);
if (NT_SUCCESS(status = WdfObjectAllocateContext(
ChildDevice,
&attributes,
(void**)&childContext
)))
{
childContext->Parent = Device;
}
else
{
TraceError(
TRACE_DEVICE,
"WdfObjectAllocateContext failed with status %!STATUS!",
status
);
EventWriteFailedWithNTStatus(NULL, __FUNCTION__, L"WdfObjectAllocateContext", status);
}
FuncExit(TRACE_DEVICE, "status=%!STATUS!", status);
return status;
}
BOOLEAN
EvtChildDeviceQueryInterface(
_In_ DMFBUSCHILDDEVICE ChildDevice,
_In_ PIRP Irp
)
{
FuncEntry(TRACE_DEVICE);
const PCHILD_DEVICE_CONTEXT pCtx = ChildDeviceGetContext(ChildDevice);
const PIO_STACK_LOCATION currentStack = IoGetCurrentIrpStackLocation(Irp);
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
{
return FALSE;
}
if (!pCtx)
{
TraceError(
TRACE_DEVICE,
"Child device context not yet allocated"
);
return FALSE;
}
// skip not interested
if (!IsEqualGUID(currentStack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID) ||
currentStack->Parameters.QueryInterface.Version != 1)
{
return FALSE;
}
PUSB_BUS_INTERFACE_USBDI_V1 pUpperInterface = (PUSB_BUS_INTERFACE_USBDI_V1)currentStack->Parameters.QueryInterface.
Interface;
TraceInformation(
TRACE_DEVICE,
"PRE QueryInterface.InterfaceType = %!GUID!",
currentStack->Parameters.QueryInterface.InterfaceType
);
TraceInformation(
TRACE_DEVICE,
"PRE QueryInterface.Version = %d",
currentStack->Parameters.QueryInterface.Version
);
KEVENT ke;
IO_STATUS_BLOCK iosb;
RtlZeroMemory(&iosb, sizeof(IO_STATUS_BLOCK));
PUSB_BUS_INTERFACE_USBDI_V1 pUsbInterface = ExAllocatePool2(
PagedPool,
sizeof(USB_BUS_INTERFACE_USBDI_V1),
NSS_POOL_TAG
);
if (!pUsbInterface)
{
return FALSE;
}
RtlZeroMemory(pUsbInterface, sizeof(USB_BUS_INTERFACE_USBDI_V1));
const PDEVICE_OBJECT deviceObject = DMF_BusFilter_WdmAttachedDeviceGet(ChildDevice);
KeInitializeEvent(&ke, NotificationEvent, FALSE);
const PIRP qiIrp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
deviceObject,
NULL,
0,
NULL,
&ke,
&iosb
);
qiIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; // required initialize
qiIrp->IoStatus.Information = 0;
const PIO_STACK_LOCATION qiStack = IoGetNextIrpStackLocation(qiIrp);
qiStack->MajorFunction = IRP_MJ_PNP;
qiStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
qiStack->Parameters.QueryInterface.InterfaceType = currentStack->Parameters.QueryInterface.InterfaceType;
qiStack->Parameters.QueryInterface.Version = currentStack->Parameters.QueryInterface.Version;
qiStack->Parameters.QueryInterface.Size = currentStack->Parameters.QueryInterface.Size;
qiStack->Parameters.QueryInterface.Interface = (PINTERFACE)pUsbInterface;
qiStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
const NTSTATUS status = IoCallDriver(deviceObject, qiIrp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
}
BOOLEAN ret = FALSE;
if (NT_SUCCESS(qiIrp->IoStatus.Status))
{
TraceInformation(
TRACE_DEVICE,
"IoCallDriver succeeded with status %!STATUS!",
qiIrp->IoStatus.Status
);
TraceInformation(
TRACE_DEVICE,
"POST usbInterface.Version = %d",
pUsbInterface->Version
);
TraceInformation(
TRACE_DEVICE,
"POST usbInterface.Size = %d",
pUsbInterface->Size
);
pCtx->OriginalInterface.Size = pUpperInterface->Size = pUsbInterface->Size;
pCtx->OriginalInterface.Version = pUpperInterface->Version = pUsbInterface->Version;
// save original functions
pCtx->OriginalInterface.InterfaceReference = pUsbInterface->InterfaceReference;
pCtx->OriginalInterface.InterfaceDereference = pUsbInterface->InterfaceDereference;
pCtx->OriginalInterface.GetUSBDIVersion = pUsbInterface->GetUSBDIVersion;
pCtx->OriginalInterface.SubmitIsoOutUrb = pUsbInterface->SubmitIsoOutUrb;
pCtx->OriginalInterface.QueryBusInformation = pUsbInterface->QueryBusInformation;
pCtx->OriginalInterface.IsDeviceHighSpeed = pUsbInterface->IsDeviceHighSpeed;
pCtx->OriginalInterface.QueryBusTime = pUsbInterface->QueryBusTime;
// report proxy functions
pUpperInterface->InterfaceReference = UsbInterfaceReference;
pUpperInterface->InterfaceDereference = UsbInterfaceDereference;
pUpperInterface->GetUSBDIVersion = UsbInterfaceGetUSBDIVersion;
pUpperInterface->SubmitIsoOutUrb = UsbInterfaceSubmitIsoOutUrb;
pUpperInterface->QueryBusInformation = UsbInterfaceQueryBusInformation;
pUpperInterface->IsDeviceHighSpeed = UsbInterfaceIsDeviceHighSpeed;
pUpperInterface->QueryBusTime = UsbInterfaceQueryBusTime;
// keep original bus context
pCtx->OriginalInterface.BusContext = pUsbInterface->BusContext;
// replace context object so we get it in our hooked function
pUpperInterface->BusContext = ChildDevice;
Irp->IoStatus.Status = STATUS_SUCCESS;
// causes the module to complete the request
ret = TRUE;
}
ExFreePoolWithTag(pUsbInterface, NSS_POOL_TAG);
FuncExitNoReturn(TRACE_DEVICE);
return ret;
}

67
src/Device.h Normal file
View File

@ -0,0 +1,67 @@
/*
* nssudeaudio - USB Bus Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
*
* Copyright (c) 2022-2023, Nefarius Software Solutions e.U.
* All rights reserved.
*
* Redistribution and use in bytecode or binary forms, without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions in bytecode or binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution. This includes repository READMEs for open-source projects
* interfacing with this product, websites or in-application credits.
*
* * Neither the name of the nssudeaudio.sys nor the names of its contributors may
* be used to endorse or promote products derived from or distributed
* with this software without specific prior written permission.
*
* * Bundling or otherwise redistributing copies of binaries signed by
* Nefarius Software Solutions e.U. is prohibited without specific prior
* written permission.
*
* * Personal use for research, experiment, and testing for
* the benefit of public knowledge, personal study, private
* entertainment, hobby projects, amateur pursuits, or religious
* observance, without any anticipated commercial application,
* is use for a permitted purpose.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <usbbusif.h>
//
// Child device context
//
typedef struct _CHILD_DEVICE_CONTEXT
{
WDFDEVICE Parent;
USB_BUS_INTERFACE_USBDI_V1 OriginalInterface;
} CHILD_DEVICE_CONTEXT, * PCHILD_DEVICE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CHILD_DEVICE_CONTEXT, ChildDeviceGetContext)
//
// Bus filter module callbacks
//
EVT_DMF_BusFilter_DeviceAdd EvtChildDeviceAdded;
EVT_DMF_BusFilter_DeviceQueryInterface EvtChildDeviceQueryInterface;

20
src/Dmf.props Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_PropertySheetDisplayName>Driver Module Framework</_PropertySheetDisplayName>
<!-- By default, look for DMF in parent root directory, otherwise use environment variable value -->
<DmfRootPath Condition="'$(DmfRootPath)' == ''">$(SolutionDir)..\</DmfRootPath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(DmfRootPath)\DMF\Modules.Library;$(DmfRootPath)\DMF\Modules.Template;$(DmfRootPath)\DMF\Modules.Library.Tests;$(DmfRootPath)\DMF\Framework;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies Condition="'$(DriverType)'=='KMDF'">$(DmfRootPath)\$(Configuration)\$(PlatformName)\lib\DmfK\DmfK.lib;$(DmfRootPath)\$(Configuration)\$(PlatformName)\individual_libs\DmfKModules.Template\DmfKModules.Template.lib;%(AdditionalDependencies);</AdditionalDependencies>
<AdditionalDependencies Condition="'$(DriverType)'=='UMDF'">$(DmfRootPath)\$(Configuration)\$(PlatformName)\lib\DmfU\DmfU.lib;$(DmfRootPath)\$(Configuration)\$(PlatformName)\individual_libs\DmfUModules.Template\DmfUModules.Template.lib;%(AdditionalDependencies);</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_PropertySheetDisplayName>DMF Bus Filter Extension</_PropertySheetDisplayName>
<DmfBusFilterExtensionRootPath Condition="'$(DmfBusFilterExtensionRootPath)' == ''">$(SolutionDir)..\</DmfBusFilterExtensionRootPath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(DmfBusFilterExtensionRootPath)\src;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies Condition="'$(DriverType)'=='KMDF'">$(DmfBusFilterExtensionRootPath)\bin\$(Configuration)\$(PlatformName)\DmfBusFilterExtension.lib;%(AdditionalDependencies);</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

149
src/Driver.c Normal file
View File

@ -0,0 +1,149 @@
/*
* nssudeaudio - USB Bus Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
*
* Copyright (c) 2022-2023, Nefarius Software Solutions e.U.
* All rights reserved.
*
* Redistribution and use in bytecode or binary forms, without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions in bytecode or binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution. This includes repository READMEs for open-source projects
* interfacing with this product, websites or in-application credits.
*
* * Neither the name of the nssudeaudio.sys nor the names of its contributors may
* be used to endorse or promote products derived from or distributed
* with this software without specific prior written permission.
*
* * Bundling or otherwise redistributing copies of binaries signed by
* Nefarius Software Solutions e.U. is prohibited without specific prior
* written permission.
*
* * Personal use for research, experiment, and testing for
* the benefit of public knowledge, personal study, private
* entertainment, hobby projects, amateur pursuits, or religious
* observance, without any anticipated commercial application,
* is use for a permitted purpose.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "Driver.h"
#include "Driver.tmh"
#pragma code_seg("INIT")
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WPP_INIT_TRACING(DriverObject, RegistryPath);
EventRegisterNefarius_USB_Bus_Class_Filter_Driver_for_fixing_UDE_compatibility_with_USBAUDIO_SYS();
FuncEntry(TRACE_DRIVER);
WDFDRIVER driver = NULL;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = EvtDriverContextCleanup;
WDF_DRIVER_CONFIG config;
WDF_DRIVER_CONFIG_INIT(&config,
DMF_BusFilter_DeviceAdd // provided by module
);
NTSTATUS status = WdfDriverCreate(
DriverObject,
RegistryPath,
&attributes,
&config,
&driver
);
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_DRIVER,
"WdfDriverCreate failed %!STATUS!",
status
);
EventWriteFailedWithNTStatus(NULL, __FUNCTION__, L"WdfDriverCreate", status);
goto errorExit;
}
DMF_BusFilter_CONFIG filterConfig;
DMF_BusFilter_CONFIG_INIT(&filterConfig, DriverObject);
filterConfig.DeviceType = FILE_DEVICE_BUS_EXTENDER;
filterConfig.EvtDeviceAdd = EvtChildDeviceAdded;
filterConfig.EvtDeviceQueryInterface = EvtChildDeviceQueryInterface;
status = DMF_BusFilter_Initialize(&filterConfig);
if (!NT_SUCCESS(status))
{
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"DMF_BusFilter_Initialize failed %!STATUS!",
status
);
EventWriteFailedWithNTStatus(NULL, __FUNCTION__, L"DMF_BusFilter_Initialize", status);
goto errorExit;
}
EventWriteStartEvent(NULL, DriverObject, status);
FuncExit(TRACE_DRIVER, "status=%!STATUS!", status);
return status;
errorExit:
EventUnregisterNefarius_USB_Bus_Class_Filter_Driver_for_fixing_UDE_compatibility_with_USBAUDIO_SYS();
WPP_CLEANUP(DriverObject);
return status;
}
#pragma code_seg()
//
// Called on driver object disposal
//
#pragma code_seg("PAGED")
VOID
EvtDriverContextCleanup(
_In_ WDFOBJECT DriverObject
)
{
PAGED_CODE();
FuncEntry(TRACE_DRIVER);
EventWriteUnloadEvent(NULL, DriverObject);
EventUnregisterNefarius_USB_Bus_Class_Filter_Driver_for_fixing_UDE_compatibility_with_USBAUDIO_SYS();
//
// Stop WPP Tracing
//
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
}
#pragma code_seg()

72
src/Driver.h Normal file
View File

@ -0,0 +1,72 @@
/*
* nssudeaudio - USB Bus Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
*
* Copyright (c) 2022-2023, Nefarius Software Solutions e.U.
* All rights reserved.
*
* Redistribution and use in bytecode or binary forms, without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions in bytecode or binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution. This includes repository READMEs for open-source projects
* interfacing with this product, websites or in-application credits.
*
* * Neither the name of the nssudeaudio.sys nor the names of its contributors may
* be used to endorse or promote products derived from or distributed
* with this software without specific prior written permission.
*
* * Bundling or otherwise redistributing copies of binaries signed by
* Nefarius Software Solutions e.U. is prohibited without specific prior
* written permission.
*
* * Personal use for research, experiment, and testing for
* the benefit of public knowledge, personal study, private
* entertainment, hobby projects, amateur pursuits, or religious
* observance, without any anticipated commercial application,
* is use for a permitted purpose.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#pragma warning(disable:5040)
#include <DmfModules.Library.h>
#pragma warning(default:5040)
#include <Dmf_BusFilter.h>
#include <ntddk.h>
#include <wdf.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#include <initguid.h>
#include <devpropdef.h>
#include <devpkey.h>
#include "nssudeaudioETW.h"
#include "Trace.h"
#include "Util.h"
#include "Device.h"
#define MAX_ID_CHARS 200
#define MAX_ID_SIZE (MAX_ID_CHARS * sizeof(WCHAR))
#define NSS_POOL_TAG 'uSSN'
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtDriverContextCleanup;

62
src/Trace.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
//
// Define the tracing flags.
//
// Tracing GUID - {DA6816E8-ED3C-4593-91A1-2CE2DF70184C}
//
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
nssudeaudioTraceGuid, (da6816e8,ed3c,4593,91a1,2ce2df70184c), \
\
WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
WPP_DEFINE_BIT(DMF_TRACE) \
WPP_DEFINE_BIT(TRACE_DRIVER) \
WPP_DEFINE_BIT(TRACE_DEVICE) \
WPP_DEFINE_BIT(TRACE_UTIL) \
)
#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
WPP_LEVEL_LOGGER(flag)
#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
(WPP_LEVEL_ENABLED(flag) && \
WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// USEPREFIX and USESUFFIX strip all trailing whitespace, so we need to surround
// FuncExit messages with brackets
//
// begin_wpp config
// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
// FUNC FuncEntryArguments{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncExitVoid{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
// FUNC TraceError{LEVEL=TRACE_LEVEL_ERROR}(FLAGS, MSG, ...);
// FUNC TraceInformation{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS, MSG, ...);
// FUNC TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncExitNoReturn{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
// USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> Entry");
// USEPREFIX(FuncEntryArguments, "%!STDPREFIX! [%!FUNC!] --> Entry <");
// USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <-- Exit <");
// USESUFFIX(FuncExit, ">");
// USEPREFIX(FuncExitVoid, "%!STDPREFIX! [%!FUNC!] <-- Exit");
// USEPREFIX(TraceError, "%!STDPREFIX! [%!FUNC!] ERROR:");
// USEPREFIX(TraceEvents, "%!STDPREFIX! [%!FUNC!] ");
// USEPREFIX(TraceInformation, "%!STDPREFIX! [%!FUNC!] ");
// USEPREFIX(TraceVerbose, "%!STDPREFIX! [%!FUNC!] ");
// USEPREFIX(FuncExitNoReturn, "%!STDPREFIX! [%!FUNC!] <--");
// end_wpp
//

313
src/Util.c Normal file
View File

@ -0,0 +1,313 @@
/*
* nssudeaudio - USB Bus Class Filter Driver for fixing UDE compatibility with USBAUDIO.SYS
*
* Copyright (c) 2022-2023, Nefarius Software Solutions e.U.
* All rights reserved.
*
* Redistribution and use in bytecode or binary forms, without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions in bytecode or binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution. This includes repository READMEs for open-source projects
* interfacing with this product, websites or in-application credits.
*
* * Neither the name of the nssudeaudio.sys nor the names of its contributors may
* be used to endorse or promote products derived from or distributed
* with this software without specific prior written permission.
*
* * Bundling or otherwise redistributing copies of binaries signed by
* Nefarius Software Solutions e.U. is prohibited without specific prior
* written permission.
*
* * Personal use for research, experiment, and testing for
* the benefit of public knowledge, personal study, private
* entertainment, hobby projects, amateur pursuits, or religious
* observance, without any anticipated commercial application,
* is use for a permitted purpose.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "Driver.h"
#include "Util.tmh"
//
// Set a device property on the provided PDO
//
#pragma code_seg("PAGE")
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
SetDeviceProperty(
_In_ DMFBUSCHILDDEVICE Device,
_In_ const DEVPROPKEY* PropertyKey,
_In_ DEVPROPTYPE PropertyType,
_In_ PWSTR Buffer
)
{
FuncEntry(TRACE_UTIL);
NTSTATUS status = STATUS_SUCCESS;
const PDEVICE_OBJECT pdo = DMF_BusFilter_WdmPhysicalDeviceGet(Device);
PAGED_CODE();
do {
if (!pdo)
{
TraceError(
TRACE_UTIL,
"Failed to get PDO device object"
);
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
size_t numChars = 0;
WCHAR* retval = (WCHAR*)Buffer;
WCHAR* szIter = (WCHAR*)Buffer;
switch (PropertyType)
{
case DEVPROP_TYPE_STRING_LIST:
while (szIter && *szIter && numChars + wcslen(szIter) + 2 <= MAX_ID_SIZE)
{
numChars += wcslen(szIter) + 1;
szIter += wcslen(szIter) + 1;
}
numChars++;
break;
case DEVPROP_TYPE_STRING:
numChars = wcslen(retval) + 1;
break;
default:
status = STATUS_NOT_SUPPORTED;
break;
}
if (!NT_SUCCESS(status))
{
break;
}
status = IoSetDevicePropertyData(
pdo,
PropertyKey,
LOCALE_NEUTRAL,
0,
PropertyType,
(ULONG)numChars * sizeof(WCHAR),
(PVOID)Buffer
);
} while (FALSE);
FuncExit(TRACE_UTIL, "status=%!STATUS!", status);
return status;
}
#pragma code_seg()
//
// Helper function to query device identifiers
//
#pragma code_seg("PAGE")
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS BusQueryId(
PDEVICE_OBJECT DeviceObject,
BUS_QUERY_ID_TYPE IdType,
PWCHAR Buffer,
ULONG BufferLength
)
{
NTSTATUS status;
KEVENT ke;
IO_STATUS_BLOCK iosb;
PIRP irp;
PIO_STACK_LOCATION stack;
FuncEntry(TRACE_UTIL);
PAGED_CODE();
const ULONG maxNumChars = BufferLength / sizeof(WCHAR);
KeInitializeEvent(&ke, NotificationEvent, FALSE);
RtlZeroMemory(&iosb, sizeof(IO_STATUS_BLOCK));
irp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
DeviceObject,
NULL,
0,
NULL,
&ke,
&iosb
);
irp->IoStatus.Status = STATUS_NOT_SUPPORTED; // required initialize
stack = IoGetNextIrpStackLocation(irp);
stack->MinorFunction = IRP_MN_QUERY_ID;
stack->Parameters.QueryId.IdType = IdType;
status = IoCallDriver(DeviceObject, irp);
if (status == STATUS_PENDING)
{
//
// Normally, we will not hit this, because QueryId should not be an expensive operation
//
KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
}
if (NT_SUCCESS(status))
{
if (iosb.Information)
{
size_t length = 0;
WCHAR* retval = (WCHAR*)iosb.Information;
WCHAR* szIter = (WCHAR*)iosb.Information;
switch (IdType) // NOLINT(clang-diagnostic-switch-enum)
{
//
// Double-null terminated multi-strings
//
case BusQueryHardwareIDs:
case BusQueryCompatibleIDs:
//
// Calculate size in characters by finding last double-NULL characters
//
while (szIter && *szIter && length + wcslen(szIter) + 2 <= maxNumChars)
{
length += wcslen(szIter) + 1;
szIter += wcslen(szIter) + 1;
}
length++;
RtlCopyMemory(Buffer, retval, length * sizeof(WCHAR));
ExFreePool(retval); // IRP_MN_QUERY_ID requires this
break;
//
// Single line string
//
default:
if (wcslen(retval) + 1 > maxNumChars)
{
ExFreePool(retval); // IRP_MN_QUERY_ID requires this
status = STATUS_BUFFER_TOO_SMALL;
break;
}
RtlStringCchCopyNW(Buffer, maxNumChars, retval, wcslen(retval) + 1);
ExFreePool(retval); // IRP_MN_QUERY_ID requires this
break;
}
}
else
{
status = STATUS_INVALID_DEVICE_REQUEST;
}
}
FuncExit(TRACE_UTIL, "status=%!STATUS!", status);
return status;
}
#pragma code_seg()
//
// Retrieves the device instance ID of the PDO
//
#pragma code_seg("PAGE")
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
GetDeviceInstanceIdProperty(
_In_ DMFBUSCHILDDEVICE ChildDevice,
_Out_ WDFMEMORY* Value
)
{
NTSTATUS status = STATUS_NOT_IMPLEMENTED;
WCHAR buffer[MAX_ID_CHARS];
ULONG requiredSize = 0;
DEVPROPTYPE type = 0;
WDF_OBJECT_ATTRIBUTES attributes;
PUCHAR memBuffer = NULL;
FuncEntry(TRACE_UTIL);
PAGED_CODE();
PDEVICE_OBJECT pdo = DMF_BusFilter_WdmPhysicalDeviceGet(ChildDevice);
do
{
if (!NT_SUCCESS(status = IoGetDevicePropertyData(
pdo,
&DEVPKEY_Device_InstanceId,
LOCALE_NEUTRAL,
0,
MAX_ID_CHARS,
buffer,
&requiredSize,
&type
)))
{
TraceError(
TRACE_UTIL,
"IoGetDevicePropertyData failed with status %!STATUS!",
status
);
break;
}
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = ChildDevice;
//
// Create context memory
//
if (!NT_SUCCESS(status = WdfMemoryCreate(
&attributes,
NonPagedPoolNx,
NSS_POOL_TAG,
requiredSize,
Value,
(void**)&memBuffer
)))
{
TraceError(
TRACE_UTIL,
"WdfMemoryCreate failed with status %!STATUS!",
status
);
break;
}
RtlCopyMemory(memBuffer, buffer, requiredSize);
} while (FALSE);
FuncExit(TRACE_UTIL, "status=%!STATUS!", status);
return status;
}