diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0631c1968..5faaec7be 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,3 +6,75 @@ # Root files /* @microsoft/driver-samples-maintainers + +# Audio +/audio/ @microsoft/windowsaudio + +# Bluetooth +/bluetooth/ @microsoft/bluetooth + +# Camera Platform +/avstream/ @microsoft/cameraplatdev +/general/SimpleMediaSource/ @microsoft/cameraplatdev + +# Cellular Core +/network/wwan/ @microsoft/cellcore +/nfc/ @microsoft/cellcore + +# Connection Awareness +/gnss/ @microsoft/connection-awareness +/network/radio/ @microsoft/connection-awareness + +# Core Networking +/network/wsk/ @microsoft/corenetworking + +# Consumer Storage +/sd/ @microsoft/consumer-storage +/smartcrd/ @microsoft/consumer-storage + +# Device Enumeration and Interconnect +/gpio/ @microsoft/device-enumeration-and-interconnect +/pofx/PEP/ @microsoft/device-enumeration-and-interconnect +/prm/ @microsoft/device-enumeration-and-interconnect +/wmi/wmiacpi/ @microsoft/device-enumeration-and-interconnect + +# Display Kernel +/video/ @microsoft/display-kernel-devs + +# Driver Development Supplemental Tools +/tools/ @microsoft/windows-driver-developers-supplemental-tools-admins + +# Energy Efficiency +/pofx/WDF/ @microsoft/ee-devs +/simbatt/ @microsoft/ee-devs +/thermal/ @microsoft/ee-devs + +# Event Tracing for Windows +/general/perfcounters/ @microsoft/etw +/general/tracing/ @microsoft/etw + +# File Systems +/filesys/cdfs/ @microsoft/filesystems +/filesys/fastfat/ @microsoft/filesystems + +# Filter Manager +/filesys/miniFilter/ @microsoft/filter-manager + +# Kernel Core +/general/registry/ @microsoft/kernel-core + +# Network Security +/network/trans/ @microsoft/netsec + +# Platform Integrity +/security/ @microsoft/platform-integrity +/TrEE/ @microsoft/platform-integrity + +# Sensors Platform +/sensors/ @microsoft/sensors-platform + +# Storage +/storage/ @microsoft/storage-core + +# Windows Internet of Things +/pos/ @microsoft/winiotdev diff --git a/.github/workflows/Code-Scanning.yml b/.github/workflows/Code-Scanning.yml index fc1ae7e80..6915addfd 100644 --- a/.github/workflows/Code-Scanning.yml +++ b/.github/workflows/Code-Scanning.yml @@ -38,10 +38,10 @@ jobs: submodules: 'recursive' - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - + packs: microsoft/windows-drivers - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v1.3.1 @@ -54,6 +54,9 @@ jobs: WDS_WipeOutputs: ${{ true }} - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" + + + diff --git a/Build-AllSamples.ps1 b/Build-AllSamples.ps1 index 353d95a3a..6b3a19765 100644 --- a/Build-AllSamples.ps1 +++ b/Build-AllSamples.ps1 @@ -56,7 +56,10 @@ $sampleSet = @{} foreach ($file in $solutionFiles) { $dir = (Get-Item $file).DirectoryName $dir_norm = $dir.Replace($root, '').Trim('\').Replace('\', '.').ToLower() - if ($dir_norm -match ($Samples)) { + if ($dir_norm -match ("^packages.")) { + Write-Verbose "`u{1F50E} Found and ignored non-sample [$dir_norm] at $dir" + } + elseif ($dir_norm -match ($Samples)) { Write-Verbose "`u{1F50E} Found and filtered in sample [$dir_norm] at $dir" $sampleSet[$dir_norm] = $dir } diff --git a/Build-Sample.ps1 b/Build-Sample.ps1 index a7c9deb25..0ef9d0518 100644 --- a/Build-Sample.ps1 +++ b/Build-Sample.ps1 @@ -17,6 +17,9 @@ Configuration name that will be used to build the solution. Common available val .PARAMETER Platform Platform to build the solution for (e.g. "x64", "arm64"). +.PARAMETER InfVerif_AdditionalOptions +Additional options for infverif (e.g. "/samples"). + .PARAMETER LogFilesDirectoy Path to a directory where the log files will be written to. If not provided, outputs will be logged to the current working directory. @@ -43,6 +46,7 @@ param( [string]$SampleName, [string]$Configuration = "Debug", [string]$Platform = "x64", + [string]$InfVerif_AdditionalOptions = "/samples", $LogFilesDirectory = (Get-Location) ) @@ -138,16 +142,7 @@ $warnLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.wrn" $OutLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.out" Write-Verbose "Building Sample: $SampleName; Configuration: $Configuration; Platform: $Platform {" - -# Exclude certain InfVerif exceptions to allow samples to build and detect other errors. -# error 1205: Section [xxx] referenced from DelFiles and CopyFiles directive - network\trans -# error 1144: Device software with SoftwareType 1 may not execute on all product types - general\dchu\osrfx2_dchu_extension_tight -# error 1233: Missing directive CatalogFile required for digital signature - storage\class\disk -# error 2083: Section [xxx] not referenced or used - network\trans, storage\msdsm -# error 2084: Service binary 'xxx' should reference a CopyFiles destination file - network\trans, wpd\wpdservicesampledriver -# errors 1324, 1420, 1421, 1402 will be excluded in main branch only until the fixes are merged. -# error 2086 will be excluded until the WDK used in GitHub is updated. -msbuild $solutionFile -clp:Verbosity=m -t:clean,build -property:Configuration=$Configuration -property:Platform=$Platform -p:TargetVersion=Windows10 -p:InfVerif_AdditionalOptions="/samples /msft /sw1144 /sw1199 /sw1205 /sw1233 /sw1324 /sw1420 /sw1421 /sw2083 /sw2084 /sw2086 /sw1402" -p:SignToolWS=/fdws -p:DriverCFlagAddOn=/wd4996 -warnaserror -flp1:errorsonly`;logfile=$errorLogFilePath -flp2:WarningsOnly`;logfile=$warnLogFilePath -noLogo > $OutLogFilePath +msbuild $solutionFile -clp:Verbosity=m -t:rebuild -property:Configuration=$Configuration -property:Platform=$Platform -p:TargetVersion=Windows10 -p:InfVerif_AdditionalOptions="$InfVerif_AdditionalOptions" -warnaserror -flp1:errorsonly`;logfile=$errorLogFilePath -flp2:WarningsOnly`;logfile=$warnLogFilePath -noLogo > $OutLogFilePath if ($env:WDS_WipeOutputs -ne $null) { Write-Verbose ("WipeOutputs: "+$Directory+" "+(((Get-Volume ($DriveLetter=(Get-Item ".").PSDrive.Name)).SizeRemaining/1GB))) diff --git a/Build-SampleSet.ps1 b/Build-SampleSet.ps1 index 535ac6dbb..ffbb9b0ba 100644 --- a/Build-SampleSet.ps1 +++ b/Build-SampleSet.ps1 @@ -45,15 +45,32 @@ finally { } # -# Determine build environment: 'WDK', 'EWDK', or 'GitHub'. Only used to determine build number. +# Determine build environment: 'GitHub', 'NuGet', 'EWDK', or 'WDK'. Only used to determine build number. # Determine build number (used for exclusions based on build number). Five digits. Say, '22621'. # $build_environment="" $build_number=0 # +# WDK NuGet will require presence of a folder 'packages' +# +# +# Hack: In GitHub we do not have an environment variable where we can see WDK build number, so we have it hard coded. +# +if (-not $env:GITHUB_REPOSITORY -eq '') { + $build_environment="GitHub" + $build_number=22621 +} +# +# Hack: If user has hydrated nuget packages, then use those. That will be indicated by presence of a folder named .\packages. +# +elseif(Test-Path(".\packages")) { + $build_environment=("NuGet") + $build_number=26061 +} +# # EWDK sets environment variable BuildLab. For example 'ni_release_svc_prod1.22621.2428'. # -if($env:BuildLab -match '(?[^.]*).(?[^.]*).(?[^.]*)') { +elseif($env:BuildLab -match '(?[^.]*).(?[^.]*).(?[^.]*)') { $build_environment=("EWDK."+$Matches.branch+"."+$Matches.build+"."+$Matches.qfe) $build_number=$Matches.build } @@ -64,13 +81,6 @@ elseif ($env:UCRTVersion -match '10.0.(?.*).0') { $build_environment="WDK" $build_number=$Matches.build } -# -# Hack: In GitHub we do not have an environment variable where we can see WDK build number, so we have it hard coded. -# -elseif (-not $env:GITHUB_REPOSITORY -eq '') { - $build_environment="GitHub" - $build_number=22621 -} else { # Dump all environment variables so as to help debug error: @@ -82,6 +92,21 @@ else { exit 1 } +# +# InfVerif_AdditionalOptions +# +# Samples must build cleanly and even without warnings. +# +# An exception is for infverif where specific warnings are acceptable. Those +# specific warnings indicates issues intentially present in the samples, that +# anyone that clones the samples must fix as part of productizing a driver. +# +# In 22621 those warnings are: /sw1284 /sw1285 /sw1293 /sw2083 /sw2086 +# +# After 22621 those warnings are put under a common flag: /samples +# +$InfVerif_AdditionalOptions=($build_number -le 22621 ? "/sw1284 /sw1285 /sw1293 /sw2083 /sw2086" : "/samples") + # # Determine exclusions. # @@ -127,17 +152,18 @@ $jresult = @{ $SolutionsTotal = $sampleSet.Count * $Configurations.Count * $Platforms.Count -Write-Output ("Build Environment: " + $build_environment) -Write-Output ("Build Number: " + $build_number) -Write-Output ("Samples: " + $sampleSet.Count) -Write-Output ("Configurations: " + $Configurations.Count + " (" + $Configurations + ")") -Write-Output ("Platforms: " + $Platforms.Count + " (" + $Platforms + ")") -Write-Output "Combinations: $SolutionsTotal" -Write-Output "LogicalProcessors: $LogicalProcessors" -Write-Output "ThrottleFactor: $ThrottleFactor" -Write-Output "ThrottleLimit: $ThrottleLimit" -Write-Output "WDS_WipeOutputs: $env:WDS_WipeOutputs" -Write-Output ("Disk Remaining (GB): " + (((Get-Volume ($DriveLetter = (Get-Item ".").PSDrive.Name)).SizeRemaining / 1GB))) +Write-Output ("Build Environment: " + $build_environment) +Write-Output ("Build Number: " + $build_number) +Write-Output ("Samples: " + $sampleSet.Count) +Write-Output ("Configurations: " + $Configurations.Count + " (" + $Configurations + ")") +Write-Output ("Platforms: " + $Platforms.Count + " (" + $Platforms + ")") +Write-Output "InfVerif_AdditionalOptions: $InfVerif_AdditionalOptions" +Write-Output "Combinations: $SolutionsTotal" +Write-Output "LogicalProcessors: $LogicalProcessors" +Write-Output "ThrottleFactor: $ThrottleFactor" +Write-Output "ThrottleLimit: $ThrottleLimit" +Write-Output "WDS_WipeOutputs: $env:WDS_WipeOutputs" +Write-Output ("Disk Remaining (GB): " + (((Get-Volume ($DriveLetter = (Get-Item ".").PSDrive.Name)).SizeRemaining / 1GB))) Write-Output "" Write-Output "T: Combinations" Write-Output "B: Built" @@ -161,6 +187,7 @@ $SampleSet.GetEnumerator() | ForEach-Object -ThrottleLimit $ThrottleLimit -Paral $exclusionReasons = $using:exclusionReasons $Configurations = $using:Configurations $Platforms = $using:Platforms + $InfVerif_AdditionalOptions = $using:InfVerif_AdditionalOptions $Verbose = $using:Verbose $sampleName = $_.Key @@ -185,7 +212,7 @@ $SampleSet.GetEnumerator() | ForEach-Object -ThrottleLimit $ThrottleLimit -Paral $thisresult = "Excluded" } else { - .\Build-Sample -Directory $directory -SampleName $sampleName -LogFilesDirectory $LogFilesDirectory -Configuration $configuration -Platform $platform -Verbose:$Verbose + .\Build-Sample -Directory $directory -SampleName $sampleName -LogFilesDirectory $LogFilesDirectory -Configuration $configuration -Platform $platform -InfVerif_AdditionalOptions $InfVerif_AdditionalOptions -Verbose:$Verbose if ($LASTEXITCODE -eq 0) { $thissucceeded += 1 $thisresult = "Succeeded" diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..5a578a7cf --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/TrEE/Miniport/TrEEMiniportSample.inf b/TrEE/Miniport/TrEEMiniportSample.inf index c1ba30a24..44eae2d67 100644 Binary files a/TrEE/Miniport/TrEEMiniportSample.inf and b/TrEE/Miniport/TrEEMiniportSample.inf differ diff --git a/TrEE/Miniport/TrEEMiniportSample.vcxproj b/TrEE/Miniport/TrEEMiniportSample.vcxproj index f2ec5ea29..7a2265b67 100644 --- a/TrEE/Miniport/TrEEMiniportSample.vcxproj +++ b/TrEE/Miniport/TrEEMiniportSample.vcxproj @@ -38,7 +38,7 @@ Windows10 False - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -46,7 +46,7 @@ Windows10 True - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -54,7 +54,7 @@ Windows10 False - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -62,7 +62,7 @@ Windows10 True - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -70,7 +70,7 @@ Windows10 False - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -78,7 +78,7 @@ Windows10 True - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver diff --git a/TrEE/OSService/TrEEOSServiceSample.inf b/TrEE/OSService/TrEEOSServiceSample.inf index e14149b91..e283ff98c 100644 Binary files a/TrEE/OSService/TrEEOSServiceSample.inf and b/TrEE/OSService/TrEEOSServiceSample.inf differ diff --git a/TrEE/OSService/TrEEOSServiceSample.vcxproj b/TrEE/OSService/TrEEOSServiceSample.vcxproj index d3afa66ac..7fd4726d1 100644 --- a/TrEE/OSService/TrEEOSServiceSample.vcxproj +++ b/TrEE/OSService/TrEEOSServiceSample.vcxproj @@ -38,7 +38,7 @@ Windows10 False - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -46,7 +46,7 @@ Windows10 True - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -54,7 +54,7 @@ Windows10 False - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -62,7 +62,7 @@ Windows10 True - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -70,7 +70,7 @@ Windows10 False - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver @@ -78,7 +78,7 @@ Windows10 True - Desktop + Universal KMDF WindowsKernelModeDriver10.0 Driver diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.inf b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.inf new file mode 100644 index 000000000..889f9bdb8 Binary files /dev/null and b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.inf differ diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.sln b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.sln new file mode 100644 index 000000000..1cedca270 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.sln @@ -0,0 +1,60 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31409.214 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SamplesCommon", "SamplesCommon", "{0DF6D5E6-3B78-414B-B37B-85D9CA454487}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AudioCodec", "AudioCodec", "{0D3B6287-146E-4700-B2EE-11D520014FEA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SamplesCommon", "..\..\Common\SamplesCommon.vcxproj", "{6A946D59-6690-4ED0-A77D-7D4C3D4B3241}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioCodec", "AudioCodec.vcxproj", "{C575002D-5FDE-43C7-AB19-EE846A20083A}" + ProjectSection(ProjectDependencies) = postProject + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} = {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} + 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 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|ARM64.Build.0 = Debug|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|x64.ActiveCfg = Debug|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|x64.Build.0 = Debug|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Debug|x64.Deploy.0 = Debug|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|ARM64.ActiveCfg = Release|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|ARM64.Build.0 = Release|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|ARM64.Deploy.0 = Release|ARM64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|x64.ActiveCfg = Release|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|x64.Build.0 = Release|x64 + {C575002D-5FDE-43C7-AB19-EE846A20083A}.Release|x64.Deploy.0 = Release|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|ARM64.Build.0 = Debug|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|x64.ActiveCfg = Debug|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|x64.Build.0 = Debug|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Debug|x64.Deploy.0 = Debug|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|ARM64.ActiveCfg = Release|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|ARM64.Build.0 = Release|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|ARM64.Deploy.0 = Release|ARM64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|x64.ActiveCfg = Release|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|x64.Build.0 = Release|x64 + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} = {0DF6D5E6-3B78-414B-B37B-85D9CA454487} + {C575002D-5FDE-43C7-AB19-EE846A20083A} = {0D3B6287-146E-4700-B2EE-11D520014FEA} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8E3043F2-1C76-4A4A-9C60-A645BD6CBF24} + EndGlobalSection +EndGlobal diff --git a/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj new file mode 100644 index 000000000..0cdc9e615 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 31 + {C575002D-5FDE-43C7-AB19-EE846A20083A} + {497e31cb-056b-4f31-abb8-447fd55ee5a5} + v4.5 + 12.0 + Debug + AudioCodec + $(LatestTargetPlatformVersion) + + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + KMDF + Windows Driver + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Windows Driver + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + KMDF + Windows Driver + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Windows Driver + + + + + + + + + + + DbgengKernelDebugger + $(IntDir) + + + DbgengKernelDebugger + $(IntDir) + + + DbgengKernelDebugger + $(IntDir) + + + DbgengKernelDebugger + $(IntDir) + + + + true + true + ..\..\common\trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + $(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies) + + + + + true + true + ..\..\common\trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + $(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies) + + + + + true + true + ..\..\common\trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + $(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies) + + + + + true + true + ..\..\common\trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\..\common;..\..\inc;..\..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + $(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib;..\..\Common\$(IntDir)\SamplesCommon.lib;%(AdditionalDependencies) + + + + + + + + + diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.vcxproj.filters b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj.Filters similarity index 77% rename from general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.vcxproj.filters rename to audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj.Filters index 2edeb4fc8..0b882019e 100644 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.vcxproj.filters +++ b/audio/Acx/Samples/AudioCodec/Driver/AudioCodec.vcxproj.Filters @@ -19,26 +19,23 @@ - + + + + Driver Files - - Header Files - - - Header Files - - - Header Files - - + Header Files - + + Source Files + + Source Files diff --git a/audio/Acx/Samples/AudioCodec/Driver/Device.cpp b/audio/Acx/Samples/AudioCodec/Driver/Device.cpp new file mode 100644 index 000000000..7e9a0a3c6 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/Device.cpp @@ -0,0 +1,439 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Device.cpp - Device handling events for example driver. + +Abstract: + + This file contains the device entry points and callbacks. + +Environment: + + Kernel-mode Driver Framework + +--*/ + +#include +#include +#include "public.h" +#include +#include +#include +#include +#include "streamengine.h" +#include "DriverSettings.h" + +#ifndef __INTELLISENSE__ +#include "device.tmh" +#endif + +UNICODE_STRING g_RegistryPath = { 0 }; // This is used to store the registry settings path for the driver + +ULONG DeviceDriverTag = DRIVER_TAG; + +ULONG IdleTimeoutMsec = IDLE_TIMEOUT_MSEC; + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath +) +/*++ + +Routine Description: + +Copies the following registry path to a global variable. + +\REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\\Parameters + +Arguments: + +RegistryPath - Registry path passed to DriverEntry + +Returns: + +NTSTATUS - SUCCESS if able to configure the framework + +--*/ + +{ + PAGED_CODE(); + + // + // Initializing the unicode string, so that if it is not allocated it will not be deallocated too. + // + RtlInitUnicodeString(&g_RegistryPath, nullptr); + + g_RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR); + + g_RegistryPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, g_RegistryPath.MaximumLength, DRIVER_TAG); + + if (g_RegistryPath.Buffer == nullptr) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtBusDeviceAdd( + _In_ WDFDRIVER Driver, + _Inout_ PWDFDEVICE_INIT DeviceInit +) +/*++ + +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. All the software resources + should be allocated in this callback. + +Arguments: + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICE_CONFIG devCfg; + WDFDEVICE device = nullptr; + PCODEC_DEVICE_CONTEXT devCtx; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + // + // The driver calls this DDI in its AddDevice callback before creating the PnP device. + // ACX uses this call to add default/standard settings for the device to be created. + // + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + RETURN_IF_FAILED(AcxDeviceInitInitialize(DeviceInit, &devInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = Codec_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = Codec_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceD0Entry = Codec_EvtDeviceD0Entry; + pnpPowerCallbacks.EvtDeviceD0Exit = Codec_EvtDeviceD0Exit; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = Codec_EvtDeviceContextCleanup; + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&DeviceInit, &attributes, &device)); + + // + // Init Codec's device context. + // + devCtx = GetCodecDeviceContext(device); + ASSERT(devCtx != nullptr); + + devCtx->Render = nullptr; + devCtx->Capture = nullptr; + devCtx->ExcludeD3Cold = WdfFalse; + + // + // The driver calls this DDI in its AddDevice callback after creating the PnP + // device. ACX uses this call to apply any post device settings. + // + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + // + // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so + // that you don't get the popup in usermode (on Win2K) when you surprise + // remove the device. + // + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.SurpriseRemovalOK = WdfTrue; + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + + // + // Create a render circuit and capture circuit and add them to the current + // device context. These circuits will be added to the device when the + // prepare hardware callback is called. + // + RETURN_NTSTATUS_IF_FAILED(CodecR_AddStaticRender(device, &CODEC_RENDER_COMPONENT_GUID, &renderCircuitName)); + + RETURN_NTSTATUS_IF_FAILED(CodecC_AddStaticCapture(device, &CODEC_CAPTURE_COMPONENT_GUID, &MIC_CUSTOM_NAME, &captureCircuitName)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // NOTE: Download firmware here. + + // NOTE: Register streaming h/w resources here. + + // + // Set power policy data. + // + RETURN_NTSTATUS_IF_FAILED(Codec_SetPowerPolicy(Device)); + + // + // Setting up the data saving (CSaveData) and wave file reader (CWaveReader) + // utility classes which will be used by the virtual streaming engine. + // + RETURN_NTSTATUS_IF_FAILED(CSaveData::SetDeviceObject(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(CSaveData::InitializeWorkItems(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(CWaveReader::InitializeWorkItems(WdfDeviceWdmGetDeviceObject(Device))); + + // + // The driver uses this DDI to associate a circuit to a device. After + // this call the circuit is not visible until the device goes in D0. + // For a real driver there should be a check here to make sure the + // circuit has not been added already (there could be a situation where + // prepareHardware is called multiple times and releaseHardware is only + // called once). + // + + ASSERT(devCtx->Render); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Render)); + + ASSERT(devCtx->Capture); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Capture)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PCODEC_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // The driver uses this DDI to delete a circuit from the current device. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceRemoveCircuit(Device, devCtx->Render)); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceRemoveCircuit(Device, devCtx->Capture)); + + // NOTE: Release streaming h/w resources here. + + CSaveData::DestroyWorkItems(); + CWaveReader::DestroyWorkItems(); + + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDeviceD0Entry( + _In_ WDFDEVICE Device, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(PreviousState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +NTSTATUS +Codec_EvtDeviceD0Exit( + _In_ WDFDEVICE Device, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + NTSTATUS status = STATUS_SUCCESS; + POWER_ACTION powerAction; + + PAGED_CODE(); + + powerAction = WdfDeviceGetSystemPowerAction(Device); + + // + // Update the power policy D3-cold info for Connected Standby. + // + if (TargetState == WdfPowerDeviceD3 && powerAction == PowerActionNone) + { + PCODEC_DEVICE_CONTEXT devCtx; + WDF_TRI_STATE excludeD3Cold = WdfTrue; + ACX_DX_EXIT_LATENCY latency; + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Get the current exit latency. + // + latency = AcxDeviceGetCurrentDxExitLatency(Device, + WdfDeviceGetSystemPowerAction(Device), + TargetState); + + // + // If the current exit latency for the ACX device is responsive + // (not instant or fast) then D3-cold does not need to be excluded. + // Otherwise, D3-cold should be excluded because if the hardware + // goes into this state it will take too long to go back into D0 + // and respond. + // + if (latency == AcxDxExitLatencyResponsive) + { + excludeD3Cold = WdfFalse; + } + + if (devCtx->ExcludeD3Cold != excludeD3Cold) + { + devCtx->ExcludeD3Cold = excludeD3Cold; + + RETURN_NTSTATUS_IF_FAILED(Codec_SetPowerPolicy(Device)); + } + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Init the idle policy structure. + // + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = IDLE_POWER_TIMEOUT; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + idleSettings.ExcludeD3Cold = devCtx->ExcludeD3Cold; + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceAssignS0IdleSettings(Device, &idleSettings)); + + return status; +} + +VOID +Codec_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + nullptr + +--*/ +{ + WDFDEVICE device; + PCODEC_DEVICE_CONTEXT devCtx; + + device = (WDFDEVICE)WdfDevice; + devCtx = GetCodecDeviceContext(device); + ASSERT(devCtx != nullptr); + + if (devCtx->Capture) + { + CodecC_CircuitCleanup(devCtx->Capture); + } +} diff --git a/audio/Acx/Samples/AudioCodec/Driver/Driver.cpp b/audio/Acx/Samples/AudioCodec/Driver/Driver.cpp new file mode 100644 index 000000000..452b0d99e --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/Driver.cpp @@ -0,0 +1,129 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Driver.cpp + +Abstract: + + This file contains the driver entry points and callbacks. + +Environment: + + Kernel-mode Driver Framework + +--*/ + +#include "public.h" +#include "cpp_utils.h" + +#ifndef __INTELLISENSE__ +#include "driver.tmh" +#endif + +_Use_decl_annotations_ +void AudioCodecDriverUnload( + _In_ WDFDRIVER Driver +) +{ + PAGED_CODE(); + + if (!Driver) + { + ASSERT(FALSE); + return; + } + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); + + if (g_RegistryPath.Buffer != nullptr) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + return; +} + +INIT_CODE_SEG +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath +) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. DriverEntry specifies the other entry + points in the function driver, such as EvtDevice and DriverUnload. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + WDF_DRIVER_CONFIG wdfCfg; + ACX_DRIVER_CONFIG acxCfg; + WDFDRIVER driver; + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + PAGED_CODE(); + WPP_INIT_TRACING(DriverObject, RegistryPath); + + auto exit = scope_exit([&status, &DriverObject]() { + if (!NT_SUCCESS(status)) + { + WPP_CLEANUP(DriverObject); + + if (g_RegistryPath.Buffer != nullptr) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + } + }); + + RETURN_NTSTATUS_IF_FAILED(CopyRegistrySettingsPath(RegistryPath)); + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + WDF_DRIVER_CONFIG_INIT(&wdfCfg, Codec_EvtBusDeviceAdd); + wdfCfg.EvtDriverUnload = AudioCodecDriverUnload; + + // + // Create a framework driver object to represent our driver. + // + RETURN_NTSTATUS_IF_FAILED(WdfDriverCreate(DriverObject, RegistryPath, &attributes, &wdfCfg, &driver)); + + // + // Initializing the ACX driver configuration struct which contains size and flags + // elements. + // + ACX_DRIVER_CONFIG_INIT(&acxCfg); + + // + // The driver calls this DDI in its DriverEntry callback after creating the WDF driver + // object. ACX uses this call to apply any post driver settings. + // + RETURN_NTSTATUS_IF_FAILED(AcxDriverInitialize(driver, &acxCfg)); + + return status; +} diff --git a/audio/Acx/Samples/AudioCodec/Driver/DriverSettings.h b/audio/Acx/Samples/AudioCodec/Driver/DriverSettings.h new file mode 100644 index 000000000..65aa7f5b9 --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/DriverSettings.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + DriverSettings.h + +Abstract: + + Contains guid definitions and other definitions used by the render and capture circuits + for this specific driver. Driver developers should replace these definitions with their + own. + +Environment: + + Kernel mode + +--*/ + +// Defining the component ID for the capture circuit. This ID uniquely identifies the circuit instance (vendor specific): +DEFINE_GUID(CODEC_CAPTURE_COMPONENT_GUID, 0xc3ee9ec6, 0x8e8c, 0x49e9, 0xaf, 0x4b, 0xa7, 0xfc, 0x28, 0xe9, 0xd2, 0xe7); + +// Defines a custom name for the capture circuit bridge pin: +DEFINE_GUID(MIC_CUSTOM_NAME, 0xd5649dc4, 0x2fa2, 0x418b, 0xb2, 0x78, 0x39, 0x7, 0x64, 0x6b, 0x3, 0xe); + +// Defining the component ID for the render circuit. This ID uniquely identifies the circuit instance (vendor specific): +DEFINE_GUID(CODEC_RENDER_COMPONENT_GUID, 0xd03deb75, 0xe5b2, 0x45f7, 0x91, 0xfa, 0xf7, 0xae, 0x42, 0xdd, 0xf, 0xe0); + +// This is always the definition for the system container guid: +DEFINE_GUID(SYSTEM_CONTAINER_GUID, 0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + +// Driver developers should update this guid if the container is a device rather than a +// system. Otherwise, this GUID should stay the same: +DEFINE_GUID(DEVICE_CONTAINER_GUID, 0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + +// AudioCodec driver tag: +#define DRIVER_TAG (ULONG) 'CduA' + +// The idle timeout in msec for power policy structure: +#define IDLE_TIMEOUT_MSEC (ULONG) 10000 + +// The WPP control GUID defined in Trace.h should also be updated to be unique. + +// This string must match the string defined in AudioCodec.inf for the microphone name: +DECLARE_CONST_UNICODE_STRING(captureCircuitName, L"Microphone0"); + +// This string must match the string defined in AudioCodec.inf for the speaker name: +DECLARE_CONST_UNICODE_STRING(renderCircuitName, L"Speaker0"); diff --git a/audio/Acx/Samples/AudioCodec/Driver/ReadMe.txt b/audio/Acx/Samples/AudioCodec/Driver/ReadMe.txt new file mode 100644 index 000000000..ebc61c6da --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/ReadMe.txt @@ -0,0 +1,42 @@ +======================================================================== + AudioCodec Project Overview +======================================================================== + +This file contains a summary of what you will find in each of the files that make up your project. + +AudioCodec.vcxproj + This is the main project file for projects generated using an Application Wizard. + It contains information about the version of the product that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +AudioCodec.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +Driver.cpp & Driver.h + DriverEntry and WDFDRIVER related functionality and callbacks. Driver developers should + make changes to these files for their specific driver as necessary. + +Device.cpp & Device.h + WDFDEVICE related functionality and callbacks. Driver developers should make changes to + these files for their specific driver as necessary. + +Trace.h + Definitions for WPP tracing. + +DriverSettings.h + Contains guid definitions and other definitions used by the render and capture circuits + for this specific driver. Driver developers should replace these definitions with their + own. + +///////////////////////////////////////////////////////////////////////////// + +Learn more about Kernel Mode Driver Framework here: + +http://msdn.microsoft.com/en-us/library/ff544296(v=VS.85).aspx + +///////////////////////////////////////////////////////////////////////////// diff --git a/audio/Acx/Samples/AudioCodec/Driver/Resources.rc b/audio/Acx/Samples/AudioCodec/Driver/Resources.rc new file mode 100644 index 000000000..788fc416b --- /dev/null +++ b/audio/Acx/Samples/AudioCodec/Driver/Resources.rc @@ -0,0 +1,12 @@ +#include + +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Audio Codec Acx Sample Driver" +#define VER_INTERNALNAME_STR "AudioCodec.sys" +#define VER_ORIGINALFILENAME_STR "AudioCodec.sys" + +#include "common.ver" + diff --git a/audio/Acx/Samples/Common/CaptureCircuit.cpp b/audio/Acx/Samples/Common/CaptureCircuit.cpp new file mode 100644 index 000000000..ba205a907 --- /dev/null +++ b/audio/Acx/Samples/Common/CaptureCircuit.cpp @@ -0,0 +1,799 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + CaptureCircuit.cpp + +Abstract: + + Capture Circuit. This file contains routines to create and handle + capture circuit. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include +#include +#include +#include "AudioFormats.h" +#include "streamengine.h" +#include "cpp_utils.h" +#include "circuithelper.h" + +#ifndef __INTELLISENSE__ +#include "captureCircuit.tmh" +#endif + +// +// Controls how the custom name of the bridge pin is read. +// +BOOL g_UseCustomInfName = TRUE; + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtAcxPinSetDataFormat( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat +) +/*++ + +Routine Description: + + This ACX pin callback sets the device/mixed format. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + PAGED_CODE(); + + // NOTE: update device/mixed format here. + + return STATUS_NOT_SUPPORTED; +} + +/////////////////////////////////////////////////////////// +// +// For more information on volume element see: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/ksnodetype-volume +// +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtVolumeAssignLevelCallback( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _In_ LONG VolumeLevel +) +{ + PAGED_CODE(); + + ASSERT(Volume); + PVOLUME_ELEMENT_CONTEXT volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + volumeCtx->VolumeLevel[Channel] = VolumeLevel; + } + else + { + for (ULONG i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = VolumeLevel; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtVolumeRetrieveLevelCallback( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _Out_ LONG * VolumeLevel +) +{ + PAGED_CODE(); + + ASSERT(Volume); + PVOLUME_ELEMENT_CONTEXT volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel == ALL_CHANNELS_ID) + { + Channel = 0; + } + + *VolumeLevel = volumeCtx->VolumeLevel[Channel]; + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateVolumeElement( + _In_ ACXCIRCUIT Circuit, + _Out_ ACXVOLUME* Element +) +/*++ + +Routine Description: + + This routine creates a volume element. + +Return Value: + + NT status value +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CONFIG volumeCfg; + VOLUME_ELEMENT_CONTEXT * volumeCtx; + + PAGED_CODE(); + + // + // The driver uses this DDI to assign its volume element callbacks. + // + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxVolumeAssignLevel = CodecC_EvtVolumeAssignLevelCallback; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = CodecC_EvtVolumeRetrieveLevelCallback; + + // + // Create Volume element + // + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(Circuit, &attributes, &volumeCfg, Element)); + + ASSERT(*Element != nullptr); + volumeCtx = GetVolumeElementContext(*Element); + ASSERT(volumeCtx); + + // + // (max + min)/2 puts it in the middle of the valid range, divide that by the stepping to get the nearest + // valid step, multiply that by stepping to put it back at a level value. + // + volumeCtx->VolumeLevel[0] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING; + volumeCtx->VolumeLevel[1] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtAcxPinRetrieveName( + _In_ ACXPIN Pin, + _Out_ PUNICODE_STRING Name +) +/*++ + +Routine Description: + + If g_UseCustomInfName is false then the ACX + pin callback EvtAcxPinRetrieveName calls this + function in order to retrieve the pin name. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Pin); + + PAGED_CODE(); + + return RtlUnicodeStringPrintf(Name, L"CustomName2"); +} + +VOID +CodecC_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin +) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + nullptr + +--*/ +{ + UNREFERENCED_PARAMETER(WdfPin); +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CircuitCleanup( + _In_ ACXCIRCUIT Circuit +) +{ + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + // + // Remove the static capture circuit. + // + circuitCtx = GetCaptureCircuitContext(Circuit); + ASSERT(circuitCtx != nullptr); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName +) +/*++ + +Routine Description: + + Creates the static capture circuit (pictured below) + and adds it to the device context. This is called + when a new device is detected and the AddDevice + call is made by the pnp manager. + + ****************************************************** + * Capture Circuit * + * * + * +-----------------------+ * + * | | * + * | +-------------+ | * + * Host ------>| | Volume Node | |---> Bridge * + * Pin | +-------------+ | Pin * + * | | * + * +-----------------------+ * + * * + ****************************************************** + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + PCAPTURE_DEVICE_CONTEXT captureDevCtx; + ACXCIRCUIT captureCircuit = nullptr; + WDF_OBJECT_ATTRIBUTES attributes; + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Alloc audio context to current device. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CAPTURE_DEVICE_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&captureDevCtx)); + ASSERT(captureDevCtx); + + // + // Create a capture circuit associated with this child device. + // + RETURN_NTSTATUS_IF_FAILED(CodecC_CreateCaptureCircuit(Device, ComponentGuid, MicCustomName, CircuitName, &captureCircuit)); + + devCtx->Capture = captureCircuit; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Capture_AllocateSupportedFormats( + _In_ WDFDEVICE Device, + _In_reads_bytes_(CodecCapturePinCount) ACXPIN Pin[], + _In_ ACXCIRCUIT Circuit, + _In_ size_t CodecCapturePinCount +) +{ + UNREFERENCED_PARAMETER(CodecCapturePinCount); + + NTSTATUS status = STATUS_SUCCESS; + ACXDATAFORMAT formatPcm44100c1; + ACXDATAFORMAT formatPcm48000c1; + ACXDATAFORMATLIST formatList; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c1, Circuit, Device, &formatPcm44100c1)); + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c1, Circuit, Device, &formatPcm48000c1)); + + /////////////////////////////////////////////////////////// + // + // Define supported formats for the host pin. + // + + // + // The raw processing mode list is associated with each single circuit + // by ACX. A driver uses this DDI to retrieve the built-in raw + // data-format list. + // + RETURN_NTSTATUS_IF_TRUE(CodecCaptureHostPin >= CodecCapturePinCount, STATUS_INVALID_PARAMETER); + formatList = AcxPinGetRawDataFormatList(Pin[CodecCaptureHostPin]); + RETURN_NTSTATUS_IF_TRUE(formatList == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + // + // The driver uses this DDI to add data formats to the raw + // processing mode list associated with the current circuit. + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c1)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c1)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT* Circuit +) +/*++ + +Routine Description: + + This routine builds the CODEC capture circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + CODEC_CAPTURE_CIRCUIT_CONTEXT* circuitCtx; + ACXPIN pin[CodecCapturePinCount]; + + PAGED_CODE(); + + // + // Init output value. + // + *Circuit = nullptr; + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + { + PACXCIRCUIT_INIT circuitInit = nullptr; + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + + // + // The driver uses this DDI to allocate an ACXCIRCUIT_INIT + // structure. This opaque structure is used when creating + // a standalone audio circuit representing an audio device. + // + circuitInit = AcxCircuitInitAllocate(Device); + + // + // A driver uses this DDI to free the allocated + // ACXCIRCUIT_INIT structure when an error is detected. + // Normally the structures is deleted/cleared by ACX when + // an ACX circuit is created successfully. + // + auto circuitInitScope = scope_exit([&circuitInit]() { + if (circuitInit) { + AcxCircuitInitFree(circuitInit); + } + }); + + // + // The driver uses this DDI to specify the Component ID + // of the ACX circuit. This ID is a guid that uniquely + // identifies the circuit instance (vendor specific). + // + AcxCircuitInitSetComponentId(circuitInit, ComponentGuid); + + // + // The driver uses this DDI to specify the circuit name. + // For standalone circuits, this is the audio device name + // which is used by clients to open handles to the audio devices. + // + (VOID)AcxCircuitInitAssignName(circuitInit, CircuitName); + + // + // The driver uses this DDI to specify the circuit type. The + // circuit type can be AcxCircuitTypeRender, AcxCircuitTypeCapture, + // AcxCircuitTypeOther, or AcxCircuitTypeMaximum (for validation). + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeCapture); + + // + // The driver uses this DDI to assign its (if any) power callbacks. + // + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = CodecC_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = CodecC_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + + // + // The driver uses this DDI to register for a stream-create callback. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback(circuitInit, CodecC_EvtCircuitCreateStream)); + + // + // The driver uses this DDI to create a new ACX circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_CAPTURE_CIRCUIT_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + + circuitInitScope.release(); + + circuitCtx = GetCaptureCircuitContext(circuit); + ASSERT(circuitCtx); + } + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Create volume element. + // + { + ACXELEMENT elements[CaptureElementCount] = { 0 }; + + RETURN_NTSTATUS_IF_FAILED(CodecC_CreateVolumeElement(circuit, (ACXVOLUME*)&elements[CaptureVolumeIndex])); + + // + // Saving the volume element in the circuit context. + // + circuitCtx->VolumeElement = (ACXVOLUME)elements[CaptureVolumeIndex]; + + // + // The driver uses this DDI post circuit creation to add ACXELEMENTs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + } + + /////////////////////////////////////////////////////////// + // + // Create the pins for the circuit. + // + { + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CONFIG pinCfg; + CODEC_PIN_CONTEXT* pinCtx; + + /////////////////////////////////////////////////////////// + // + // Create capture streaming pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = CodecC_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationSink; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecC_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &(pin[CodecCaptureHostPin]))); + + ASSERT(pin[CodecCaptureHostPin] != nullptr); + pinCtx = GetCodecPinContext(pin[CodecCaptureHostPin]); + ASSERT(pinCtx); + pinCtx->CodecPinType = CodecPinTypeHost; + + /////////////////////////////////////////////////////////// + // + // Create capture endpoint pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + ACX_PIN_CONFIG_INIT(&pinCfg); + + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSNODETYPE_MICROPHONE; + pinCfg.PinCallbacks = &pinCallbacks; + + // Specify how to read the custom name. + if (g_UseCustomInfName) + { + pinCfg.Name = MicCustomName; + } + else + { + pinCallbacks.EvtAcxPinRetrieveName = CodecC_EvtAcxPinRetrieveName; + } + g_UseCustomInfName = !g_UseCustomInfName; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &(pin[CodecCaptureBridgePin]))); + + ASSERT(pin[CodecCaptureBridgePin] != nullptr); + } + + /////////////////////////////////////////////////////////// + // + // Add audio jack to bridge pin. + // For more information on audio jack see: https://docs.microsoft.com/en-us/windows/win32/api/devicetopology/ns-devicetopology-ksjack_description + // + { + ACX_JACK_CONFIG jackCfg; + ACXJACK jack; + PJACK_CONTEXT jackCtx; + + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + jackCfg.Description.Color = RGB(0, 0, 0); + jackCfg.Description.ConnectionType = AcxConnTypeAtapiInternal; + jackCfg.Description.GeoLocation = AcxGeoLocFront; + jackCfg.Description.GenLocation = AcxGenLocPrimaryBox; + jackCfg.Description.PortConnection = AcxPortConnIntegratedDevice; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, JACK_CONTEXT); + attributes.ParentObject = pin[CodecCaptureBridgePin]; + + RETURN_NTSTATUS_IF_FAILED(AcxJackCreate(pin[CodecCaptureBridgePin], &attributes, &jackCfg, &jack)); + + ASSERT(jack != nullptr); + + jackCtx = GetJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddJacks(pin[CodecCaptureBridgePin], &jack, 1)); + } + + RETURN_NTSTATUS_IF_FAILED(Capture_AllocateSupportedFormats(Device, pin, circuit, CodecCapturePinCount)); + + /////////////////////////////////////////////////////////// + // + // The driver uses this DDI post circuit creation to add ACXPINs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, pin, CodecCapturePinCount)); + + // + // Set output value. + // + *Circuit = circuit; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtCircuitPowerUp( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +CodecC_EvtCircuitPowerDown( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine creates a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PCAPTURE_DEVICE_CONTEXT devCtx; + WDF_OBJECT_ATTRIBUTES attributes; + ACXSTREAM stream; + STREAMENGINE_CONTEXT * streamCtx; + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_RT_STREAM_CALLBACKS rtCallbacks; + CCaptureStreamEngine * streamEngine = nullptr; + CODEC_CAPTURE_CIRCUIT_CONTEXT * circuitCtx; + CODEC_PIN_CONTEXT * pinCtx; + + auto streamEngineScope = scope_exit([&streamEngine]() { + + if (streamEngine) + { + delete streamEngine; + } + + }); + + PAGED_CODE(); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != nullptr); + + circuitCtx = GetCaptureCircuitContext(Circuit); + ASSERT(circuitCtx != nullptr); + + pinCtx = GetCodecPinContext(Pin); + ASSERT(pinCtx != nullptr); + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = EvtStreamPause; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Init RT streaming callbacks. + // + ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks); + rtCallbacks.EvtAcxStreamGetHwLatency = EvtStreamGetHwLatency; + rtCallbacks.EvtAcxStreamAllocateRtPackets = EvtStreamAllocateRtPackets; + rtCallbacks.EvtAcxStreamFreeRtPackets = EvtStreamFreeRtPackets; + rtCallbacks.EvtAcxStreamGetCapturePacket = CodecC_EvtStreamGetCapturePacket; + rtCallbacks.EvtAcxStreamGetCurrentPacket = EvtStreamGetCurrentPacket; + rtCallbacks.EvtAcxStreamGetPresentationPosition = EvtStreamGetPresentationPosition; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks)); + + // + // Buffer notifications are supported. + // + AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, STREAMENGINE_CONTEXT); + attributes.EvtDestroyCallback = EvtStreamDestroy; + RETURN_NTSTATUS_IF_FAILED(AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + streamCtx = GetStreamEngineContext(stream); + ASSERT(streamCtx); + + // + // Create the virtual streaming engine which will control + // streaming logic for the capture circuit. + // + streamEngine = new (POOL_FLAG_NON_PAGED, DeviceDriverTag) CCaptureStreamEngine(stream, StreamFormat); + RETURN_NTSTATUS_IF_TRUE(streamEngine == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + streamCtx->StreamEngine = (PVOID)streamEngine; + + streamEngine = nullptr; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtStreamGetCapturePacket( + _In_ ACXSTREAM Stream, + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData +) +{ + PSTREAMENGINE_CONTEXT ctx; + CCaptureStreamEngine* streamEngine = nullptr; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast(ctx->StreamEngine); + + return streamEngine->GetCapturePacket(LastCapturePacket, QPCPacketStart, MoreData); +} + + diff --git a/audio/Acx/Samples/Common/CircuitHelper.cpp b/audio/Acx/Samples/Common/CircuitHelper.cpp new file mode 100644 index 000000000..bfff74b22 --- /dev/null +++ b/audio/Acx/Samples/Common/CircuitHelper.cpp @@ -0,0 +1,620 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + CircuitHelper.cpp + +Abstract: + + This module contains helper functions for circuits. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include "CircuitHelper.h" + +#ifndef __INTELLISENSE__ +#include "CircuitHelper.tmh" +#endif + +const ULONG _DSP_STREAM_PROPERTY_UI4_VALUE = 1; + +PAGED_CODE_SEG +NTSTATUS AllocateFormat( + _In_ KSDATAFORMAT_WAVEFORMATEXTENSIBLE WaveFormat, + _In_ ACXCIRCUIT Circuit, + _In_ WDFDEVICE Device, + _Out_ ACXDATAFORMAT* Format +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACX_DATAFORMAT_CONFIG formatCfg; + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &WaveFormat); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FORMAT_CONTEXT); + attributes.ParentObject = Circuit; + + // + // Creates an ACXDATAFORMAT handle for the given wave format. + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, Format)); + + ASSERT((*Format) != NULL); + FORMAT_CONTEXT* formatCtx; + formatCtx = GetFormatContext(*Format); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS CreateStreamBridge( + _In_ ACX_STREAM_BRIDGE_CONFIG StreamCfg, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ DSP_PIN_CONTEXT* PinCtx, + _In_ BOOL Render) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + attributes.ParentObject = Pin; + + ACX_OBJECTBAG_CONFIG objBagCfg; + ACXOBJECTBAG objBag = NULL; + ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg); + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Circuit; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(objBag, &TestUI4, _DSP_STREAM_PROPERTY_UI4_VALUE)); + + // + // Add a stream BRIDGE. + // + PCGUID inModes[] = { + &AUDIO_SIGNALPROCESSINGMODE_RAW, + &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + }; + + if (Render) + { + StreamCfg.InModesCount = SIZEOF_ARRAY(inModes); + StreamCfg.InModes = inModes; + } + + // + // Do not specify InModes for capture - this will prevent the ACX framework from adding created streams to this stream + // bridge automatically. We want to add the stream bridges manually since we don't want KWS streams added. + // + StreamCfg.OutMode = &AUDIO_SIGNALPROCESSINGMODE_RAW; + StreamCfg.OutStreamVarArguments = objBag; + + // + // Uncomment this line to reverse the change-state sequence notifications. + // + // streamCfg.Flags |= AcxStreamBridgeInvertChangeStateSequence; + + ACXSTREAMBRIDGE streamBridge = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxStreamBridgeCreate(Circuit, &attributes, &StreamCfg, &streamBridge)); + + if (!Render) + { + PinCtx->HostStreamBridge = streamBridge; + } + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddStreamBridges(Pin, &streamBridge, 1)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ACXAUDIOENGINE AudioEngineElement, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Explicitly connect the circuit/elements. Note that driver doesn't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for both render and capture devices. + // + // Circuit layout + // ----------------------------------------- + // | | + // | -------------------- | + // Host -0->|-----1->| |-0-------->|-3-> Bridge Pin + // | | Audio Engine | | + // Offload -1->|-----2->| Node |-3--| | + // | |------------------| | | + // | | | + // Loopback <-2-|<------------------------------ | | + // | | + // | | + // |---------------------------------------| + // + + ACX_CONNECTION connections[4]; + + ACX_CONNECTION_INIT(&connections[0], Circuit, AudioEngineElement); + connections[0].FromPin.Id = RenderHostPin; + connections[0].ToPin.Id = 1; + + ACX_CONNECTION_INIT(&connections[1], Circuit, AudioEngineElement); + connections[1].FromPin.Id = RenderOffloadPin; + connections[1].ToPin.Id = 2; + + ACX_CONNECTION_INIT(&connections[2], AudioEngineElement, Circuit); + connections[2].ToPin.Id = RenderLoopbackPin; + connections[2].FromPin.Id = 3; + + ACX_CONNECTION_INIT(&connections[3], AudioEngineElement, Circuit); + connections[3].ToPin.Id = RenderBridgePin; + connections[3].FromPin.Id = 0; + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(Circuit, connections, SIZEOF_ARRAY(connections))); + + return status; + +} + +PAGED_CODE_SEG +NTSTATUS +Codec_GetModeFromAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _Out_ GUID * SignalProcessingMode + ) +{ + NTSTATUS status = STATUS_NO_MORE_ENTRIES; + PKSATTRIBUTE attributeHeader = NULL; + PAGED_CODE(); + *SignalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT; + + status = FindKsAttributeById(Attributes, + AttributesSize, + &KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE, + sizeof(KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE), + &attributeHeader); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + ASSERT(attributeHeader->Attribute == KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE); + ASSERT(attributeHeader->Size == sizeof(KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE)); + + KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE* signalProcessingModeAttribute; + signalProcessingModeAttribute = (KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE*)attributeHeader; + *SignalProcessingMode = signalProcessingModeAttribute->SignalProcessingMode; + status = STATUS_SUCCESS; +exit: + return status; +} + +struct AFX_FIND_KSATTRIBUTE_BY_ID +{ + const _GUID * Id; + ULONG Size; + PKSATTRIBUTE Attribute; +}; + +PAGED_CODE_SEG +NTSTATUS +FindKsAttributeByIdVisitor( + _In_ PKSATTRIBUTE AttributeHeader, + _In_ PVOID Context, + _Out_ BOOLEAN * bContinue + ) +{ + NTSTATUS status = STATUS_SUCCESS; + AFX_FIND_KSATTRIBUTE_BY_ID * ctx = (AFX_FIND_KSATTRIBUTE_BY_ID *)Context; + PAGED_CODE(); + // Default: continue searching. + *bContinue = TRUE; + + if (IsEqualGUIDAligned(AttributeHeader->Attribute, *ctx->Id)) + { + // Validate its size. + if (AttributeHeader->Size < ctx->Size) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + ctx->Attribute = AttributeHeader; + *bContinue = FALSE; + } +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS +FindKsAttributeById( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ const _GUID * AttributeId, + _In_ ULONG AttributeSize, + _Out_ PKSATTRIBUTE * AttributeHeader + ) +{ + PAGED_CODE(); + NTSTATUS status; + AFX_FIND_KSATTRIBUTE_BY_ID ctx = {0}; + *AttributeHeader = NULL; + ctx.Id = AttributeId; + ctx.Size = AttributeSize; + status = TraverseKsAttributeList(Attributes, AttributesSize, FindKsAttributeByIdVisitor, &ctx); + if (!NT_SUCCESS(status)) + { + goto exit; + } + if (ctx.Attribute == NULL) + { + status = STATUS_NO_MORE_ENTRIES; + goto exit; + } + *AttributeHeader = ctx.Attribute; +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS +TraverseKsAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ PFN_KSATTRIBUTES_VISITOR Visitor, + _In_ PVOID Context + ) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + ULONG cbRemaining = 0; + PKSATTRIBUTE attributeHeader = NULL; + ASSERT(Visitor); + // + // Note: multiple-item ptr must have a FILE_QUAD_ALIGNMENT only in relation to the Pin's format size. + // I.e., it is not guaranteed that the attributes are FILE_QUAD_ALIGNMENT in memory, unless the caller reallocates + // them before calling this function (which is currently not done by anyone in any driver/sample). + // + //ASSERT((ULONG_PTR)Attributes == (((ULONG_PTR)Attributes + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT)); + if (AttributesSize < sizeof(KSMULTIPLE_ITEM)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (Attributes->Size < sizeof(KSMULTIPLE_ITEM)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (AttributesSize < Attributes->Size) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + cbRemaining = Attributes->Size; + // + // Init ptr / size of attributes of list. + // + cbRemaining -= sizeof(KSMULTIPLE_ITEM); + attributeHeader = (PKSATTRIBUTE)(Attributes + 1); + for (ULONG i = 0; i < Attributes->Count; i++) + { + BOOLEAN bContinue = TRUE; + size_t cbAttribute = 0; + + if (cbRemaining < sizeof(KSATTRIBUTE)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (attributeHeader->Size < sizeof(KSATTRIBUTE)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + if (cbRemaining < attributeHeader->Size) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + // + // Invoke the descriptor enumeration routine. + // + status = Visitor(attributeHeader, Context, &bContinue); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + if (!bContinue) + { + break; + } + // + // Adjust pointer and buffer size to next attribute (QWORD aligned) + // + cbAttribute = CODEC_ALIGN_SIZE_UP_CONSTANT(attributeHeader->Size, FILE_QUAD_ALIGNMENT); + if (cbRemaining < cbAttribute) + { + // + // Out of buffer, check if this was the last attribute. + // + if (i + 1 != Attributes->Count) + { + // + // This was not the last attribute, nevertheless there is no more buffer, error out. + // + status = STATUS_INVALID_PARAMETER; + goto exit; + } + // This was the final attribute. Exit loop with success status. + break; + } + // Check next attribute. + attributeHeader = (PKSATTRIBUTE)(((PBYTE)attributeHeader) + cbAttribute); + cbRemaining -= (ULONG)cbAttribute; + } + // Normalize success code. + status = STATUS_SUCCESS; +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS +EvtJackRetrievePresence( + _In_ ACXJACK Jack, + _In_ PBOOLEAN IsConnected +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Jack); + UNREFERENCED_PARAMETER(IsConnected); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Because this is a sample we always return true (jack is present). A real driver should check + // if the device is actually present before returning true. + // + *IsConnected = true; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CreateAudioJack( + _In_ ULONG ChannelMapping, + _In_ ULONG Color, + _In_ ACX_JACK_CONNECTION_TYPE ConnectionType, + _In_ ACX_JACK_GEO_LOCATION GeoLocation, + _In_ ACX_JACK_GEN_LOCATION GenLocation, + _In_ ACX_JACK_PORT_CONNECTION PortConnection, + _In_ ULONG Flags, + _In_ ACXPIN BridgePin + ) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + ACX_JACK_CONFIG jackCfg; + ACXJACK jack; + PJACK_CONTEXT jackCtx; + ACX_JACK_CALLBACKS jackCallbacks; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = ChannelMapping; + jackCfg.Description.Color = Color; + jackCfg.Description.ConnectionType = ConnectionType; + jackCfg.Description.GeoLocation = GeoLocation; + jackCfg.Description.GenLocation = GenLocation; + jackCfg.Description.PortConnection = PortConnection; + jackCfg.Flags = Flags; + + ACX_JACK_CALLBACKS_INIT(&jackCallbacks); + jackCallbacks.EvtAcxJackRetrievePresenceState = EvtJackRetrievePresence; + jackCfg.Callbacks = &jackCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, JACK_CONTEXT); + attributes.ParentObject = BridgePin; + + status = AcxJackCreate(BridgePin, &attributes, &jackCfg, &jack); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + ASSERT(jack != nullptr); + + jackCtx = GetJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + status = AcxPinAddJacks(BridgePin, &jack, 1); + +exit: + return status; +} + +PAGED_CODE_SEG +VOID +CpuResourcesCallbackHelper +( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request, + _In_ ACXELEMENT Element +) +{ + NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; + ULONG_PTR outDataCb = 0; + ACX_REQUEST_PARAMETERS params; + ULONG minSize = sizeof(ULONG); + + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + if ((params.Type != AcxRequestTypeProperty) || + (params.Parameters.Property.ItemType != AcxItemTypeElement)) + { + // Return to acx + (VOID) AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + + if (Element == NULL) + { + ntStatus = STATUS_NOT_SUPPORTED; + goto exit; + } + + ULONG elementId = params.Parameters.Property.ItemId; + ULONG currentElementId = AcxElementGetId(Element); + ULONG valueCb = params.Parameters.Property.ValueCb; + + if (valueCb != 0) + { + if (params.Parameters.Property.Value == NULL) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + } + + // + // Check to see if the current node is the peakmeter node, if not then return the call to ACX + // + if (elementId != currentElementId) + { + (VOID) AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + + if (params.Parameters.Property.Verb == AcxPropertyVerbGet) + { + + if (valueCb == 0) + { + outDataCb = minSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + goto exit; + } + else if (valueCb < minSize) + { + outDataCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + else + { + *((PULONG)params.Parameters.Property.Value) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU; + params.Parameters.Property.ValueCb = sizeof(ULONG); + outDataCb = params.Parameters.Property.ValueCb; + ntStatus = STATUS_SUCCESS; + } + } + else if (params.Parameters.Property.Verb == AcxPropertyVerbBasicSupport) + { + if ((valueCb != sizeof(ULONG)) && (valueCb != sizeof(KSPROPERTY_DESCRIPTION))) + { + outDataCb = minSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + goto exit; + } + + if (valueCb >= sizeof(KSPROPERTY_DESCRIPTION)) + { + // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it + // + PKSPROPERTY_DESCRIPTION PropDesc = (PKSPROPERTY_DESCRIPTION)params.Parameters.Property.Value; + + PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET; + PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + PropDesc->PropTypeSet.Id = VT_UI4; + PropDesc->PropTypeSet.Flags = 0; + PropDesc->MembersListCount = 0; + PropDesc->Reserved = 0; + outDataCb = sizeof(KSPROPERTY_DESCRIPTION); + ntStatus = STATUS_SUCCESS; + } + else if (valueCb >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + // + *((PULONG)params.Parameters.Property.Value) = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET; + outDataCb = minSize; + ntStatus = STATUS_SUCCESS; + } + else if (valueCb > 0) + { + outDataCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + outDataCb = minSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + } + else + { + // + // Just give it back to ACX. After this call the request is gone. + // + (VOID) AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + +exit: + if (Request != NULL) + { + WdfRequestCompleteWithInformation(Request, ntStatus, outDataCb); + } +} // EvtAudioCpuResourcesCallback diff --git a/audio/Acx/Samples/Common/CircuitHelper.h b/audio/Acx/Samples/Common/CircuitHelper.h new file mode 100644 index 000000000..589381534 --- /dev/null +++ b/audio/Acx/Samples/Common/CircuitHelper.h @@ -0,0 +1,135 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + CircuitHelper.h + +Abstract: + + This module contains helper functions for endpoints. + +Environment: + + Kernel mode + +--*/ + +// size_t +// __inline +// CODEC_ALIGN_SIZE_DOWN_CONSTANT( +// IN size_t Length, +// IN size_t AlignTo +// ) +#define CODEC_ALIGN_SIZE_DOWN_CONSTANT(Length, AlignTo) ((Length) & ~((AlignTo)-1)) + +#define CODEC_ALIGN_SIZE_DOWN CODEC_ALIGN_SIZE_DOWN_CONSTANT + +// size_t +// __inline +// CODEC_ALIGN_SIZE_UP_CONSTANT( +// IN size_t Length, +// IN size_t AlignTo +// ) +#define CODEC_ALIGN_SIZE_UP_CONSTANT(Length, AlignTo) CODEC_ALIGN_SIZE_DOWN_CONSTANT((Length) + (AlignTo)-1, (AlignTo)) + +#define CODEC_ALIGN_SIZE_UP CODEC_ALIGN_SIZE_UP_CONSTANT + +PAGED_CODE_SEG +NTSTATUS +Codec_GetModeFromAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _Out_ GUID * SignalProcessingMode + ); + +// +// Enumeration visitor callback. +// +typedef +NTSTATUS +(EVT_KSATTRIBUTES_VISITOR)( + _In_ PKSATTRIBUTE AttributeHeader, + _In_ PVOID Context, + _Out_ BOOLEAN * bContinue + ); + +typedef EVT_KSATTRIBUTES_VISITOR *PFN_KSATTRIBUTES_VISITOR; + +static +PAGED_CODE_SEG +EVT_KSATTRIBUTES_VISITOR FindKsAttributeByIdVisitor; + +PAGED_CODE_SEG +NTSTATUS +FindKsAttributeById( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ const _GUID * AttributeId, + _In_ ULONG AttributeSize, + _Out_ PKSATTRIBUTE * AttributeHeader + ); + +PAGED_CODE_SEG +NTSTATUS +TraverseKsAttributeList( + _In_ const PKSMULTIPLE_ITEM Attributes, + _In_ ULONG AttributesSize, + _In_ PFN_KSATTRIBUTES_VISITOR Visitor, + _In_ PVOID Context + ); + +PAGED_CODE_SEG +NTSTATUS AllocateFormat( + _In_ KSDATAFORMAT_WAVEFORMATEXTENSIBLE WaveFormat, + _In_ ACXCIRCUIT Circuit, + _In_ WDFDEVICE Device, + _Out_ ACXDATAFORMAT* Format +); + +PAGED_CODE_SEG +NTSTATUS CreateStreamBridge( + _In_ ACX_STREAM_BRIDGE_CONFIG StreamCfg, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ DSP_PIN_CONTEXT* PinCtx, + _In_ BOOL Render +); + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ACXAUDIOENGINE AudioEngineElement, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateAudioJack( + _In_ ULONG ChannelMapping, + _In_ ULONG Color, + _In_ ACX_JACK_CONNECTION_TYPE ConnectionType, + _In_ ACX_JACK_GEO_LOCATION GeoLocation, + _In_ ACX_JACK_GEN_LOCATION GenLocation, + _In_ ACX_JACK_PORT_CONNECTION PortConnection, + _In_ ULONG Flags, + _In_ ACXPIN BridgePin +); + +PAGED_CODE_SEG +NTSTATUS EvtJackRetrievePresence( + _In_ ACXJACK Jack, + _In_ PBOOLEAN IsConnected +); + +PAGED_CODE_SEG +VOID CpuResourcesCallbackHelper( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request, + _In_ ACXELEMENT Element +); + diff --git a/audio/Acx/Samples/Common/KeywordDetector.cpp b/audio/Acx/Samples/Common/KeywordDetector.cpp new file mode 100644 index 000000000..f34767450 --- /dev/null +++ b/audio/Acx/Samples/Common/KeywordDetector.cpp @@ -0,0 +1,484 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + KeywordDetector.cpp + +Abstract: + + Sample keyword detector management. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include +#include +#include +#include "streamengine.h" +#include "KeywordDetector.h" + +PAGED_CODE_SEG +CKeywordDetector::CKeywordDetector() + : + m_streamRunning(FALSE), + m_qpcStartCapture(0), + m_nLastQueuedPacket(-1), + m_SoundDetectorArmed1(FALSE), + m_SoundDetectorArmed2(FALSE), + m_SoundDetectorData1(0), + m_SoundDetectorData2(0), + m_ullKeywordStartTimestamp(0), + m_ullKeywordStopTimestamp(0) +{ + PAGED_CODE(); + + // Initialize our pool of packets and the list structures + KeInitializeSpinLock(&PacketPoolSpinLock); + KeInitializeSpinLock(&PacketFifoSpinLock); + ResetFifo(); +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() +{ + PAGED_CODE(); + + NTSTATUS ntStatus; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; + + RTL_QUERY_REGISTRY_TABLE paramTable[] = { + // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"KeywordDetectorStartTimestamp", &m_ullKeywordStartTimestamp, (REG_QWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_QWORD, &m_ullKeywordStartTimestamp, sizeof(ULONGLONG) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"KeywordDetectorStopTimestamp", &m_ullKeywordStopTimestamp, (REG_QWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_QWORD, &m_ullKeywordStopTimestamp, sizeof(ULONGLONG) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); + + if (!NT_SUCCESS(ntStatus)) + { + return ntStatus; + } + + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); + if (DriverKey) + { + ZwClose(DriverKey); + } + + return ntStatus; +} + + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::ResetDetector(_In_ GUID eventId) +{ + PAGED_CODE(); + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else if(eventId == GUID_NULL) + { + // When DownloadDetectorData is called to set the pattern for multiple keywords + // at once, all keyword detectors must be reset. Also used during keyword detector + // initialization and cleanup to restore it back to initial state and power down. + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data) +{ + PAGED_CODE(); + + // reset the detector for this event Id + ResetDetector(eventId); + + // In this example, the driver supports detection data + // set with a single call for both detectors, or each + // detector set individually. + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = Data; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = Data; + } + else if(eventId == GUID_NULL) + { + // in this simplified example "Data" is set on both detectors, + // however in a real system "Data" could be a data structure which + // contains different values for each detector. + m_SoundDetectorData1 = m_SoundDetectorData2 = Data; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +// The following function is only applicable to single keyword detection systems, +// and assumes keyword detector #1. +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data) +{ + PAGED_CODE(); + + if (eventId == CONTOSO_KEYWORD1) + { + *Data = m_SoundDetectorData1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Data = m_SoundDetectorData2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +ULONGLONG CKeywordDetector::GetStartTimestamp() +{ + PAGED_CODE(); + + return m_ullKeywordStartTimestamp; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +ULONGLONG CKeywordDetector::GetStopTimestamp() +{ + PAGED_CODE(); + + return m_ullKeywordStopTimestamp; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::ResetFifo() +{ + PAGED_CODE(); + + m_qpcStartCapture = 0; + m_nLastQueuedPacket = (-1); + InitializeListHead(&PacketPoolHead); + InitializeListHead(&PacketFifoHead); + + for (int i = 0; i < ARRAYSIZE(PacketPool); i++) + { + InsertTailList(&PacketPoolHead, &PacketPool[i].ListEntry); + } + return; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm) +{ + PAGED_CODE(); + + BOOL previousArming = FALSE; + NTSTATUS ntStatus = STATUS_SUCCESS; + + // the previous state is "armed" if either detector is armed. + // this reflects the fact that both detectors are sharing the + // same stream. + previousArming = m_SoundDetectorArmed1 || m_SoundDetectorArmed2; + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorArmed1 = Arm; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorArmed2 = Arm; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + if (Arm && !previousArming && m_qpcStartCapture == 0) + { + StartBufferingStream(); + } + else if (!Arm && previousArming && !m_streamRunning) + { + // if it's not actively streaming and everything has been disarmed, + // then stop buffering. + ResetFifo(); + } + + return ntStatus; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (eventId == CONTOSO_KEYWORD1) + { + *Arm = m_SoundDetectorArmed1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Arm = m_SoundDetectorArmed2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return ntStatus; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::Run() +{ + PAGED_CODE(); + + if (m_qpcStartCapture == 0) + { + StartBufferingStream(); + } + + m_streamRunning = TRUE; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::Stop() +{ + PAGED_CODE(); + + ResetFifo(); + m_streamRunning = FALSE; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::StartBufferingStream() +{ + LARGE_INTEGER qpc; + LARGE_INTEGER qpcFrequency; + + PAGED_CODE(); + + qpc = KeQueryPerformanceCounter(&qpcFrequency); + m_qpcStartCapture = qpc.QuadPart; + m_qpcFrequency = qpcFrequency.QuadPart; + + return; +} + +PAGED_CODE_SEG +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::NotifyDetection() +{ + PAGED_CODE(); + + // A detection will only happen if armed and the + // stream is already running. If there isn't a client + // running, then set the stream start time to align + // with this detection. + if (!m_streamRunning) + { + StartBufferingStream(); + + // The following code is for testing purposes only. + // m_qpcFrequency is defined to be the number of ticks in 1 second. + // Use the stream start time (the current time retrieved in StartBufferStream) to + // mark when the keyword ended, and the start time minus 1 second worth of ticks + // to mark when the keyword started. Also, adjust the stream start time to align + // to this new keyword start time, so that the simulated stream contains the full keyword. + + m_ullKeywordStopTimestamp = m_qpcStartCapture; // stop time is the current time + m_qpcStartCapture = m_qpcStartCapture - m_qpcFrequency; // buffer start time is 1 second ago + m_ullKeywordStartTimestamp = m_qpcStartCapture; // buffer start time = keyword start time + + } + else + { + // The following code is for testing purposes only. + // If the stream is running, we cannot modify qpcStartCapture to be in + // the past, so instead make the keyword start & stop times fit within the + // time period that the keyword has been running. If it has been running + // for more than 1 second, then set the keyword start time to be 1 second back + // into the stream, as though we just figured out there was a keyword there. + // If it has been running less than one second, then the keyword size ends + // up being however long the stream has been running. + + LARGE_INTEGER qpc; + qpc = KeQueryPerformanceCounter(NULL); + + m_ullKeywordStopTimestamp = qpc.QuadPart; // stop time is the current time + + if (m_qpcStartCapture < (qpc.QuadPart - m_qpcFrequency)) + { + m_ullKeywordStartTimestamp = (qpc.QuadPart - m_qpcFrequency); + } + else + { + m_ullKeywordStartTimestamp = m_qpcStartCapture; + } + + } + + return; +} + +_IRQL_requires_min_(DISPATCH_LEVEL) +VOID CKeywordDetector::DpcRoutine(_In_ LONGLONG PerformanceCounter, _In_ LONGLONG PerformanceFrequency) +{ + LONGLONG currentPacket; + LONGLONG packetsToQueue; + + // TODO: the timer only runs when the stream is open, but really for KWS it should be building up a collection of burst data + // in the queue from 1.5 sec before the trigger happens. Is there some way to simulate that behavior here? Without doing that, + // there isn't really a burst that happens, just a trickle because while the timestamps will be right, the queue won't contain + // anything until the timer fires at the normal rate. + + if (m_qpcStartCapture <= 0) + { + return; + } + + currentPacket = (PerformanceCounter - m_qpcStartCapture) * (SamplesPerSecond / SamplesPerPacket) / PerformanceFrequency; + packetsToQueue = currentPacket - m_nLastQueuedPacket; + + while (packetsToQueue > 0) + { + LIST_ENTRY* packetListEntry; + PACKET_ENTRY* packetEntry; + + do + { + packetListEntry = ExInterlockedRemoveHeadList(&PacketPoolHead, &PacketPoolSpinLock); + if (packetListEntry != NULL) break; + + // Pool is empty, no room to buffer more, an overrun is occurring. Drop and reuse the + // oldest packet from head of fifo. + + // Since the pool is empty, the fifo should be full. However, although unlikely, the + // driver might empty the fifo before this routine removes a packet. In that case, the + // pool should have packets available again. Therefore this is a retry loop. + packetListEntry = ExInterlockedRemoveHeadList(&PacketFifoHead, &PacketFifoSpinLock); + if (packetListEntry != NULL) break; + } while (TRUE); + + packetEntry = CONTAINING_RECORD(packetListEntry, PACKET_ENTRY, ListEntry); + + packetEntry->PacketNumber = ++m_nLastQueuedPacket; + packetEntry->QpcWhenSampled = m_qpcStartCapture + (packetEntry->PacketNumber * PerformanceFrequency * SamplesPerPacket / SamplesPerSecond); + + // TODO: this should really put something real in the buffer. Use the sine tone generator maybe? + RtlZeroMemory(&packetEntry->Samples[0], sizeof(packetEntry->Samples)); + + ExInterlockedInsertTailList(&PacketFifoHead, packetListEntry, &PacketFifoSpinLock); + + packetsToQueue -= 1; + } +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetReadPacket +( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_writes_(PacketSize) PVOID *Packets, + _Out_ ULONG *PacketNumber, + _Out_ ULONG64 *PerformanceCounterValue, + _Out_ BOOLEAN *MoreData +) +{ + NTSTATUS ntStatus; + BYTE *packetData; + PACKET_ENTRY *packetEntry; + LIST_ENTRY *packetListEntry = NULL; + + packetListEntry = ExInterlockedRemoveHeadList(&PacketFifoHead, &PacketFifoSpinLock); + if (packetListEntry == NULL) + { + ntStatus = STATUS_DEVICE_NOT_READY; + goto Exit; + } + packetEntry = CONTAINING_RECORD(packetListEntry, PACKET_ENTRY, ListEntry); + + ntStatus = RtlLongLongToULong(packetEntry->PacketNumber, PacketNumber); + if (!NT_SUCCESS(ntStatus)) + { + goto Exit; + } + + packetData = (PBYTE) Packets[(*PacketNumber) % PacketCount]; + + *PerformanceCounterValue = packetEntry->QpcWhenSampled; + *MoreData = !IsListEmpty(&PacketFifoHead); + + // TODO: the packet size here needs to line up to the packet size allocated. + // Also, handle the first packet offset + RtlCopyMemory(packetData, packetEntry->Samples, min(sizeof(packetEntry->Samples), PacketSize)); + +Exit: + if (packetListEntry != NULL) + { + ExInterlockedInsertTailList(&PacketPoolHead, packetListEntry, &PacketPoolSpinLock); + } + + return ntStatus; +} diff --git a/audio/Acx/Samples/Common/KeywordDetector.h b/audio/Acx/Samples/Common/KeywordDetector.h new file mode 100644 index 000000000..2d5293b86 --- /dev/null +++ b/audio/Acx/Samples/Common/KeywordDetector.h @@ -0,0 +1,145 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + KeywordDetector.h + +Abstract: + + Sample Keyword Detector. + + +--*/ + +#pragma once + +typedef struct +{ + SOUNDDETECTOR_PATTERNHEADER Header; + LONGLONG ContosoDetectorConfigurationData; +} CONTOSO_KEYWORDCONFIGURATION; + +typedef struct +{ + SOUNDDETECTOR_PATTERNHEADER Header; + LONGLONG ContosoDetectorResultData; + ULONGLONG KeywordStartTimestamp; + ULONGLONG KeywordStopTimestamp; + GUID EventId; +} CONTOSO_KEYWORDDETECTIONRESULT; + +DEFINE_GUID(CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2, +0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9); + +// {A537F559-2D67-463B-B10E-BEB750A21F31} +DEFINE_GUID(CONTOSO_KEYWORD1, +0xa537f559, 0x2d67, 0x463b, 0xb1, 0xe, 0xbe, 0xb7, 0x50, 0xa2, 0x1f, 0x31); +// {655E417A-80A5-4A77-B3F1-512EAF67ABCF} +DEFINE_GUID(CONTOSO_KEYWORD2, +0x655e417a, 0x80a5, 0x4a77, 0xb3, 0xf1, 0x51, 0x2e, 0xaf, 0x67, 0xab, 0xcf); + +#define KEYWORDDETECTOR_POOLTAG 'KWS0' + +class CKeywordDetector +{ +public: + PAGED_CODE_SEG + CKeywordDetector(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ResetDetector(_In_ GUID eventId); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + ULONGLONG GetStartTimestamp(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + ULONGLONG GetStopTimestamp(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID NotifyDetection(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID Run(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID Stop(); + + _IRQL_requires_min_(DISPATCH_LEVEL) + VOID DpcRoutine(_In_ LONGLONG PerformanceCounter, _In_ LONGLONG PerformanceFrequency); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetReadPacket(_In_ ULONG PacketCount, _In_ ULONG PacketSize, _Out_writes_(PacketSize) PVOID *Packets, _Out_ ULONG *PacketNumber, _Out_ ULONGLONG *PerformanceCount, _Out_ BOOLEAN *MoreData); + +private: + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID ResetFifo(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ReadKeywordTimestampRegistry(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID StartBufferingStream(); + + // The Contoso keyword detector processes 10ms packets of 16KHz 16-bit PCM + // audio samples + static const int SamplesPerSecond = 16000; + static const int SamplesPerPacket = (10 * SamplesPerSecond / 1000); + + typedef struct + { + LIST_ENTRY ListEntry; + LONGLONG PacketNumber; + LONGLONG QpcWhenSampled; + UINT16 Samples[SamplesPerPacket]; + } PACKET_ENTRY; + + BOOLEAN m_streamRunning; + + BOOLEAN m_SoundDetectorArmed1; + BOOLEAN m_SoundDetectorArmed2; + LONGLONG m_SoundDetectorData1; + LONGLONG m_SoundDetectorData2; + + LONGLONG m_qpcStartCapture; + LONGLONG m_qpcFrequency; + LONGLONG m_nLastQueuedPacket; + + ULONGLONG m_ullKeywordStartTimestamp; + ULONGLONG m_ullKeywordStopTimestamp; + + KSPIN_LOCK PacketPoolSpinLock; + LIST_ENTRY PacketPoolHead; + PACKET_ENTRY PacketPool[1 * SamplesPerSecond / SamplesPerPacket]; // Enough storage for 1 second of audio data + + KSPIN_LOCK PacketFifoSpinLock; + LIST_ENTRY PacketFifoHead; + +}; + diff --git a/audio/Acx/Samples/Common/NewDelete.cpp b/audio/Acx/Samples/Common/NewDelete.cpp new file mode 100644 index 000000000..583d36c5c --- /dev/null +++ b/audio/Acx/Samples/Common/NewDelete.cpp @@ -0,0 +1,91 @@ +/*++ + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. +Module Name: + newdelete.cpp +Abstract: + Contains overloaded placement new and delete operators +Environment: + Kernel mode +--*/ + +#include "private.h" +#include "NewDelete.h" + +/***************************************************************************** + * ::new(POOL_FLAGS) + ***************************************************************************** + * New function for creating objects with a specified pool flags. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags +) +{ + PVOID result = ExAllocatePool2(poolFlags, size, 'wNwS'); + + return result; +} + +/***************************************************************************** + * ::new(POOL_FLAGS, TAG) + ***************************************************************************** + * New function for creating objects with specified pool flags and allocation tag. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags, + _In_ ULONG tag +) +{ + PVOID result = ExAllocatePool2(poolFlags, size, tag); + + return result; +} + +void __cdecl operator delete(PVOID buffer) +{ + if (buffer) + { + ExFreePool(buffer); + } +} + +void __cdecl operator delete(PVOID buffer, ULONG tag) +{ + if (buffer) + { + ExFreePoolWithTag(buffer, tag); + } +} + +void __cdecl operator delete(_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize) +{ + UNREFERENCED_PARAMETER(cbSize); + + if (buffer) + { + ExFreePool(buffer); + } +} + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer) +{ + if (buffer) + { + ExFreePool(buffer); + } +} + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize) +{ + UNREFERENCED_PARAMETER(cbSize); + + if (buffer) + { + ExFreePool(buffer); + } +} + diff --git a/audio/Acx/Samples/Common/NewDelete.h b/audio/Acx/Samples/Common/NewDelete.h new file mode 100644 index 000000000..fb660ff9c --- /dev/null +++ b/audio/Acx/Samples/Common/NewDelete.h @@ -0,0 +1,58 @@ +/*++ +Copyright (c) Microsoft Corporation. All rights reserved. + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. +Module Name: + NewDelete.h +Abstract: + Contains overloaded placement new and delete operators +Environment: + Kernel mode +--*/ + +/***************************************************************************** + * ::new(POOL_FLAGS) + ***************************************************************************** + * New function for creating objects with a specified pool flags. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags +); + +/***************************************************************************** + * ::new(POOL_FLAGS, TAG) + ***************************************************************************** + * New function for creating objects with specified pool flags and allocation tag. + */ +PVOID operator new( + _In_ size_t size, + _In_ POOL_FLAGS poolFlags, + _In_ ULONG tag +); + +/***************************************************************************** + * ::delete() + ***************************************************************************** + * Delete function. + */ +void __cdecl operator delete(PVOID buffer); + +/***************************************************************************** + * ::delete() + ***************************************************************************** + * Delete function. + */ +void __cdecl operator delete(PVOID buffer, ULONG tag); + +void __cdecl operator delete[](PVOID pVoid, _In_ size_t cbSize); + +void __cdecl operator delete(_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize); + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer); + +void __cdecl operator delete[](_Pre_maybenull_ __drv_freesMem(Mem) PVOID buffer, _In_ size_t cbSize); + + diff --git a/audio/Acx/Samples/Common/Private.h b/audio/Acx/Samples/Common/Private.h new file mode 100644 index 000000000..da89ef785 --- /dev/null +++ b/audio/Acx/Samples/Common/Private.h @@ -0,0 +1,922 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + Private.h + +Abstract: + + Contains structure definitions and function prototypes private to + the Common library. + +Environment: + + Kernel mode + +--*/ + +#ifndef _PRIVATE_H_ +#define _PRIVATE_H_ + + +#include +#include +#include "cpp_utils.h" +#include +#include +#include +#include "NewDelete.h" + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include "Trace.h" + +#include +#include + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +extern const GUID DSP_CIRCUIT_SPEAKER_GUID; +extern const GUID DSP_CIRCUIT_MICROPHONE_GUID; +extern const GUID DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID; +extern const GUID DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID; + +///////////////////////////////////////////////////////// +// +// Driver wide definitions +// + +// Copied from cfgmgr32.h +#if !defined(MAX_DEVICE_ID_LEN) +#define MAX_DEVICE_ID_LEN 200 +#endif + +// Number of millisecs per sec. +#define MS_PER_SEC 1000 + +// Number of hundred nanosecs per sec. +#define HNS_PER_SEC 10000000 + +#define REQUEST_TIMEOUT_SECONDS 5 + +#undef MIN +#undef MAX +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef SIZEOF_ARRAY +#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) +#endif // !defined(SIZEOF_ARRAY) + +#ifndef RGB +#define RGB(r, g, b) (DWORD)(r << 16 | g << 8 | b) +#endif + +#define ALL_CHANNELS_ID UINT32_MAX +#define MAX_CHANNELS 2 + +// +// Ks support. +// +#define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \ + KSPROPERTY_TYPE_GET | \ + KSPROPERTY_TYPE_SET + +// +// Define struct to hold signal processing mode and corresponding +// list of supported formats. +// +typedef struct +{ + GUID SignalProcessingMode; + KSDATAFORMAT_WAVEFORMATEXTENSIBLE* FormatList; + ULONG FormatListCount; +} SUPPORTED_FORMATS_LIST; + +// +// Define CAPTURE device context. +// +typedef struct _CAPTURE_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} CAPTURE_DEVICE_CONTEXT, * PCAPTURE_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CAPTURE_DEVICE_CONTEXT, GetCaptureDeviceContext) + +// +// Define RENDER device context. +// +typedef struct _RENDER_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} RENDER_DEVICE_CONTEXT, * PRENDER_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(RENDER_DEVICE_CONTEXT, GetRenderDeviceContext) + +// +// Define circuit/stream element context. +// +typedef struct _ELEMENT_CONTEXT { + BOOLEAN Dummy; +} ELEMENT_CONTEXT, *PELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ELEMENT_CONTEXT, GetElementContext) + +// +// Define circuit/stream element context. +// +typedef struct _MUTE_ELEMENT_CONTEXT { + BOOL MuteState[MAX_CHANNELS]; +} MUTE_ELEMENT_CONTEXT, *PMUTE_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MUTE_ELEMENT_CONTEXT, GetMuteElementContext) + +// +// Define circuit/stream element context. +// +typedef struct _VOLUME_ELEMENT_CONTEXT { + LONG VolumeLevel[MAX_CHANNELS]; +} VOLUME_ELEMENT_CONTEXT, *PVOLUME_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(VOLUME_ELEMENT_CONTEXT, GetVolumeElementContext) + +#define VOLUME_STEPPING 0x8000 +#define VOLUME_LEVEL_MAXIMUM 0x00000000 +#define VOLUME_LEVEL_MINIMUM (-96 * 0x10000) + +// +// Define mute timer context. +// +typedef struct _MUTE_TIMER_CONTEXT { + ACXELEMENT MuteElement; + ACXEVENT Event; +} MUTE_TIMER_CONTEXT, *PMUTE_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MUTE_TIMER_CONTEXT, GetMuteTimerContext) + +// +// Define format context. +// +typedef struct _FORMAT_CONTEXT { + BOOLEAN Dummy; +} FORMAT_CONTEXT, *PFORMAT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FORMAT_CONTEXT, GetFormatContext) + +// +// Define jack context. +// +typedef struct _JACK_CONTEXT { + ULONG Dummy; +} JACK_CONTEXT, * PJACK_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(JACK_CONTEXT, GetJackContext) + +// +// Define audio engine context. +// +typedef struct _ENGINE_CONTEXT { + ACXDATAFORMAT MixFormat; +} ENGINE_CONTEXT, * PENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ENGINE_CONTEXT, GetEngineContext) + +// +// Define stream audio engine context. +// +typedef struct _STREAMAUDIOENGINE_CONTEXT { + BOOLEAN Dummy; +} STREAMAUDIOENGINE_CONTEXT, * PSTREAMAUDIOENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAMAUDIOENGINE_CONTEXT, GetStreamAudioEngineContext) + +// +// Define keyword spotter context +// +typedef struct _KEYWORDSPOTTER_CONTEXT { + ACXPNPEVENT Event; + PVOID KeywordDetector; +} KEYWORDSPOTTER_CONTEXT, * PKEYWORDSPOTTER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(KEYWORDSPOTTER_CONTEXT, GetKeywordSpotterContext) + +// +// Define pnp event context. +// +typedef struct _PNPEVENT_CONTEXT { + BOOLEAN Dummy; +} PNPEVENT_CONTEXT, * PPNPEVENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PNPEVENT_CONTEXT, GetPnpEventContext) + +// +// Define peakmeter element context. +// +typedef struct _PEAKMETER_ELEMENT_CONTEXT { + LONG PeakMeterLevel[MAX_CHANNELS]; +} PEAKMETER_ELEMENT_CONTEXT, * PPEAKMETER_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PEAKMETER_ELEMENT_CONTEXT, GetPeakMeterElementContext) + +// +// Define DSP circuit's peakmeter element context. +// +typedef struct _DSP_PEAKMETER_ELEMENT_CONTEXT +{ + PVOID peakMeter; +} DSP_PEAKMETER_ELEMENT_CONTEXT, *PDSP_PEAKMETER_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PEAKMETER_ELEMENT_CONTEXT, GetDspPeakMeterElementContext) + +// +// Define stream engine context. +// +typedef struct _STREAMENGINE_CONTEXT { + PVOID StreamEngine; +} STREAMENGINE_CONTEXT, * PSTREAMENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAMENGINE_CONTEXT, GetStreamEngineContext) + +#define PEAKMETER_STEPPING_DELTA 0x1000 +#define PEAKMETER_MAXIMUM LONG_MAX +#define PEAKMETER_MINIMUM LONG_MIN + +///////////////////////////////////////////////////////////// +// Codec driver defintions +// + +typedef enum _CODEC_PIN_TYPE { + CodecPinTypeHost, + CodecPinTypeOffload, + CodecPinTypeLoopback, + CodecPinTypeKeyword, + CodecPinTypeDevice +} CODEC_PIN_TYPE, * PCODEC_PIN_TYPE; + +typedef struct _CODEC_PIN_CONTEXT { + CODEC_PIN_TYPE CodecPinType; +} CODEC_PIN_CONTEXT, * PCODEC_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_PIN_CONTEXT, GetCodecPinContext) + +/////////////////////////////////////////////////////////// +// Dsp driver definitions +// + +typedef enum { + CaptureHostPin = 0, + CaptureBridgePin = 1, + CaptureKWSPin = 2, + CapturePinCount = 3 +} CAPTURE_PIN_TYPE; + +typedef enum { + RenderHostPin = 0, + RenderOffloadPin = 1, + RenderLoopbackPin = 2, + RenderBridgePin = 3, + RenderPinCount = 4 +} RENDER_PIN_TYPE; + +typedef struct _DSP_PIN_CONTEXT { + ACXTARGETCIRCUIT TargetCircuit; + ULONG TargetPinId; + RENDER_PIN_TYPE RenderPinType; + CAPTURE_PIN_TYPE CapturePinType; + + // The stream bridge below will only be valid for the Capture circuit Bridge Pin + + // Host stream bridge will be used to ensure host stream creations are passed + // to the downlevel circuits. Since the HostStreamBridge won't have InModes set, + // the ACX framework will not add streams automatically. We will add streams for + // non KWS pin. + ACXSTREAMBRIDGE HostStreamBridge; +} DSP_PIN_CONTEXT, * PDSP_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PIN_CONTEXT, GetDspPinContext) + +///////////////////////////////////////////////////////////// +// Multicircuit Dsp driver definitions +// + +// +// Circuit context for multi circuit dsp circuits. +// +typedef struct _DSP_CIRCUIT_CONTEXT +{ + ACXAUDIOENGINE AudioEngineElement; + ACXPEAKMETER PeakMeterElement; + PVOID peakMeter; + ACXKEYWORDSPOTTER KeywordSpotter; + BOOLEAN IsRenderCircuit; +} DSP_CIRCUIT_CONTEXT, *PDSP_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_CIRCUIT_CONTEXT, GetDspCircuitContext) + +typedef struct _DSP_ENGINE_CONTEXT +{ + ACXDATAFORMAT MixFormat; + BOOLEAN GFxEnabled; +} DSP_ENGINE_CONTEXT, *PDSP_ENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_ENGINE_CONTEXT, GetDspEngineContext) + +typedef struct _DSP_STREAMAUDIOENGINE_CONTEXT +{ + BOOLEAN LFxEnabled; +} DSP_STREAMAUDIOENGINE_CONTEXT, *PDSP_STREAMAUDIOENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_STREAMAUDIOENGINE_CONTEXT, GetDspStreamAudioEngineContext) + +///////////////////////////////////////////////////////// +// +// Codec Render (speaker) definitions +// + +// +// Define render circuit context. +// +typedef struct _CODEC_RENDER_CIRCUIT_CONTEXT { + ACXVOLUME VolumeElement; + ACXMUTE MuteElement; + ACXPEAKMETER PeakMeterElement; + ACXAUDIOENGINE AudioEngineElement; +} CODEC_RENDER_CIRCUIT_CONTEXT, * PCODEC_RENDER_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_RENDER_CIRCUIT_CONTEXT, GetRenderCircuitContext) + +typedef enum { + CodecRenderHostPin = 0, + CodecRenderBridgePin = 1, + CodecRenderPinCount = 2 +} CODEC_RENDER_PINS; + +typedef enum { + RenderVolumeIndex = 0, + RenderMuteIndex = 1, + RenderElementCount = 2 +} CODEC_RENDER_ELEMENTS; + +// Render callbacks. + +EVT_ACX_CIRCUIT_CREATE_STREAM CodecR_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CodecR_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CodecR_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET CodecR_EvtStreamSetRenderPacket; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CodecR_EvtStreamGetLoopbackPacket; +EVT_ACX_PIN_SET_DATAFORMAT CodecR_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecR_EvtPinContextCleanup; +EVT_ACX_MUTE_ASSIGN_STATE CodecR_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE CodecR_EvtMuteRetrieveState; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecR_EvtVolumeAssignLevel; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecR_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL CodecR_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL CodecR_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS CodecR_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE CodecR_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE CodecR_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT CodecR_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT CodecR_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE CodecR_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE CodecR_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION CodecR_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION CodecR_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION CodecR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION CodecR_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION CodecR_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +PAGED_CODE_SEG +NTSTATUS +CodecR_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Codec Capture (microphone) definitions +// + +// +// Define capture circuit context. +// +typedef struct _CODEC_CAPTURE_CIRCUIT_CONTEXT { + ACXVOLUME BoostElement; + ACXVOLUME VolumeElement; + ACXKEYWORDSPOTTER KeywordSpotter; +} CODEC_CAPTURE_CIRCUIT_CONTEXT, * PCODEC_CAPTURE_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_CAPTURE_CIRCUIT_CONTEXT, GetCaptureCircuitContext) + +typedef enum { + CodecCaptureHostPin = 0, + CodecCaptureBridgePin = 1, + CodecCapturePinCount = 2 +} CODEC_CAPTURE_PINS; + +typedef enum { + CaptureVolumeIndex = 0, + CaptureElementCount = 1 +} CAPTURE_ELEMENTS; + +// Capture callbacks. + +EVT_ACX_CIRCUIT_CREATE_STREAM CodecC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CodecC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CodecC_EvtCircuitPowerDown; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecC_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecC_EvtVolumeRetrieveLevelCallback; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecC_EvtBoostAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecC_EvtBoostRetrieveLevelCallback; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CodecC_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CodecC_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME CodecC_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecC_EvtPinContextCleanup; +EVT_ACX_KEYWORDSPOTTER_RETRIEVE_ARM CodecC_EvtAcxKeywordSpotterRetrieveArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_ARM CodecC_EvtAcxKeywordSpotterAssignArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_PATTERNS CodecC_EvtAcxKeywordSpotterAssignPatterns; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_RESET CodecC_EvtAcxKeywordSpotterAssignReset; + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// MicArray definitions +// + +// +// Define MicArray circuit context. +// +typedef struct _MICARRAY_CIRCUIT_CONTEXT { + ACXMUTE MuteElement; + ACXVOLUME VolumeElement; + ACXPEAKMETER PeakMeterElement; + ACXKEYWORDSPOTTER KeywordSpotter; +} MICARRAY_CIRCUIT_CONTEXT, * PMICARRAY_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MICARRAY_CIRCUIT_CONTEXT, GetMicArrayCircuitContext) + +typedef enum { + MicArrayVolumeIndex = 0, + MicArrayMuteIndex = 1, + MicArrayPeakmeterIndex = 2, + MicArrayKWSIndex = 3, + MicArrayElementCount = 4 +} MICARRAY_ELEMENTS; + +// MicArray callbacks. + +EVT_ACX_MUTE_ASSIGN_STATE MicArray_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE MicArray_EvtMuteRetrieveState; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL MicArray_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_CIRCUIT_CREATE_STREAM MicArray_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP MicArray_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN MicArray_EvtCircuitPowerDown; +EVT_ACX_VOLUME_ASSIGN_LEVEL MicArray_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL MicArray_EvtVolumeRetrieveLevelCallback; +EVT_ACX_STREAM_GET_CAPTURE_PACKET MicArray_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT MicArray_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME MicArray_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP MicArray_EvtPinContextCleanup; +EVT_ACX_KEYWORDSPOTTER_RETRIEVE_ARM MicArray_EvtAcxKeywordSpotterRetrieveArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_ARM MicArray_EvtAcxKeywordSpotterAssignArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_PATTERNS MicArray_EvtAcxKeywordSpotterAssignPatterns; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_RESET MicArray_EvtAcxKeywordSpotterAssignReset; +EVT_ACX_PIN_CONNECTED MicArray_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED MicArray_EvtPinDisconnected; +EVT_WDF_DEVICE_CONTEXT_CLEANUP MicArray_EvtDeviceContextCleanup; +EVT_ACX_OBJECT_PROCESS_REQUEST MicArray_EvtPinProposeDataFormat2Callback; +EVT_ACX_OBJECT_PREPROCESS_REQUEST MicArray_EvtAudioCpuResourcesCallback; + +PAGED_CODE_SEG +NTSTATUS +MicArray_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +PAGED_CODE_SEG +NTSTATUS +MicArray_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +///////////////////////////////////////////////////////// +// +// Microphone (external: headphone) definitions +// + +// +// Define MicrophoneHp circuit context. +// +typedef struct _MICROPHONEHP_CIRCUIT_CONTEXT { + ACXMUTE MuteElement; + ACXVOLUME VolumeElement; + ACXPEAKMETER PeakMeterElement; +} MICROPHONEHP_CIRCUIT_CONTEXT, * PMICROPHONEHP_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MICROPHONEHP_CIRCUIT_CONTEXT, GetMicrophoneHpCircuitContext) + +typedef enum { + MicrophoneHpVolumeIndex = 0, + MicrophoneHpMuteIndex = 1, + MicrophoneHpPeakmeterIndex = 2, + MicrophoneHpElementCount = 3 +} MICROPHONEHP_ELEMENTS; + +// MicrophoneHp callbacks. + +EVT_ACX_MUTE_ASSIGN_STATE MicrophoneHp_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE MicrophoneHp_EvtMuteRetrieveState; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL MicrophoneHp_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_CIRCUIT_CREATE_STREAM MicrophoneHp_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP MicrophoneHp_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN MicrophoneHp_EvtCircuitPowerDown; +EVT_ACX_VOLUME_ASSIGN_LEVEL MicrophoneHp_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL MicrophoneHp_EvtVolumeRetrieveLevelCallback; +EVT_ACX_STREAM_GET_CAPTURE_PACKET MicrophoneHp_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT MicrophoneHp_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME MicrophoneHp_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP MicrophoneHp_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED MicrophoneHp_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED MicrophoneHp_EvtPinDisconnected; +EVT_ACX_OBJECT_PREPROCESS_REQUEST MicrophoneHp_EvtAudioCpuResourcesCallback; + +PAGED_CODE_SEG +NTSTATUS +MicrophoneHp_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +PAGED_CODE_SEG +NTSTATUS +MicrophoneHp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +///////////////////////////////////////////////////////// +// +// Speaker definitions +// + +// +// Define circuit context for Speaker and SpeakerHp. +// +typedef struct _DSP_RENDER_CIRCUIT_CONTEXT { + ACXPEAKMETER PeakMeterElement; + ACXAUDIOENGINE AudioEngineElement; + PVOID PeakMeter; +} DSP_RENDER_CIRCUIT_CONTEXT, * PDSP_RENDER_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_RENDER_CIRCUIT_CONTEXT, GetSpeakerCircuitContext) + +// Speaker callbacks. + +EVT_ACX_CIRCUIT_CREATE_STREAM Speaker_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP Speaker_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN Speaker_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET Speaker_EvtStreamSetRenderPacket; +EVT_ACX_STREAM_GET_CAPTURE_PACKET Speaker_EvtStreamGetLoopbackPacket; +EVT_ACX_PIN_SET_DATAFORMAT Speaker_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Speaker_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED Speaker_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED Speaker_EvtPinDisconnected; + +//Render Audio Engine callbacks. + +EVT_ACX_MUTE_ASSIGN_STATE Speaker_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE Speaker_EvtMuteRetrieveState; +EVT_ACX_VOLUME_RETRIEVE_LEVEL Speaker_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL Speaker_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL Speaker_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS Speaker_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE Speaker_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE Speaker_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT Speaker_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT Speaker_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE Speaker_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE Speaker_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION Speaker_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION Speaker_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION Speaker_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION Speaker_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION Speaker_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +PAGED_CODE_SEG +NTSTATUS +Speaker_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +Speaker_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName, + _In_ BOOLEAN IsHeadphones, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// HDMI definitions +// + +// +// Define HDMI circuit context. +// +typedef struct _DSP_HDMI_CIRCUIT_CONTEXT { + ACXVOLUME VolumeElement; + ACXMUTE MuteElement; + ACXPEAKMETER PeakmeterElement; +} DSP_HDMI_CIRCUIT_CONTEXT, * PDSP_HDMI_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_HDMI_CIRCUIT_CONTEXT, GetHDMICircuitContext) + +typedef enum { + HDMIVolumeIndex = 0, + HDMIMuteIndex = 1, + HDMIPeakmeterIndex = 2, + HDMIElementCount = 3 +} HDMI_ELEMENTS; + +typedef enum { + HDMIHostPin = 0, + HDMILoopbackPin = 1, + HDMIBridgePin = 2, + HDMIPinCount = 3 +} HDMI_PIN_TYPE; + +typedef struct _HDMI_PIN_CONTEXT { + ACXTARGETCIRCUIT TargetCircuit; + ULONG TargetPinId; + HDMI_PIN_TYPE PinType; + CAPTURE_PIN_TYPE CapturePinType; +} HDMI_PIN_CONTEXT, * PHDMI_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HDMI_PIN_CONTEXT, GetHDMIPinContext) + +typedef struct _HDMI_STREAM_CONTEXT { + HDMI_PIN_TYPE PinType; + CAPTURE_PIN_TYPE CapturePinType; +} HDMI_STREAM_CONTEXT, * PHDMI_STREAM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HDMI_STREAM_CONTEXT, GetHDMIStreamContext) + +// HDMI callbacks. +EVT_ACX_CIRCUIT_CREATE_STREAM HDMI_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP HDMI_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN HDMI_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET HDMI_EvtStreamSetRenderPacket; +EVT_ACX_STREAM_GET_CAPTURE_PACKET HDMI_EvtStreamGetLoopbackPacket; +EVT_ACX_PIN_SET_DATAFORMAT HDMI_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP HDMI_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED HDMI_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED HDMI_EvtPinDisconnected; +EVT_WDF_DEVICE_CONTEXT_CLEANUP HDMI_EvtDeviceContextCleanup; +EVT_ACX_MUTE_ASSIGN_STATE HDMI_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE HDMI_EvtMuteRetrieveState; +EVT_ACX_VOLUME_ASSIGN_LEVEL HDMI_EvtRampedVolumeAssignLevel; +EVT_ACX_VOLUME_RETRIEVE_LEVEL HDMI_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL HDMI_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_OBJECT_PREPROCESS_REQUEST HDMI_EvtAudioCpuResourcesCallback; + +PAGED_CODE_SEG +NTSTATUS +HDMI_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +HDMI_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Multi circuit codec Render (speaker) definitions +// + +// Uses the same circuit context, render pin, and render element definitions as Codec Render. + +// Render callbacks. +EVT_ACX_CIRCUIT_CREATE_STREAM RenderMC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP RenderMC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN RenderMC_EvtCircuitPowerDown; +EVT_ACX_PIN_SET_DATAFORMAT RenderMC_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMC_EvtPinContextCleanup; +EVT_ACX_MUTE_ASSIGN_STATE RenderMC_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE RenderMC_EvtMuteRetrieveState; +EVT_ACX_VOLUME_RETRIEVE_LEVEL RenderMC_EvtVolumeRetrieveLevel; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL RenderMC_EvtRampedVolumeAssignLevel; + +PAGED_CODE_SEG +NTSTATUS +RenderMC_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Multi circuit codec Capture (microphone) definitions +// + +// Uses the same circuit context, render pin, and render element definitions as Codec Capture. + +// Capture callbacks. +EVT_ACX_CIRCUIT_CREATE_STREAM CaptureMC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CaptureMC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CaptureMC_EvtCircuitPowerDown; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CaptureMC_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CaptureMC_EvtAcxPinSetDataFormat; +EVT_ACX_PIN_RETRIEVE_NAME CaptureMC_EvtAcxPinRetrieveName; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CaptureMC_EvtPinContextCleanup; + +PAGED_CODE_SEG +NTSTATUS +CaptureMC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri, + _Out_ ACXCIRCUIT * Circuit +); + +///////////////////////////////////////////////////////// +// +// Multi circuit dsp Render (speaker) definitions +// + +// Uses the same circuit context, render pin, and render element definitions as Codec Render. + +// Render callbacks. +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE RenderMCDsp_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE RenderMCDsp_EvtCircuitCompositeInitialize; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMCDsp_EvtCircuitContextCleanup; +EVT_WDF_DEVICE_PREPARE_HARDWARE RenderMCDsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE RenderMCDsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT RenderMCDsp_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMCDsp_EvtDeviceContextCleanup; +EVT_ACX_CIRCUIT_CREATE_STREAM RenderMCDsp_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP RenderMCDsp_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN RenderMCDsp_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET RenderMCDsp_EvtStreamSetRenderPacket; +EVT_ACX_PIN_SET_DATAFORMAT RenderMCDsp_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP RenderMCDsp_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED RenderMCDsp_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED RenderMCDsp_EvtPinDisconnected; + +// Render Audio Engine +EVT_ACX_MUTE_ASSIGN_STATE DspR_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE DspR_EvtMuteRetrieveState; +EVT_ACX_VOLUME_RETRIEVE_LEVEL DspR_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL DspR_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL DspR_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS DspR_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE DspR_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE DspR_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT DspR_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT DspR_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE DspR_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE DspR_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION DspR_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION DspR_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION DspR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION DspR_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION DspR_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +PAGED_CODE_SEG +NTSTATUS +RenderMCDsp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS CreateRenderCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateRenderMCDspPin( + _In_ ACX_PIN_TYPE PinType, + _In_ ACXCIRCUIT Circuit, + _In_ ACX_PIN_COMMUNICATION Communication, + _In_ const GUID* Category, + _In_ ACX_PIN_CALLBACKS* PinCallbacks, + _In_ bool Mic, + _Out_ ACXPIN* Pin +); + +PAGED_CODE_SEG +NTSTATUS CreateAudioEngine( + _In_ ACXCIRCUIT Circuit, + _In_reads_(PinCount) ACXPIN* Pins, + _In_ ULONG PinCount, + _Out_ ACXAUDIOENGINE* AudioEngineElement +); + +///////////////////////////////////////////////////////// +// +// Multi circuit dsp Capture (microphone) definitions +// + +// Uses the same circuit context, capture pin and capture element definitions as Codec Capture. + +// Capture callbacks. +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE CaptureMCDsp_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE CaptureMCDsp_EvtCircuitCompositeInitialize; +EVT_WDF_DEVICE_PREPARE_HARDWARE CaptureMCDsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE CaptureMCDsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT CaptureMCDsp_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CaptureMCDsp_EvtDeviceContextCleanup; +EVT_ACX_CIRCUIT_CREATE_STREAM CaptureMCDsp_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CaptureMCDsp_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CaptureMCDsp_EvtCircuitPowerDown; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CaptureMCDsp_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CaptureMCDsp_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CaptureMCDsp_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED CaptureMCDsp_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED CaptureMCDsp_EvtPinDisconnected; + +PAGED_CODE_SEG +NTSTATUS +CaptureMCDsp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS CreateCaptureCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateCaptureMCDspPin( + _In_ ACX_PIN_TYPE PinType, + _In_ ACXCIRCUIT Circuit, + _In_ ACX_PIN_COMMUNICATION Communication, + _In_ const GUID* Category, + _In_ ACX_PIN_CALLBACKS* PinCallbacks, + _In_ bool Mic, + _Out_ ACXPIN* Pin +); + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + + + +#endif // _PRIVATE_H_ diff --git a/audio/Acx/Samples/Common/RenderCircuit.cpp b/audio/Acx/Samples/Common/RenderCircuit.cpp new file mode 100644 index 000000000..2f5abd130 --- /dev/null +++ b/audio/Acx/Samples/Common/RenderCircuit.cpp @@ -0,0 +1,807 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + RenderCircuit.cpp + +Abstract: + + Render Circuit. This file contains routines to create and handle + render circuit with no offload. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include +#include +#include +#include "AudioFormats.h" +#include "streamengine.h" +#include "cpp_utils.h" +#include "circuithelper.h" + +#ifndef __INTELLISENSE__ +#include "renderCircuit.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtAcxPinSetDataFormat( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat +) +/*++ + +Routine Description: + + This ACX pin callback sets the device/mixed format. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + PAGED_CODE(); + + // NOTE: update device/mixed format here. + + return STATUS_NOT_SUPPORTED; +} + +/////////////////////////////////////////////////////////// +// +// For more information on mute element see: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/ksnodetype-mute +// +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtMuteAssignState( + _In_ ACXMUTE Mute, + _In_ ULONG Channel, + _In_ ULONG State +) +{ + PMUTE_ELEMENT_CONTEXT muteCtx; + ULONG i; + + PAGED_CODE(); + + muteCtx = GetMuteElementContext(Mute); + ASSERT(muteCtx); + + // + // Use first channel for all channels setting. + // + if (Channel != ALL_CHANNELS_ID) + { + muteCtx->MuteState[Channel] = State; + } + else + { + for (i = 0; i < MAX_CHANNELS; ++i) + { + muteCtx->MuteState[i] = State; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtMuteRetrieveState( + _In_ ACXMUTE Mute, + _In_ ULONG Channel, + _Out_ ULONG * State +) +{ + PMUTE_ELEMENT_CONTEXT muteCtx; + + PAGED_CODE(); + + muteCtx = GetMuteElementContext(Mute); + ASSERT(muteCtx); + + // + // Use first channel for all channels setting. + // + if (Channel != ALL_CHANNELS_ID) + { + *State = muteCtx->MuteState[Channel]; + } + else + { + *State = muteCtx->MuteState[0]; + } + + return STATUS_SUCCESS; +} + +/////////////////////////////////////////////////////////// +// +// For more information on volume element see: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/ksnodetype-volume +// +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtRampedVolumeAssignLevel( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _In_ LONG VolumeLevel, + _In_ ACX_VOLUME_CURVE_TYPE CurveType, + _In_ ULONGLONG CurveDuration +) +{ + PVOLUME_ELEMENT_CONTEXT volumeCtx; + ULONG i; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(CurveType); + UNREFERENCED_PARAMETER(CurveDuration); + + volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + volumeCtx->VolumeLevel[Channel] = VolumeLevel; + } + else + { + for (i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = VolumeLevel; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +NTAPI +CodecR_EvtVolumeRetrieveLevel( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _Out_ LONG * VolumeLevel +) +{ + PVOLUME_ELEMENT_CONTEXT volumeCtx; + + PAGED_CODE(); + + volumeCtx = GetVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + *VolumeLevel = volumeCtx->VolumeLevel[Channel]; + } + else + { + *VolumeLevel = volumeCtx->VolumeLevel[0]; + } + + return STATUS_SUCCESS; +} + +VOID +CodecR_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin +) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + nullptr + +--*/ +{ + + UNREFERENCED_PARAMETER(WdfPin); +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName +) +/*++ + +Routine Description: + + Creates the static render circuit (pictured below) and + adds it to the device context. This is called when a + new device is detected and the AddDevice call is made + by the pnp manager. + + *************************************************************************** + * Render Circuit * + * * + * +--------------------------------------------+ * + * | | * + * | +-------------+ +-------------+ | * + * Host ------>| | Volume Node | | Mute Node | |---> Bridge * + * Pin | +-------------+ +-------------+ | Pin * + * | | * + * +--------------------------------------------+ * + * * + *************************************************************************** + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + PRENDER_DEVICE_CONTEXT renderDevCtx; + ACXCIRCUIT renderCircuit = nullptr; + WDF_OBJECT_ATTRIBUTES attributes; + + PAGED_CODE(); + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != nullptr); + + // + // Alloc audio context to current device. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RENDER_DEVICE_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&renderDevCtx)); + ASSERT(renderDevCtx); + + // + // Create a render circuit associated with this child device. + // + RETURN_NTSTATUS_IF_FAILED(CodecR_CreateRenderCircuit(Device, ComponentGuid, CircuitName, &renderCircuit)); + + devCtx->Render = renderCircuit; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Render_AllocateSupportedFormats( + _In_ WDFDEVICE Device, + _In_reads_bytes_(CodecRenderPinCount) ACXPIN Pin[], + _In_ ACXCIRCUIT Circuit, + _In_ size_t CodecRenderPinCount +) +{ + UNREFERENCED_PARAMETER(CodecRenderPinCount); + + NTSTATUS status = STATUS_SUCCESS; + ACXDATAFORMAT formatPcm44100c2; + ACXDATAFORMAT formatPcm48000c2; + ACXDATAFORMATLIST formatList; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c2, Circuit, Device, &formatPcm44100c2)); + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c2, Circuit, Device, &formatPcm48000c2)); + + /////////////////////////////////////////////////////////// + // + // Define supported formats for the host pin. + // + + // + // The raw processing mode list is associated with each single circuit + // by ACX. The driver uses this DDI to retrieve the built-in raw + // data-format list. + // + RETURN_NTSTATUS_IF_TRUE(CodecRenderHostPin >= CodecRenderPinCount, STATUS_INVALID_PARAMETER); + formatList = AcxPinGetRawDataFormatList(Pin[CodecRenderHostPin]); + RETURN_NTSTATUS_IF_TRUE(formatList == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + // + // The driver uses this DDI to add data formats to the raw + // processing mode list associated with the current circuit. + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c2)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _Out_ ACXCIRCUIT* Circuit +) +/*++ + +Routine Description: + + This routine builds the CODEC render circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + CODEC_RENDER_CIRCUIT_CONTEXT* circuitCtx; + ACXPIN pin[CodecRenderPinCount]; + + PAGED_CODE(); + + // + // Init output value. + // + *Circuit = nullptr; + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + { + PACXCIRCUIT_INIT circuitInit = nullptr; + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + + // + // The driver uses this DDI to allocate an ACXCIRCUIT_INIT + // structure. This opaque structure is used when creating + // a standalone audio circuit representing an audio device. + // + circuitInit = AcxCircuitInitAllocate(Device); + + // + // The driver uses this DDI to free the allocated + // ACXCIRCUIT_INIT structure when an error is detected. + // Normally the structures is deleted/cleared by ACX when + // an ACX circuit is created successfully. + // + auto circuitInitScope = scope_exit([&circuitInit]() { + if (circuitInit) { + AcxCircuitInitFree(circuitInit); + } + }); + + // + // The driver uses this DDI to specify the Component ID + // of the ACX circuit. This ID is a guid that uniquely + // identifies the circuit instance (vendor specific). + // + AcxCircuitInitSetComponentId(circuitInit, ComponentGuid); + + // + // The driver uses this DDI to specify the circuit name. + // For standalone circuits, this is the audio device name + // which is used by clients to open handles to the audio devices. + // + (VOID)AcxCircuitInitAssignName(circuitInit, CircuitName); + + // + // The driver uses this DDI to specify the circuit type. The + // circuit type can be AcxCircuitTypeRender, AcxCircuitTypeCapture, + // AcxCircuitTypeOther, or AcxCircuitTypeMaximum (for validation). + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeRender); + + // + // The driver uses this DDI to assign its (if any) power callbacks. + // + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = CodecR_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = CodecR_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + + // + // The driver uses this DDI to register for a stream-create callback. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback(circuitInit, CodecR_EvtCircuitCreateStream)); + + // + // The driver uses this DDI to create a new ACX circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + + circuitInitScope.release(); + + circuitCtx = GetRenderCircuitContext(circuit); + ASSERT(circuitCtx); + } + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Create mute and volume elements. + // + { + ACXELEMENT elements[RenderElementCount] = { 0 }; + + // + // The driver uses this DDI to assign its volume element callbacks. + // + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxRampedVolumeAssignLevel = CodecR_EvtRampedVolumeAssignLevel; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = CodecR_EvtVolumeRetrieveLevel; + + // + // Create Volume element + // + ACX_VOLUME_CONFIG volumeCfg; + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Name = &KSAUDFNAME_VOLUME_CONTROL; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(circuit, &attributes, &volumeCfg, (ACXVOLUME*)&elements[RenderVolumeIndex])); + + // + // The driver uses this DDI to assign its mute element callbacks. + // + ACX_MUTE_CALLBACKS muteCallbacks; + ACX_MUTE_CALLBACKS_INIT(&muteCallbacks); + muteCallbacks.EvtAcxMuteAssignState = CodecR_EvtMuteAssignState; + muteCallbacks.EvtAcxMuteRetrieveState = CodecR_EvtMuteRetrieveState; + + // + // Create Mute element + // + ACX_MUTE_CONFIG muteCfg; + ACX_MUTE_CONFIG_INIT(&muteCfg); + muteCfg.ChannelsCount = MAX_CHANNELS; + muteCfg.Name = &KSAUDFNAME_WAVE_MUTE; + muteCfg.Callbacks = &muteCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, MUTE_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxMuteCreate(circuit, &attributes, &muteCfg, (ACXMUTE*)&elements[RenderMuteIndex])); + + // + // Saving the volume and mute elements in the circuit context. + // + circuitCtx->VolumeElement = (ACXVOLUME)elements[RenderVolumeIndex]; + circuitCtx->MuteElement = (ACXMUTE)elements[RenderMuteIndex]; + + // + // The driver uses this DDI post circuit creation to add ACXELEMENTs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + } + + /////////////////////////////////////////////////////////// + // + // Create the pins for the circuit. + // + { + ACX_PIN_CONFIG pinCfg; + CODEC_PIN_CONTEXT* pinCtx; + ACX_PIN_CALLBACKS pinCallbacks; + + /////////////////////////////////////////////////////////// + // + // Create Render Pin. + // + + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = CodecR_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationSink; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin[CodecRenderHostPin])); + + ASSERT(pin[CodecRenderHostPin] != nullptr); + pinCtx = GetCodecPinContext(pin[CodecRenderHostPin]); + ASSERT(pinCtx); + pinCtx->CodecPinType = CodecPinTypeHost; + + /////////////////////////////////////////////////////////// + // + // Create Device Bridge Pin. + // + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSNODETYPE_SPEAKER; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + // + // The driver uses this DDI to create one or more pins on the circuits. + // + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin[CodecRenderBridgePin])); + + ASSERT(pin[CodecRenderBridgePin] != nullptr); + pinCtx = GetCodecPinContext(pin[CodecRenderBridgePin]); + ASSERT(pinCtx); + pinCtx->CodecPinType = CodecPinTypeDevice; + } + + /////////////////////////////////////////////////////////// + // + // Add audio jack to bridge pin. + // For more information on audio jack see: https://docs.microsoft.com/en-us/windows/win32/api/devicetopology/ns-devicetopology-ksjack_description + // + { + ACX_JACK_CONFIG jackCfg; + ACXJACK jack; + PJACK_CONTEXT jackCtx; + + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + jackCfg.Description.Color = RGB(0, 0, 0); + jackCfg.Description.ConnectionType = AcxConnTypeAtapiInternal; + jackCfg.Description.GeoLocation = AcxGeoLocFront; + jackCfg.Description.GenLocation = AcxGenLocPrimaryBox; + jackCfg.Description.PortConnection = AcxPortConnIntegratedDevice; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, JACK_CONTEXT); + attributes.ParentObject = pin[CodecRenderBridgePin]; + + RETURN_NTSTATUS_IF_FAILED(AcxJackCreate(pin[CodecRenderBridgePin], &attributes, &jackCfg, &jack)); + + ASSERT(jack != nullptr); + + jackCtx = GetJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddJacks(pin[CodecRenderBridgePin], &jack, 1)); + } + + RETURN_NTSTATUS_IF_FAILED(Render_AllocateSupportedFormats(Device, pin, circuit, CodecRenderPinCount)); + + /////////////////////////////////////////////////////////// + // + // The driver uses this DDI post circuit creation to add ACXPINs. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, pin, CodecRenderPinCount)); + + // + // Set output value. + // + *Circuit = circuit; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +_Use_decl_annotations_ +NTSTATUS +CodecR_EvtCircuitPowerUp( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +CodecR_EvtCircuitPowerDown( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID* SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine creates a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PRENDER_DEVICE_CONTEXT devCtx; + WDF_OBJECT_ATTRIBUTES attributes; + ACXSTREAM stream; + STREAMENGINE_CONTEXT * streamCtx; + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_RT_STREAM_CALLBACKS rtCallbacks; + CRenderStreamEngine* renderStreamEngine = nullptr; + CODEC_PIN_TYPE codecPinType; + PCODEC_PIN_CONTEXT pinCtx; + ACX_PIN_TYPE pinType; + CODEC_RENDER_CIRCUIT_CONTEXT* circuitCtx; + + auto streamEngineScope = scope_exit([&renderStreamEngine]() { + + delete renderStreamEngine; + + }); + + PAGED_CODE(); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + ASSERT(Circuit != nullptr); + circuitCtx = GetRenderCircuitContext(Circuit); + ASSERT(circuitCtx); + + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != nullptr); + UNREFERENCED_PARAMETER(devCtx); + + pinCtx = GetCodecPinContext(Pin); + codecPinType = pinCtx->CodecPinType; + + pinType = AcxPinGetType(Pin); + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = EvtStreamPause; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Init RT streaming callbacks. + // + ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks); + rtCallbacks.EvtAcxStreamGetHwLatency = EvtStreamGetHwLatency; + rtCallbacks.EvtAcxStreamAllocateRtPackets = EvtStreamAllocateRtPackets; + rtCallbacks.EvtAcxStreamFreeRtPackets = EvtStreamFreeRtPackets; + rtCallbacks.EvtAcxStreamSetRenderPacket = CodecR_EvtStreamSetRenderPacket; + rtCallbacks.EvtAcxStreamGetCurrentPacket = EvtStreamGetCurrentPacket; + rtCallbacks.EvtAcxStreamGetPresentationPosition = EvtStreamGetPresentationPosition; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks)); + + // + // Buffer notifications are supported. + // + AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, STREAMENGINE_CONTEXT); + attributes.EvtDestroyCallback = EvtStreamDestroy; + RETURN_NTSTATUS_IF_FAILED(AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + // + // Create the virtual streaming engine which will control + // streaming logic for the render circuit. + // + renderStreamEngine = new (POOL_FLAG_NON_PAGED, DeviceDriverTag) CRenderStreamEngine(stream, StreamFormat, FALSE, NULL); + RETURN_NTSTATUS_IF_TRUE(renderStreamEngine == nullptr, STATUS_INSUFFICIENT_RESOURCES); + + streamCtx = GetStreamEngineContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)renderStreamEngine; + + renderStreamEngine = nullptr; + + // + // Done. + // + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtStreamSetRenderPacket( + _In_ ACXSTREAM Stream, + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength +) +{ + PSTREAMENGINE_CONTEXT ctx; + CRenderStreamEngine* streamEngine = nullptr; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast(ctx->StreamEngine); + + return streamEngine->SetRenderPacket(Packet, Flags, EosPacketLength); +} + diff --git a/audio/Acx/Samples/Common/SamplesCommon.vcxproj b/audio/Acx/Samples/Common/SamplesCommon.vcxproj new file mode 100644 index 000000000..0932d59a1 --- /dev/null +++ b/audio/Acx/Samples/Common/SamplesCommon.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {6A946D59-6690-4ED0-A77D-7D4C3D4B3241} + {497e31cb-056b-4f31-abb8-447fd55ee5a5} + v4.5 + 12.0 + Debug + SamplesCommon + $(LatestTargetPlatformVersion) + + + + Windows10 + true + WindowsKernelModeDriver10.0 + StaticLibrary + KMDF + Windows Driver + 1 + 31 + + + Windows10 + false + WindowsKernelModeDriver10.0 + StaticLibrary + KMDF + Windows Driver + 1 + 31 + + + Windows10 + true + WindowsKernelModeDriver10.0 + StaticLibrary + KMDF + Windows Driver + 1 + 31 + + + Windows10 + false + WindowsKernelModeDriver10.0 + StaticLibrary + KMDF + Windows Driver + 1 + 31 + + + + + + + + + + + DbgengKernelDebugger + $(IntDir) + + + DbgengKernelDebugger + $(IntDir) + + + DbgengKernelDebugger + $(IntDir) + + + DbgengKernelDebugger + $(IntDir) + + + + true + true + trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + + + true + true + trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + + + true + true + trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + + + true + true + trace_macros.h + true + $(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\1.1;..\inc;..\shared;%(AdditionalIncludeDirectories) + ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=1;KMDF_VERSION_MAJOR=1;KMDF_VERSION_MINOR=31;%(PreprocessorDefinitions) + + + sha256 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/Acx/Samples/Common/SaveData.cpp b/audio/Acx/Samples/Common/SaveData.cpp new file mode 100644 index 000000000..72e98850d --- /dev/null +++ b/audio/Acx/Samples/Common/SaveData.cpp @@ -0,0 +1,1103 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SaveData.cpp + +Abstract: + + Implementation of data saving class for ACX driver samples. + + To save the playback data to disk, this class maintains a circular data + buffer, associated frame structures and worker items to save frames to + disk. + Each frame structure represents a portion of buffer. When that portion + of frame is full, a workitem is scheduled to save it to disk. + + + +--*/ +#pragma warning (disable : 4127) +#pragma warning (disable : 26165) + + +#include "private.h" +#include +#include +#include +#include +#include "savedata.h" +#include // This is for using RtlStringCbPrintf + +#define SAVEDATA_POOLTAG 'TDVS' +#define SAVEDATA_POOLTAG1 '1DVS' +#define SAVEDATA_POOLTAG2 '2DVS' +#define SAVEDATA_POOLTAG3 '3DVS' +#define SAVEDATA_POOLTAG4 '4DVS' +#define SAVEDATA_POOLTAG5 '5DVS' +#define SAVEDATA_POOLTAG6 '6DVS' +#define SAVEDATA_POOLTAG7 '7DVS' + +//============================================================================= +// Defines +//============================================================================= +#define RIFF_TAG 0x46464952; +#define WAVE_TAG 0x45564157; +#define FMT__TAG 0x20746D66; +#define DATA_TAG 0x61746164; + +#define DEFAULT_FRAME_COUNT 4 +#define DEFAULT_FRAME_SIZE PAGE_SIZE * 4 +#define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT + +#define DEFAULT_FILE_FOLDER1 L"\\DriverData\\Audio_Samples" +#define DEFAULT_FILE_FOLDER2 L"\\DriverData\\Audio_Samples\\AudioCodec" +#define DEFAULT_FILE_NAME L"\\DriverData\\Audio_Samples\\AudioCodec\\STREAM" +#define OFFLOAD_FILE_NAME L"OFFLOAD" +#define HOST_FILE_NAME L"HOST" + +#define MAX_WORKER_ITEM_COUNT 15 + + +PSAVEWORKER_PARAM CSaveData::m_pWorkItems = NULL; +PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL; + +//============================================================================= +// Statics +//============================================================================= +ULONG CSaveData::m_ulStreamId = 0; +ULONG CSaveData::m_ulOffloadStreamId = 0; + +//============================================================================= +// CSaveData +//============================================================================= + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::CSaveData() +: m_pDataBuffer(NULL), + m_FileHandle(NULL), + m_ulFrameCount(DEFAULT_FRAME_COUNT), + m_ulBufferSize(DEFAULT_BUFFER_SIZE), + m_ulFrameSize(DEFAULT_FRAME_SIZE), + m_ulBufferOffset(0), + m_ulFrameIndex(0), + m_fFrameUsed(NULL), + m_waveFormat(NULL), + m_pFilePtr(NULL), + m_fWriteDisabled(FALSE), + m_bInitialized(FALSE) +{ + PAGED_CODE(); + + m_FileHeader.dwRiff = RIFF_TAG; + m_FileHeader.dwFileSize = 0; + m_FileHeader.dwWave = WAVE_TAG; + m_FileHeader.dwFormat = FMT__TAG; + m_FileHeader.dwFormatLength = sizeof(WAVEFORMATEX); + + m_DataHeader.dwData = DATA_TAG; + m_DataHeader.dwDataLength = 0; + + RtlZeroMemory(&m_objectAttributes, sizeof(m_objectAttributes)); +} // CSaveData + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::~CSaveData() +{ + PAGED_CODE(); + Cleanup(); +} // CSaveData + +void +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::Cleanup +( + void +) +{ + PAGED_CODE(); + + // Update the wave header in data file with real file size. + // + if(m_pFilePtr) + { + // RIFF header, whose size is the whole file size minus RIFF header. + m_FileHeader.dwFileSize = + (DWORD)m_pFilePtr->QuadPart - 2 * sizeof(DWORD); + // The data length is the size of all the audio that was written. + // It gets calculated by taking: + m_DataHeader.dwDataLength = (DWORD)m_pFilePtr->QuadPart - // the whole file size, + sizeof(m_FileHeader) - // minus the file header, + m_FileHeader.dwFormatLength - // minus the format, + sizeof(m_DataHeader); // minus the data header itself. + + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (NT_SUCCESS(FileOpen(FALSE))) + { + FileWriteHeader(); + + FileClose(); + } + + KeReleaseMutex(&m_FileSync, FALSE); + } + + m_FileHeader.dwRiff = RIFF_TAG; + m_FileHeader.dwFileSize = 0; + m_FileHeader.dwWave = WAVE_TAG; + m_FileHeader.dwFormat = FMT__TAG; + m_FileHeader.dwFormatLength = sizeof(WAVEFORMATEX); + + m_DataHeader.dwData = DATA_TAG; + m_DataHeader.dwDataLength = 0; + m_pFilePtr = NULL; + } + + if (m_waveFormat) + { + ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1); + m_waveFormat = NULL; + } + + if (m_fFrameUsed) + { + ExFreePoolWithTag(m_fFrameUsed, SAVEDATA_POOLTAG2); + m_fFrameUsed = NULL; + } + + if (m_FileName.Buffer) + { + ExFreePoolWithTag(m_FileName.Buffer, SAVEDATA_POOLTAG3); + m_FileName.Buffer = NULL; + } + + if (m_pDataBuffer) + { + ExFreePoolWithTag(m_pDataBuffer, SAVEDATA_POOLTAG4); + m_pDataBuffer = NULL; + } +} + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::DestroyWorkItems +( + void +) +{ + PAGED_CODE(); + + if (m_pWorkItems) + { + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + if (m_pWorkItems[i].WorkItem!=NULL) + { + IoFreeWorkItem(m_pWorkItems[i].WorkItem); + m_pWorkItems[i].WorkItem = NULL; + } + } + ExFreePoolWithTag(m_pWorkItems, SAVEDATA_POOLTAG); + m_pWorkItems = NULL; + } + +} // DestroyWorkItems + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::Disable +( + _In_ BOOL fDisable +) +{ + PAGED_CODE(); + + m_fWriteDisabled = fDisable; +} // Disable + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileClose(void) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_FileHandle) + { + ntStatus = ZwClose(m_FileHandle); + m_FileHandle = NULL; + } + + return ntStatus; +} // FileClose + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileOpen +( + _In_ BOOL fOverWrite +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + if( FALSE == m_bInitialized ) + { + return STATUS_UNSUCCESSFUL; + } + + if(!m_FileHandle) + { + ntStatus = + ZwCreateFile + ( + &m_FileHandle, + GENERIC_WRITE | SYNCHRONIZE, + &m_objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + fOverWrite ? FILE_OVERWRITE_IF : FILE_OPEN_IF, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + } + + return ntStatus; +} // FileOpen + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileWrite +( + _In_reads_bytes_(ulDataSize) PBYTE pData, + _In_ ULONG ulDataSize +) +{ + PAGED_CODE(); + + ASSERT(pData); + ASSERT(m_pFilePtr); + + NTSTATUS ntStatus; + + if (m_FileHandle) + { + IO_STATUS_BLOCK ioStatusBlock; + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + pData, + ulDataSize, + m_pFilePtr, + NULL); + + if (NT_SUCCESS(ntStatus)) + { + ASSERT(ioStatusBlock.Information == ulDataSize); + + m_pFilePtr->QuadPart += ulDataSize; + } + } + else + { + ntStatus = STATUS_INVALID_HANDLE; + } + + return ntStatus; +} // FileWrite + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileWriteHeader(void) +{ + PAGED_CODE(); + + NTSTATUS ntStatus; + + if (m_FileHandle && m_waveFormat) + { + IO_STATUS_BLOCK ioStatusBlock; + + m_pFilePtr->QuadPart = 0; + + m_FileHeader.dwFormatLength = (m_waveFormat->wFormatTag == WAVE_FORMAT_PCM) ? + sizeof( PCMWAVEFORMAT ) : + sizeof( WAVEFORMATEX ) + m_waveFormat->cbSize; + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_FileHeader, + sizeof(m_FileHeader), + m_pFilePtr, + NULL); + + if (NT_SUCCESS(ntStatus)) + { + m_pFilePtr->QuadPart += sizeof(m_FileHeader); + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + m_waveFormat, + m_FileHeader.dwFormatLength, + m_pFilePtr, + NULL); + } + + if (NT_SUCCESS(ntStatus)) + { + m_pFilePtr->QuadPart += m_FileHeader.dwFormatLength; + + ntStatus = ZwWriteFile( m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_DataHeader, + sizeof(m_DataHeader), + m_pFilePtr, + NULL); + } + + if (NT_SUCCESS(ntStatus)) + { + m_pFilePtr->QuadPart += sizeof(m_DataHeader); + } + } + else + { + ntStatus = STATUS_INVALID_HANDLE; + } + + + return ntStatus; +} // FileWriteHeader + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetDeviceObject +( + _In_ PDEVICE_OBJECT DeviceObject +) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_pDeviceObject = DeviceObject; + return ntStatus; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +PDEVICE_OBJECT +CSaveData::GetDeviceObject +( + void +) +{ + PAGED_CODE(); + + return m_pDeviceObject; +} + +//============================================================================= +_Use_decl_annotations_ +PSAVEWORKER_PARAM +CSaveData::GetNewWorkItem +( + void +) +{ + LARGE_INTEGER timeOut = { 0 }; + NTSTATUS ntStatus; + + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + ntStatus = + KeWaitForSingleObject + ( + &m_pWorkItems[i].EventDone, + Executive, + KernelMode, + FALSE, + &timeOut + ); + if (STATUS_SUCCESS == ntStatus) + { + if (m_pWorkItems[i].WorkItem) + return &(m_pWorkItems[i]); + else + return NULL; + } + } + + return NULL; +} // GetNewWorkItem + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::Initialize +( + _In_ BOOL _bOffloaded +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen = 0; + IO_STATUS_BLOCK ioStatusBlock = {0}; + HANDLE fileHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fileName; + + if (_bOffloaded) + { + m_ulOffloadStreamId++; + } + else + { + m_ulStreamId++; + } + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER1); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER2); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + } + } + + if (NT_SUCCESS(ntStatus)) + { + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : m_ulStreamId); + m_FileName.Length = 0; + ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); + } + + if (NT_SUCCESS(ntStatus)) + { + m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL + m_FileName.Buffer = (PWSTR) + ExAllocatePool2 + ( + POOL_FLAG_PAGED, + m_FileName.MaximumLength, + SAVEDATA_POOLTAG3 + ); + if (!m_FileName.Buffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Allocate memory for data buffer. + // + if (NT_SUCCESS(ntStatus)) + { + RtlStringCbCopyW(m_FileName.Buffer, m_FileName.MaximumLength, szTemp); + m_FileName.Length = (USHORT)wcslen(m_FileName.Buffer) * sizeof(WCHAR); + + m_pDataBuffer = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_ulBufferSize, + SAVEDATA_POOLTAG4 + ); + if (!m_pDataBuffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Allocate memory for frame usage flags and m_pFilePtr. + // + if (NT_SUCCESS(ntStatus)) + { + m_fFrameUsed = (PBOOL) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_ulFrameCount * sizeof(BOOL) + + sizeof(LARGE_INTEGER), + SAVEDATA_POOLTAG2 + ); + if (!m_fFrameUsed) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Initialize the spinlock to synchronize access to the frames + // + KeInitializeSpinLock ( &m_FrameInUseSpinLock ) ; + + // Initialize the file mutex + // + KeInitializeMutex( &m_FileSync, 1 ) ; + + // Open the data file. + // + if (NT_SUCCESS(ntStatus)) + { + // m_fFrameUsed has additional memory to hold m_pFilePtr + // + m_pFilePtr = (PLARGE_INTEGER) + (((PBYTE) m_fFrameUsed) + m_ulFrameCount * sizeof(BOOL)); + + // Create data file. + InitializeObjectAttributes + ( + &m_objectAttributes, + &m_FileName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL + ); + + m_bInitialized = TRUE; + + // Write wave header information to data file. + ntStatus = KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + ); + + if (STATUS_SUCCESS == ntStatus) + { + ntStatus = FileOpen(TRUE); + if (NT_SUCCESS(ntStatus)) + { + ntStatus = FileWriteHeader(); + + FileClose(); + } + + KeReleaseMutex( &m_FileSync, FALSE ); + } + } + + return ntStatus; +} // Initialize + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::InitializeWorkItems +( + _In_ PDEVICE_OBJECT DeviceObject +) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_pWorkItems != NULL) + { + return ntStatus; + } + + m_pWorkItems = (PSAVEWORKER_PARAM) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + sizeof(SAVEWORKER_PARAM) * MAX_WORKER_ITEM_COUNT, + SAVEDATA_POOLTAG + ); + if (m_pWorkItems) + { + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + + m_pWorkItems[i].WorkItem = IoAllocateWorkItem(DeviceObject); + if(m_pWorkItems[i].WorkItem == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + KeInitializeEvent + ( + &m_pWorkItems[i].EventDone, + NotificationEvent, + TRUE + ); + } + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + return ntStatus; +} // InitializeWorkItems + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +SaveFrameWorkerCallback +( + _In_ PDEVICE_OBJECT pDeviceObject, + _In_opt_ PVOID Context +) +{ + UNREFERENCED_PARAMETER(pDeviceObject); + + PAGED_CODE(); + + ASSERT(Context); + + PSAVEWORKER_PARAM pParam = (PSAVEWORKER_PARAM) Context; + PCSaveData pSaveData; + + if (NULL == pParam) + { + // This is completely unexpected, assert here. + // + ASSERT(pParam); + return; + } + + ASSERT(pParam->pSaveData); + ASSERT(pParam->pSaveData->m_fFrameUsed); + + if (pParam->WorkItem) + { + pSaveData = pParam->pSaveData; + + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &pSaveData->m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (NT_SUCCESS(pSaveData->FileOpen(FALSE))) + { + pSaveData->FileWrite(pParam->pData, pParam->ulDataSize); + pSaveData->FileClose(); + } + InterlockedExchange( (LONG *)&(pSaveData->m_fFrameUsed[pParam->ulFrameNo]), FALSE ); + + KeReleaseMutex( &pSaveData->m_FileSync, FALSE ); + } + } + + KeSetEvent(&pParam->EventDone, 0, FALSE); +} // SaveFrameWorkerCallback + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetDataFormat +( + _In_ PKSDATAFORMAT pDataFormat +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + ASSERT(pDataFormat); + + PWAVEFORMATEX pwfx = NULL; + + if (IsEqualGUIDAligned(pDataFormat->Specifier, + KSDATAFORMAT_SPECIFIER_DSOUND)) + { + pwfx = + &(((PKSDATAFORMAT_DSOUND) pDataFormat)->BufferDesc.WaveFormatEx); + } + else if (IsEqualGUIDAligned(pDataFormat->Specifier, + KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) + { + pwfx = &((PKSDATAFORMAT_WAVEFORMATEX) pDataFormat)->WaveFormatEx; + } + + if (pwfx) + { + // Free the previously allocated waveformat + if (m_waveFormat) + { + ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1); + } + + m_waveFormat = (PWAVEFORMATEX) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + (pwfx->wFormatTag == WAVE_FORMAT_PCM) ? + sizeof( PCMWAVEFORMAT ) : + sizeof( WAVEFORMATEX ) + pwfx->cbSize, + SAVEDATA_POOLTAG1 + ); + + if(m_waveFormat) + { + RtlCopyMemory( m_waveFormat, + pwfx, + (pwfx->wFormatTag == WAVE_FORMAT_PCM) ? + sizeof( PCMWAVEFORMAT ) : + sizeof( WAVEFORMATEX ) + pwfx->cbSize); + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + return ntStatus; +} // SetDataFormat + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetMaxWriteSize +( + _In_ ULONG ulMaxWriteSize +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG bufferSize = 0; + PBYTE buffer = NULL; + + // + // Compute new buffer size. + // + ntStatus = RtlULongMult(ulMaxWriteSize, DEFAULT_FRAME_COUNT, &bufferSize); + if (!NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // + // Alloc memory for buffer. + // + buffer = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + bufferSize, + SAVEDATA_POOLTAG4 + ); + if (!buffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // + // Free old one. + // + if (m_pDataBuffer) + { + ExFreePoolWithTag(m_pDataBuffer, SAVEDATA_POOLTAG4); + m_pDataBuffer = NULL; + } + + // + // Init new buffer settings. + // + m_pDataBuffer = buffer; + m_ulBufferSize = bufferSize; + m_ulFrameSize = ulMaxWriteSize; + + ntStatus = STATUS_SUCCESS; + +Done: + return ntStatus; +} // SetDataFormat + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::ReadData +( + _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount +) +{ + UNREFERENCED_PARAMETER(pBuffer); + UNREFERENCED_PARAMETER(ulByteCount); + + PAGED_CODE(); + + // Not implemented yet. +} // ReadData + +//============================================================================= +_Use_decl_annotations_ +void +CSaveData::SaveFrame +( + _In_ ULONG ulFrameNo, + _In_ ULONG ulDataSize +) +{ + PSAVEWORKER_PARAM pParam = NULL; + + pParam = GetNewWorkItem(); + if (pParam) + { + pParam->pSaveData = this; + pParam->ulFrameNo = ulFrameNo; + pParam->ulDataSize = ulDataSize; + pParam->pData = m_pDataBuffer + ulFrameNo * m_ulFrameSize; + KeResetEvent(&pParam->EventDone); + IoQueueWorkItem(pParam->WorkItem, SaveFrameWorkerCallback, + CriticalWorkQueue, (PVOID)pParam); + } +} // SaveFrame + +//============================================================================= +void +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::WaitAllWorkItems +( + void +) +{ + PAGED_CODE(); + + // Save the last partially-filled frame + if (m_ulBufferOffset > m_ulFrameIndex * m_ulFrameSize) + { + ULONG size; + + size = m_ulBufferOffset - m_ulFrameIndex * m_ulFrameSize; + SaveFrame(m_ulFrameIndex, size); + } + + for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) + { + KeWaitForSingleObject + ( + &(m_pWorkItems[i].EventDone), + Executive, + KernelMode, + FALSE, + NULL + ); + } +} // WaitAllWorkItems + +//============================================================================= +_Use_decl_annotations_ +void +CSaveData::WriteData +( + _In_reads_bytes_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount +) +{ + ASSERT(pBuffer); + + BOOL fSaveFrame = FALSE; + ULONG ulSaveFrameIndex = 0; + KIRQL oldIrql; + + // If stream writing is disabled, then exit. + // + if (m_fWriteDisabled) + { + return; + } + + if( 0 == ulByteCount ) + { + return; + } + + // The logic below assumes that write size is <= than frame size. + if (ulByteCount > m_ulFrameSize) + { + ulByteCount = m_ulFrameSize; + } + + // Check to see if this frame is available. + KeAcquireSpinLock(&m_FrameInUseSpinLock, &oldIrql); + if (!m_fFrameUsed[m_ulFrameIndex]) + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + + ULONG ulWriteBytes = ulByteCount; + + if( (m_ulBufferSize - m_ulBufferOffset) < ulWriteBytes ) + { + ulWriteBytes = m_ulBufferSize - m_ulBufferOffset; + } + + RtlCopyMemory(m_pDataBuffer + m_ulBufferOffset, pBuffer, ulWriteBytes); + m_ulBufferOffset += ulWriteBytes; + + // Check to see if we need to save this frame + if (m_ulBufferOffset >= ((m_ulFrameIndex + 1) * m_ulFrameSize)) + { + fSaveFrame = TRUE; + } + + // Loop the buffer, if we reached the end. + if (m_ulBufferOffset == m_ulBufferSize) + { + fSaveFrame = TRUE; + m_ulBufferOffset = 0; + } + + if (fSaveFrame) + { + InterlockedExchange( (LONG *)&(m_fFrameUsed[m_ulFrameIndex]), TRUE ); + ulSaveFrameIndex = m_ulFrameIndex; + m_ulFrameIndex = (m_ulFrameIndex + 1) % m_ulFrameCount; + } + + // Write the left over if the next frame is available. + if (ulWriteBytes != ulByteCount) + { + KeAcquireSpinLock(&m_FrameInUseSpinLock, &oldIrql ); + if (!m_fFrameUsed[m_ulFrameIndex]) + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + RtlCopyMemory + ( + m_pDataBuffer + m_ulBufferOffset, + pBuffer + ulWriteBytes, + ulByteCount - ulWriteBytes + ); + + m_ulBufferOffset += ulByteCount - ulWriteBytes; + } + else + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql); + } + } + + if (fSaveFrame) + { + SaveFrame(ulSaveFrameIndex, m_ulFrameSize); + } + } + else + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + } + +} // WriteData + + diff --git a/audio/Acx/Samples/Common/SaveData.h b/audio/Acx/Samples/Common/SaveData.h new file mode 100644 index 000000000..9138352f0 --- /dev/null +++ b/audio/Acx/Samples/Common/SaveData.h @@ -0,0 +1,259 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SaveData.h + +Abstract: + + Declaration of data saving class for ACX driver samples. This class supplies services +to save data to disk. + + +--*/ + +#pragma once + +//----------------------------------------------------------------------------- +// Forward declaration +//----------------------------------------------------------------------------- +class CSaveData; +typedef CSaveData *PCSaveData; + + +//----------------------------------------------------------------------------- +// Structs +//----------------------------------------------------------------------------- + +// Parameter to workitem. +#include +typedef struct _SAVEWORKER_PARAM { + PIO_WORKITEM WorkItem; + ULONG ulFrameNo; + ULONG ulDataSize; + PBYTE pData; + PCSaveData pSaveData; + KEVENT EventDone; +} SAVEWORKER_PARAM; +typedef SAVEWORKER_PARAM *PSAVEWORKER_PARAM; +#include + +// wave file header. +#include +typedef struct _OUTPUT_FILE_HEADER +{ + DWORD dwRiff; + DWORD dwFileSize; + DWORD dwWave; + DWORD dwFormat; + DWORD dwFormatLength; +} OUTPUT_FILE_HEADER; +typedef OUTPUT_FILE_HEADER *POUTPUT_FILE_HEADER; + +typedef struct _OUTPUT_DATA_HEADER +{ + DWORD dwData; + DWORD dwDataLength; +} OUTPUT_DATA_HEADER; +typedef OUTPUT_DATA_HEADER *POUTPUT_DATA_HEADER; + +#include + +//----------------------------------------------------------------------------- +// Classes +//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// +// CSaveData +// Saves the wave data to disk. +// +__drv_maxIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE SaveFrameWorkerCallback; + +class CSaveData +{ +protected: + UNICODE_STRING m_FileName; // DataFile name. + HANDLE m_FileHandle; // DataFile handle. + PBYTE m_pDataBuffer; // Data buffer. + ULONG m_ulBufferSize; // Total buffer size. + + ULONG m_ulFrameIndex; // Current Frame. + ULONG m_ulFrameCount; // Frame count. + ULONG m_ulFrameSize; + ULONG m_ulBufferOffset; // index in buffer. + PBOOL m_fFrameUsed; // Frame usage table. + KSPIN_LOCK m_FrameInUseSpinLock; // Spinlock for synch. + KMUTEX m_FileSync; // Synchronizes file access + + OBJECT_ATTRIBUTES m_objectAttributes; // Used for opening file. + + OUTPUT_FILE_HEADER m_FileHeader; + PWAVEFORMATEX m_waveFormat; + OUTPUT_DATA_HEADER m_DataHeader; + PLARGE_INTEGER m_pFilePtr; + + static PDEVICE_OBJECT m_pDeviceObject; + static ULONG m_ulStreamId; + static ULONG m_ulOffloadStreamId; + static PSAVEWORKER_PARAM m_pWorkItems; + + BOOL m_fWriteDisabled; + + BOOL m_bInitialized; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSaveData(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CSaveData(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + Cleanup( + void + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + InitializeWorkItems( + _In_ PDEVICE_OBJECT DeviceObject + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + DestroyWorkItems( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + Disable( + _In_ BOOL fDisable + ); + + static + __drv_maxIRQL(DISPATCH_LEVEL) + PSAVEWORKER_PARAM + GetNewWorkItem( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Initialize( + _In_ BOOL _bOffloaded + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetDeviceObject( + _In_ PDEVICE_OBJECT DeviceObject + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + PDEVICE_OBJECT + GetDeviceObject( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + ReadData( + _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetDataFormat( + _In_ PKSDATAFORMAT pDataFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetMaxWriteSize( + _In_ ULONG ulMaxWriteSize + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + WaitAllWorkItems( + void + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + void + WriteData( + _In_reads_bytes_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount + ); + +private: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileClose( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileOpen( + _In_ BOOL fOverWrite + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileWrite( + _In_reads_bytes_(ulDataSize) PBYTE pData, + _In_ ULONG ulDataSize + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileWriteHeader( + void + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + void + SaveFrame( + _In_ ULONG ulFrameNo, + _In_ ULONG ulDataSize + ); + + friend + IO_WORKITEM_ROUTINE SaveFrameWorkerCallback; +}; +typedef CSaveData *PCSaveData; + diff --git a/audio/Acx/Samples/Common/SimPeakMeter.cpp b/audio/Acx/Samples/Common/SimPeakMeter.cpp new file mode 100644 index 000000000..0dfbd4e5c --- /dev/null +++ b/audio/Acx/Samples/Common/SimPeakMeter.cpp @@ -0,0 +1,106 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SimPeakMeter.cpp + +Abstract: + + Virtual Peakmeter - aggregates all streams + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "SimPeakMeter.h" + +#ifndef __INTELLISENSE__ +#include "SimPeakMeter.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter::CSimPeakMeter() +{ + PAGED_CODE(); + m_NumStreams = 0; + m_PeakMeterIndex = 0; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter::~CSimPeakMeter() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +LONG CSimPeakMeter::GetValue(ULONG Channel) +{ + PAGED_CODE(); + + // Ignore channel + UNREFERENCED_PARAMETER(Channel); + +#define PEAKMETER_VALUE_FULL (PEAKMETER_MAXIMUM / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_HALF (PEAKMETER_MAXIMUM / 2 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_QUARTER (PEAKMETER_MAXIMUM / 4 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_ONE_EIGTH (PEAKMETER_MAXIMUM / 8 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) + + LONG PeakMeterValues[] = { + PEAKMETER_VALUE_ONE_EIGTH, + PEAKMETER_VALUE_QUARTER, + PEAKMETER_VALUE_HALF, + PEAKMETER_VALUE_FULL, + PEAKMETER_VALUE_HALF, + PEAKMETER_VALUE_QUARTER + }; + + if (m_NumStreams) + { + LONG pmi = InterlockedIncrement(&m_PeakMeterIndex); + if (pmi == ARRAYSIZE(PeakMeterValues)) + { + pmi = 0; + InterlockedExchange(&m_PeakMeterIndex, 0); + } + + return PeakMeterValues[pmi]; + } + + // + // No active streams. Peak meter = 0 + // + return 0; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CSimPeakMeter::StartStream() +{ + PAGED_CODE(); + InterlockedIncrement(&m_NumStreams); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CSimPeakMeter::StopStream() +{ + PAGED_CODE(); + + ASSERT(m_NumStreams); + InterlockedDecrement(&m_NumStreams); + + return STATUS_SUCCESS; +} diff --git a/audio/Acx/Samples/Common/SimPeakMeter.h b/audio/Acx/Samples/Common/SimPeakMeter.h new file mode 100644 index 000000000..7203f299c --- /dev/null +++ b/audio/Acx/Samples/Common/SimPeakMeter.h @@ -0,0 +1,51 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + SimPeakMeter.h + +Abstract: + + Virtual Peakmeter - aggregates all streams + +Environment: + + Kernel mode + +--*/ + +#pragma once + +class CSimPeakMeter +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSimPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CSimPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + LONG GetValue(_In_ ULONG Channel); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS StartStream(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS StopStream(); + +private: + LONG m_NumStreams; + LONG m_PeakMeterIndex; +}; + diff --git a/audio/Acx/Samples/Common/StreamEngine.cpp b/audio/Acx/Samples/Common/StreamEngine.cpp new file mode 100644 index 000000000..be90bac6b --- /dev/null +++ b/audio/Acx/Samples/Common/StreamEngine.cpp @@ -0,0 +1,1345 @@ +/*++ + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + StreamEngine.cpp + +Abstract: + + Virtual Streaming Engine - this module controls streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "public.h" +#include +#include +#include +#include +#include "streamengine.h" + +#ifndef __INTELLISENSE__ +#include "streamengine.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_opt_ CSimPeakMeter *CircuitPeakmeter +) + : m_PacketsCount(0), + m_PacketSize(0), + m_FirstPacketOffset(0), + m_NotificationTimer(NULL), + m_CurrentState(AcxStreamStateStop), + m_CurrentPacket(0), + m_Position(0), + m_Stream(Stream), + m_StreamFormat(StreamFormat), + m_StartTime(0), + m_StartPosition(0), + m_GlitchAdjust(0), + m_ToneFrequency(DEFAULT_FREQUENCY), + m_Offload(Offload), + m_pCircuitPeakmeter(CircuitPeakmeter) +{ + PAGED_CODE(); + + KeQueryPerformanceCounter(&m_PerformanceCounterFrequency); + RtlZeroMemory(m_Packets, sizeof(m_Packets)); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::~CStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AllocateRtPackets( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET* Packets +) +{ + NTSTATUS status = STATUS_SUCCESS; + PACX_RTPACKET packets = NULL; + PVOID packetBuffer = NULL; + ULONG i; + ULONG packetAllocSizeInPages = 0; + ULONG packetAllocSizeInBytes = 0; + ULONG firstPacketOffset = 0; + size_t packetsSize = 0; + + PAGED_CODE(); + + if (PacketCount > MAX_PACKET_COUNT) + { + ASSERT(FALSE); + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + status = RtlSizeTMult(PacketCount, sizeof(ACX_RTPACKET), &packetsSize); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + packets = (PACX_RTPACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, packetsSize, DeviceDriverTag); + if (!packets) + { + status = STATUS_NO_MEMORY; + ASSERT(FALSE); + goto exit; + } + + // + // We need to allocate page-aligned buffers, to ensure no kernel memory leaks + // to user space. Round up the packet size to page aligned, then calculate + // the first packet's buffer offset so packet 0 ends on a page boundary and + // packet 1 begins on a page boundary. + // + status = RtlULongAdd(PacketSize, PAGE_SIZE - 1, &packetAllocSizeInPages); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + packetAllocSizeInPages = packetAllocSizeInPages / PAGE_SIZE; + packetAllocSizeInBytes = PAGE_SIZE * packetAllocSizeInPages; + firstPacketOffset = packetAllocSizeInBytes - PacketSize; + + for (i = 0; i < PacketCount; ++i) + { + PMDL pMdl = NULL; + + ACX_RTPACKET_INIT(&packets[i]); + + packetBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, packetAllocSizeInBytes, DeviceDriverTag); + if (packetBuffer == NULL) + { + status = STATUS_NO_MEMORY; + goto exit; + } + + pMdl = IoAllocateMdl(packetBuffer, packetAllocSizeInBytes, FALSE, TRUE, NULL); + if (pMdl == NULL) + { + status = STATUS_NO_MEMORY; + goto exit; + } + + MmBuildMdlForNonPagedPool(pMdl); + + WDF_MEMORY_DESCRIPTOR_INIT_MDL(&((packets)[i].RtPacketBuffer), pMdl, packetAllocSizeInBytes); + + packets[i].RtPacketSize = PacketSize; + if (i == 0) + { + packets[i].RtPacketOffset = firstPacketOffset; + } + else + { + packets[i].RtPacketOffset = 0; + } + m_Packets[i] = packetBuffer; + + packetBuffer = NULL; + } + + *Packets = packets; + packets = NULL; + m_PacketsCount = PacketCount; + m_PacketSize = PacketSize; + m_FirstPacketOffset = firstPacketOffset; + +exit: + if (packetBuffer) + { + ExFreePoolWithTag(packetBuffer, DeviceDriverTag); + } + if (packets) + { + FreeRtPackets(packets, PacketCount); + } + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CStreamEngine::FreeRtPackets( + _Frees_ptr_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +) +{ + ULONG i; + PVOID buffer; + + PAGED_CODE(); + + for (i = 0; i < PacketCount; ++i) + { + if (Packets[i].RtPacketBuffer.u.MdlType.Mdl) + { + buffer = MmGetMdlVirtualAddress(Packets[i].RtPacketBuffer.u.MdlType.Mdl); + IoFreeMdl(Packets[i].RtPacketBuffer.u.MdlType.Mdl); + ExFreePool(buffer); + } + } + + ExFreePool(Packets); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + WDF_TIMER_CONFIG timerConfig; + WDF_OBJECT_ATTRIBUTES timerAttributes; + PSTREAM_TIMER_CONTEXT timerCtx; + + PAGED_CODE(); + + // + // If already in this state, do nothing. + // + if (m_CurrentState == AcxStreamStatePause) + { + // Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + if (m_CurrentState != AcxStreamStateStop) + { + // Error out. + status = STATUS_INVALID_STATE_TRANSITION; + goto exit; + } + + // + // Stop to Pause. + // + WDF_TIMER_CONFIG_INIT(&timerConfig, CStreamEngine::s_EvtStreamPassCallback); + timerConfig.AutomaticSerialization = TRUE; + timerConfig.UseHighResolutionTimer = WdfTrue; + timerConfig.Period = 0; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes, STREAM_TIMER_CONTEXT); + timerAttributes.ParentObject = m_Stream; + + status = WdfTimerCreate(&timerConfig, &timerAttributes, &m_NotificationTimer); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + timerCtx = GetStreamTimerContext(m_NotificationTimer); + timerCtx->StreamEngine = this; + + m_CurrentState = AcxStreamStatePause; + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + // + // If already in this state, do nothing. + // + if (m_CurrentState == AcxStreamStateStop) + { + // Nothing to do. + goto exit; + } + + // + // Just assert we are in the correct state. + // On the way down we always want to succeed. + // + ASSERT(m_CurrentState == AcxStreamStatePause); + + // + // Pause to Stop. + // + if (m_NotificationTimer) + { + WdfTimerStop(m_NotificationTimer, TRUE); + WdfObjectDelete(m_NotificationTimer); + m_NotificationTimer = NULL; + } + + KeFlushQueuedDpcs(); + + m_Position = 0; + m_GlitchAdjust = 0; + m_CurrentPacket = 0; + + m_CurrentState = AcxStreamStateStop; + +exit: + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Pause() +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + if (m_CurrentState == AcxStreamStatePause) + { + // Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + if (m_CurrentState != AcxStreamStateRun) + { + // Error out. + status = STATUS_INVALID_STATE_TRANSITION; + goto exit; + } + + m_PeakMeter.StopStream(); + if (m_pCircuitPeakmeter) + { + m_pCircuitPeakmeter->StopStream(); + } + + // + // Run to Pause. + // + WdfTimerStop(m_NotificationTimer, TRUE); + + // Save the position we paused at. + UpdatePosition(); + + m_CurrentState = AcxStreamStatePause; + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Run() +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + if (m_CurrentState == AcxStreamStateRun) + { + // Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + if (m_CurrentState != AcxStreamStatePause) + { + status = STATUS_INVALID_STATE_TRANSITION; + goto exit; + } + + m_PeakMeter.StartStream(); + if (m_pCircuitPeakmeter) + { + m_pCircuitPeakmeter->StartStream(); + } + + // + // Pause to Run. + // + // Save the time and position - if we ran and paused previously, the StartTime and StartPosition will allow + // us to continue scheduling packet completions correctly, while still reporting absolute position from the + // start of the stream. + // + m_StartTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + m_StartPosition = m_Position; + + // Reset time we've lost to glitches + m_GlitchAdjust = 0; + + ScheduleNextPass(); + + m_CurrentState = AcxStreamStateRun; + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetPresentationPosition( + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +) +{ + ULONG blockAlign; + LARGE_INTEGER qpc; + + PAGED_CODE(); + + blockAlign = AcxDataFormatGetBlockAlign(m_StreamFormat); + + // Update the position based on the current time + UpdatePosition(); + qpc = KeQueryPerformanceCounter(NULL); + + *PositionInBlocks = m_Position / blockAlign; + *QPCPosition = (ULONGLONG)qpc.QuadPart; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetLinearBufferPosition( + _Out_ PULONGLONG Position +) +{ + UNREFERENCED_PARAMETER(Position); + PAGED_CODE(); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::SetCurrentWritePosition( + _In_ ULONG Position +) +{ + UNREFERENCED_PARAMETER(Position); + PAGED_CODE(); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::SetLastBufferPosition( + _In_ ULONG Position +) +{ + UNREFERENCED_PARAMETER(Position); + PAGED_CODE(); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AssignDrmContentId( + ULONG DrmContentId, + PACXDRMRIGHTS DrmRights +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + UNREFERENCED_PARAMETER(DrmRights); + + // + // At this point the driver should enforce the new DrmRights. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // + // From MSDN: + // + // This sample doesn't forward protected content, but if your driver uses + // lower layer drivers or a different stack to properly work, please see the + // following info from MSDN: + // + // "Before allowing protected content to flow through a data path, the system + // verifies that the data path is secure. To do so, the system authenticates + // each module in the data path beginning at the upstream end of the data path + // and moving downstream. As each module is authenticated, that module gives + // the system information about the next module in the data path so that it + // can also be authenticated. To be successfully authenticated, a module's + // binary file must be signed as DRM-compliant. + // + // Two adjacent modules in the data path can communicate with each other in + // one of several ways. If the upstream module calls the downstream module + // through IoCallDriver, the downstream module is part of a WDM driver. In + // this case, the upstream module calls the AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetHWLatency( + _Out_ ULONG* FifoSize, + _Out_ ULONG* Delay +) +{ + PAGED_CODE(); + + *FifoSize = 128; + *Delay = 0; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter * +CStreamEngine::GetPeakMeter() +{ + PAGED_CODE(); + + return &m_PeakMeter; +} + +_Use_decl_annotations_ +VOID +CStreamEngine::s_EvtStreamPassCallback( + _In_ WDFTIMER Timer +) +{ + CStreamEngine* This; + PSTREAM_TIMER_CONTEXT timerCtx; + + // Get our stream engine pointer from the timer context + timerCtx = GetStreamTimerContext(Timer); + This = timerCtx->StreamEngine; + + // Call the StreamPassCallback for the engine + This->StreamPassCallback(); +} + +// This is run every time the stream timer fires +_Use_decl_annotations_ +VOID +CStreamEngine::StreamPassCallback() +{ + ULONGLONG completedPacket; + ULONGLONG qpcCompleted; + + // Process the packet (e.g. save render to file/generate capture data) + ProcessPacket(); + + // We've completed a packet! Increment our currently active packet + completedPacket = (ULONG)InterlockedIncrement((LONG*)&m_CurrentPacket) - 1; + // Save the time at which we moved to the next packet + qpcCompleted = (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart; + + InterlockedExchange64(&m_LastPacketStart.QuadPart, m_CurrentPacketStart.QuadPart); + InterlockedExchange64(&m_CurrentPacketStart.QuadPart, qpcCompleted); + + // Tell ACX we've completed the packet. + (void)AcxRtStreamNotifyPacketComplete(m_Stream, completedPacket, qpcCompleted); + + // Schedule when our new current packet will finish + ScheduleNextPass(); +} + +_Use_decl_annotations_ +VOID +CStreamEngine::ScheduleNextPass() +{ + LONGLONG delay = 0; + ULONG bytesPerSecond; + ULONGLONG nextPacket = 0; + ULONGLONG nextPacketStartPosition = 0; + ULONGLONG nextPacketPositionFromLastPause = 0; + ULONGLONG nextPacketTimeFromLastPauseHns = 0; + ULONGLONG nextPacketTime = 0; + ULONGLONG currentTime; + BOOLEAN inTimerQueue = FALSE; + + // Get the number of bytes per second from our stored stream format + bytesPerSecond = GetBytesPerSecond(); + + // Calculate the absolute position of the beginning of the next packet from the beginning of the stream + nextPacket = m_CurrentPacket + 1; + nextPacketStartPosition = nextPacket * m_PacketSize; + + // Adjust next packet position to account for the last time we resumed from Pause + nextPacketPositionFromLastPause = nextPacketStartPosition - m_StartPosition; + + // Convert from bytes to HNS (to prevent truncation, multiply first then divide) + nextPacketTimeFromLastPauseHns = nextPacketPositionFromLastPause * HNS_PER_SEC / bytesPerSecond; + + // Next packet time is Time @ resume from Pause, offset for lost time due to glitch, with next packet time added + nextPacketTime = m_StartTime + m_GlitchAdjust + nextPacketTimeFromLastPauseHns; + + currentTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + + // Determine how long we want to wait, in HNS. Negative since it's a relative wait + delay = -(LONGLONG)(nextPacketTime - currentTime); + + // If the delay isn't negative, this means we lost some time (e.g. broken into kernel debugger). Update + // our glitch adjust to account for that lost time, and attempt to schedule again + if (delay >= 0) + { + // Glitch!!! + // Update the glitch adjustment and set the new delay. + m_GlitchAdjust += delay; + + StreamPassCallback(); + + return; + } + + // Start the timer for our next pass! Note the timer isn't periodic. + inTimerQueue = WdfTimerStart(m_NotificationTimer, delay); + + // We shouldn't be scheduling our next pass if the timer was previously still pending + ASSERT(inTimerQueue == FALSE); +} + +_Use_decl_annotations_ +VOID +CStreamEngine::UpdatePosition() +{ + ULONGLONG currentTime; + ULONG bytesPerSecond; + + if (m_CurrentState != AcxStreamStateRun) + { + return; + } + bytesPerSecond = GetBytesPerSecond(); + currentTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + + // Update position + m_Position = m_StartPosition - m_GlitchAdjust + (currentTime - m_StartTime) * bytesPerSecond / HNS_PER_SEC; +} + +_Use_decl_annotations_ +ULONG +CStreamEngine::GetBytesPerSecond() +{ + ULONG bytesPerSecond; + + bytesPerSecond = AcxDataFormatGetAverageBytesPerSec(m_StreamFormat); + + return bytesPerSecond; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetCurrentPacket( + _Out_ PULONG CurrentPacket +) +{ + ULONG currentPacket; + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + *CurrentPacket = currentPacket; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_ CSimPeakMeter * CircuitPeakmeter + +) + : CStreamEngine(Stream, StreamFormat, Offload, CircuitPeakmeter) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::~CRenderStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + status = CStreamEngine::PrepareHardware(); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + status = m_SaveData.SetDataFormat((PKSDATAFORMAT)AcxDataFormatGetKsDataFormat(m_StreamFormat)); + if (!NT_SUCCESS(status)) + { + status = STATUS_SUCCESS; + goto exit; + } + + status = m_SaveData.Initialize(m_Offload); + if (!NT_SUCCESS(status)) + { + status = STATUS_SUCCESS; + goto exit; + } + + status = m_SaveData.SetMaxWriteSize(m_PacketSize * m_PacketsCount * 16); + if (!NT_SUCCESS(status)) + { + status = STATUS_SUCCESS; + goto exit; + } + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + m_SaveData.WaitAllWorkItems(); + m_SaveData.Cleanup(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::AssignDrmContentId( + ULONG DrmContentId, + PACXDRMRIGHTS DrmRights + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + + // + // At this point the driver should enforce the new DrmRights. + // The sample driver handles DrmRights per stream basis, and + // stops writing the stream to disk, if CopyProtect = TRUE. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // Loopback: if CopyProtect is true, disable loopback stream. + // + + // + // Sample writes each stream seperately to disk. If the rights for this + // stream indicates that the stream is CopyProtected, stop writing to disk. + // + m_SaveData.Disable(DrmRights->CopyProtect); + + // + // From MSDN: + // + // This sample doesn't forward protected content, but if your driver uses + // lower layer drivers or a different stack to properly work, please see the + // following info from MSDN: + // + // "Before allowing protected content to flow through a data path, the system + // verifies that the data path is secure. To do so, the system authenticates + // each module in the data path beginning at the upstream end of the data path + // and moving downstream. As each module is authenticated, that module gives + // the system information about the next module in the data path so that it + // can also be authenticated. To be successfully authenticated, a module's + // binary file must be signed as DRM-compliant. + // + // Two adjacent modules in the data path can communicate with each other in + // one of several ways. If the upstream module calls the downstream module + // through IoCallDriver, the downstream module is part of a WDM driver. In + // this case, the upstream module calls the AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::SetRenderPacket( + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength +) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG currentPacket; + + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(EosPacketLength); + + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + if (Packet <= currentPacket) + { + //ASSERT(FALSE); + status = STATUS_DATA_LATE_ERROR; + } + else if (Packet > currentPacket + 1) + { + //ASSERT(FALSE); + status = STATUS_DATA_OVERRUN; + } + + return status; +} + +_Use_decl_annotations_ +VOID +CRenderStreamEngine::ProcessPacket() +{ + ULONG currentPacket; + ULONG packetIndex; + PBYTE packetBuffer; + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + packetIndex = currentPacket % m_PacketsCount; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + m_SaveData.WriteData(packetBuffer, m_PacketSize); +} + + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat +) + : CStreamEngine(Stream, StreamFormat, FALSE, NULL), + m_EnableWaveCapture(0) +{ + PAGED_CODE(); + + m_CurrentPacketStart.QuadPart = 0; + m_LastPacketStart.QuadPart = 0; + + RtlInitUnicodeString(&m_HostCaptureFileName, NULL); + RtlInitUnicodeString(&m_LoopbackCaptureFileName, NULL); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::~CCaptureStreamEngine() +{ + PAGED_CODE(); + + RtlFreeUnicodeString(&m_HostCaptureFileName); + RtlFreeUnicodeString(&m_LoopbackCaptureFileName); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_SUCCESS; + PWAVEFORMATEXTENSIBLE pwfext = NULL; + + PAGED_CODE(); + + status = CStreamEngine::PrepareHardware(); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + (void)ReadRegistrySettings(); + + pwfext = (PWAVEFORMATEXTENSIBLE)AcxDataFormatGetWaveFormatExtensible(m_StreamFormat); + if (pwfext == NULL) + { + // Cannot initialize reader or generator with a format that's not understood + status = STATUS_NO_MATCH; + ASSERT(FALSE); + goto exit; + } + + if (m_EnableWaveCapture) + { + status = m_WaveReader.Init(pwfext, &m_HostCaptureFileName); + if (!NT_SUCCESS(status)) + { + m_EnableWaveCapture = FALSE; + } + } + + if (!m_EnableWaveCapture) + { + status = m_ToneGenerator.Init(m_ToneFrequency, pwfext); + } + +exit: + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + if (m_EnableWaveCapture) + { + m_WaveReader.WaitAllWorkItems(); + } + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::GetCapturePacket( + _Out_ ULONG* LastCapturePacket, + _Out_ ULONGLONG* QPCPacketStart, + _Out_ BOOLEAN* MoreData +) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG currentPacket; + LONGLONG qpcPacketStart; + + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + qpcPacketStart = InterlockedCompareExchange64(&m_LastPacketStart.QuadPart, -1, -1); + + *LastCapturePacket = currentPacket - 1; + *QPCPacketStart = (ULONGLONG)qpcPacketStart; + *MoreData = FALSE; + + return status; +} + +_Use_decl_annotations_ +VOID +CCaptureStreamEngine::ProcessPacket() +{ + ULONG currentPacket; + ULONG packetIndex; + PBYTE packetBuffer; + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + packetIndex = currentPacket % m_PacketsCount; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + if (m_EnableWaveCapture) + { + m_WaveReader.ReadWaveData(packetBuffer, m_PacketSize); + } + else + { + m_ToneGenerator.GenerateSine(packetBuffer, m_PacketSize); + } +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReadRegistrySettings() +{ + NTSTATUS status; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; + + RTL_QUERY_REGISTRY_TABLE paramTable[] = { + // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"EnableWaveCapture", &m_EnableWaveCapture, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_EnableWaveCapture, sizeof(DWORD) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureFileName", &m_HostCaptureFileName, (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_SZ, &m_HostCaptureFileName, sizeof(UNICODE_STRING) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"LoopbackCaptureFileName", &m_LoopbackCaptureFileName, (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_SZ, &m_LoopbackCaptureFileName, sizeof(UNICODE_STRING) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + PAGED_CODE(); + + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + status = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); + + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); + + if (DriverKey) + { + ZwClose(DriverKey); + } + +exit: + if (!NT_SUCCESS(status)) + { + m_EnableWaveCapture = FALSE; + } + + return status; +} +_Use_decl_annotations_ +PAGED_CODE_SEG +CBufferedCaptureStreamEngine::CBufferedCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CKeywordDetector* KeywordDetector + +) + : CCaptureStreamEngine(Stream, StreamFormat), + m_KeywordDetector(KeywordDetector) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CBufferedCaptureStreamEngine::~CBufferedCaptureStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::Pause() +{ + PAGED_CODE(); + + m_KeywordDetector->Stop(); + return CCaptureStreamEngine::Pause(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::Run() +{ + PAGED_CODE(); + + m_KeywordDetector->Run(); + return CCaptureStreamEngine::Run(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::GetCapturePacket( + _Out_ ULONG* LastCapturePacket, + _Out_ ULONGLONG* QPCPacketStart, + _Out_ BOOLEAN* MoreData +) +{ + PAGED_CODE(); + + // retrieve the packet from the fifo queue + return m_KeywordDetector->GetReadPacket(m_PacketsCount, m_PacketSize, m_Packets, LastCapturePacket, QPCPacketStart, MoreData); +} + +_Use_decl_annotations_ +VOID +CBufferedCaptureStreamEngine::ProcessPacket() +{ + LARGE_INTEGER qpc; + LARGE_INTEGER qpcFrequency; + + qpc = KeQueryPerformanceCounter(&qpcFrequency); + + // Add the next packet to the fifo queue + m_KeywordDetector->DpcRoutine(qpc.QuadPart, qpcFrequency.QuadPart); +} + +//Streamengine callbacks + +VOID +EvtStreamDestroy( + _In_ WDFOBJECT Object +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + ctx = GetStreamEngineContext((ACXSTREAM)Object); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + ctx->StreamEngine = NULL; + delete streamEngine; +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG* FifoSize, + _Out_ ULONG* Delay +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->GetHWLatency(FifoSize, Delay); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAllocateRtPackets( + _In_ ACXSTREAM Stream, + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET* Packets +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AllocateRtPackets(PacketCount, PacketSize, Packets); +} + +PAGED_CODE_SEG +VOID +EvtStreamFreeRtPackets( + _In_ ACXSTREAM Stream, + _In_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->FreeRtPackets(Packets, PacketCount); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->PrepareHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->ReleaseHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamRun( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Run(); +} + + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPause( + _In_ ACXSTREAM Stream +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Pause(); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AssignDrmContentId(DrmContentId, DrmRights); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetCurrentPacket( + _In_ ACXSTREAM Stream, + _Out_ PULONG CurrentPacket +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast(ctx->StreamEngine); + + return streamEngine->GetCurrentPacket(CurrentPacket); +} + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetPresentationPosition( + _In_ ACXSTREAM Stream, + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +) +{ + PSTREAMENGINE_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetStreamEngineContext(Stream); + + streamEngine = static_cast(ctx->StreamEngine); + + return streamEngine->GetPresentationPosition(PositionInBlocks, QPCPosition); +} + diff --git a/audio/Acx/Samples/Common/StreamEngine.h b/audio/Acx/Samples/Common/StreamEngine.h new file mode 100644 index 000000000..deeff95a6 --- /dev/null +++ b/audio/Acx/Samples/Common/StreamEngine.h @@ -0,0 +1,449 @@ +#pragma once + +#include "savedata.h" +#include "tonegenerator.h" +#include "WaveReader.h" +#include "SimPeakMeter.h" +#include "keyworddetector.h" + +#define HNSTIME_PER_MILLISECOND 10000 + +#define MAX_PACKET_COUNT 2 + +#define DEFAULT_FREQUENCY 220 +#define LOOPBACK_FREQUENCY 500 + +// Stream callbacks shared between Capture and Render + +VOID +EvtStreamDestroy( + _In_ WDFOBJECT Object +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG* FifoSize, + _Out_ ULONG* Delay +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAllocateRtPackets( + _In_ ACXSTREAM Stream, + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET* Packets +); + +PAGED_CODE_SEG +VOID +EvtStreamFreeRtPackets( + _In_ ACXSTREAM Stream, + _In_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamRun( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamPause( + _In_ ACXSTREAM Stream +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetCurrentPacket( + _In_ ACXSTREAM Stream, + _Out_ PULONG CurrentPacket +); + +PAGED_CODE_SEG +NTSTATUS +EvtStreamGetPresentationPosition( + _In_ ACXSTREAM Stream, + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +); + + +class CStreamEngine +{ +public: + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AllocateRtPackets( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET * Packets + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + FreeRtPackets( + _Frees_ptr_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPresentationPosition( + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetLinearBufferPosition( + _Out_ PULONGLONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetCurrentWritePosition( + _In_ ULONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetLastBufferPosition( + _In_ ULONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCurrentPacket( + _Out_ PULONG CurrentPacket + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSimPeakMeter * + GetPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_opt_ CSimPeakMeter *CircuitPeakmeter + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CStreamEngine(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + SetFrequency( + _In_ DWORD ToneFrequency + ) + { + PAGED_CODE(); + + m_ToneFrequency = ToneFrequency; + } + +protected: + PVOID m_Packets[MAX_PACKET_COUNT]; + ULONG m_PacketsCount; + ULONG m_PacketSize; + ULONG m_FirstPacketOffset; + WDFTIMER m_NotificationTimer; + ACX_STREAM_STATE m_CurrentState; + ULONG m_CurrentPacket; + ULONGLONG m_Position; + ACXSTREAM m_Stream; + ACXDATAFORMAT m_StreamFormat; + ULONGLONG m_StartTime; + ULONGLONG m_StartPosition; + ULONGLONG m_GlitchAdjust; + LARGE_INTEGER m_PerformanceCounterFrequency; + LARGE_INTEGER m_CurrentPacketStart; + LARGE_INTEGER m_LastPacketStart; + DWORD m_ToneFrequency; + BOOL m_Offload; + CSimPeakMeter m_PeakMeter; + CSimPeakMeter* m_pCircuitPeakmeter; + + static + __drv_maxIRQL(DISPATCH_LEVEL) + _Function_class_(EVT_WDF_TIMER) + VOID s_EvtStreamPassCallback( + _In_ WDFTIMER Timer + ); + + // This is run every time the stream timer fires + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + StreamPassCallback(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ScheduleNextPass(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + UpdatePosition(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + ULONG + GetBytesPerSecond(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket() = 0; +}; + +class CRenderStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ BOOL Offload, + _In_ CSimPeakMeter *CircuitPeakmeter + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CRenderStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetRenderPacket( + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength + ); + +protected: + CSaveData m_SaveData; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket(); + +}; + +class CCaptureStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ); + +protected: + ToneGenerator m_ToneGenerator; + CWaveReader m_WaveReader; + DWORD m_EnableWaveCapture; + UNICODE_STRING m_HostCaptureFileName; + UNICODE_STRING m_LoopbackCaptureFileName; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReadRegistrySettings(); +}; + +class CBufferedCaptureStreamEngine : public CCaptureStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CBufferedCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CKeywordDetector * KeywordDetector + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CBufferedCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ); + +protected: + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + ProcessPacket(); + + CKeywordDetector * m_KeywordDetector; +}; + +// Define circuit/stream pin context. +// +typedef struct _STREAM_TIMER_CONTEXT { + CStreamEngine * StreamEngine; +} STREAM_TIMER_CONTEXT, *PSTREAM_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAM_TIMER_CONTEXT, GetStreamTimerContext) diff --git a/audio/Acx/Samples/Common/ToneGenerator.cpp b/audio/Acx/Samples/Common/ToneGenerator.cpp new file mode 100644 index 000000000..fc30e3b28 --- /dev/null +++ b/audio/Acx/Samples/Common/ToneGenerator.cpp @@ -0,0 +1,297 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + ToneGenerator.cpp + +Abstract: + + Implementation of sine wave generator for ACX driver samples + + +--*/ +#include "private.h" +#include "public.h" +#include +#include +#include +#include +#include "ToneGenerator.h" + +#define TONEGENERATOR_POOLTAG 'rGnT' + +const double TONE_AMPLITUDE = 0.5; // Scalar value, should be between 0.0 - 1.0 +const double TWO_PI = M_PI * 2; + +DWORD g_DisableToneGenerator = 0; // default is to generate tones. + +#define IF_FAILED_JUMP(result, tag) do {if (!NT_SUCCESS(result)) {goto tag;}} while(false) +#define IF_TRUE_JUMP(result, tag) do {if (result) {goto tag;}} while(false) +#define IF_TRUE_ACTION_JUMP(result, action, tag) do {if (result) {action; goto tag;}} while(false) + +// +// Double to short conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +short ConvertToShort(double Value) +{ + return (short)(Value * _I16_MAX); +}; + +// +// Double to char conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +unsigned char ConvertToUChar(double Value) +{ + const double F_127_5 = 127.5; + return (unsigned char)(Value * F_127_5 + F_127_5); +}; + +// +// Ctor: basic init. +// +_Use_decl_annotations_ +PAGED_CODE_SEG +ToneGenerator::ToneGenerator() +: m_Frequency(0), + m_ChannelCount(0), + m_BitsPerSample(0), + m_SamplesPerSecond(0), + m_Mute(false), + m_PartialFrame(NULL), + m_PartialFrameBytes(0), + m_FrameSize(0) +{ + PAGED_CODE(); + + // Theta (double) and SampleIncrement (double) are init in the Init() method + // after saving the floating point state. +} + +// +// Dtor: free resources. +// +_Use_decl_annotations_ +PAGED_CODE_SEG +ToneGenerator::~ToneGenerator() +{ + PAGED_CODE(); + + if (m_PartialFrame) + { + ExFreePoolWithTag(m_PartialFrame, TONEGENERATOR_POOLTAG); + m_PartialFrame = NULL; + m_PartialFrameBytes = 0; + } +} + +// +// Init a new frame. +// Note: caller will save and restore the floatingpoint state. +// +#pragma warning(push) +// Caller wraps this routine between KeSaveFloatingPointState/KeRestoreFloatingPointState calls. +#pragma warning(disable: 28110) + +_Use_decl_annotations_ +VOID ToneGenerator::InitNewFrame +( + _Out_writes_bytes_(FrameSize) BYTE* Frame, + _In_ DWORD FrameSize +) +{ + double sinValue = TONE_AMPLITUDE * sin( m_Theta ); + + if (FrameSize != (DWORD)m_ChannelCount * m_BitsPerSample/8) + { + ASSERT(FALSE); + RtlZeroMemory(Frame, FrameSize); + return; + } + + for(ULONG i = 0; i < m_ChannelCount; ++i) + { + if (m_BitsPerSample == 8) + { + unsigned char *dataBuffer = reinterpret_cast(Frame); + dataBuffer[i] = ConvertToUChar(sinValue); + } + else // 16 bits per sample + { + short *dataBuffer = reinterpret_cast(Frame); + dataBuffer[i] = ConvertToShort(sinValue); + } + } + + m_Theta += m_SampleIncrement; + if (m_Theta >= TWO_PI) + { + m_Theta -= TWO_PI; + } +} +#pragma warning(pop) + +// +// GenerateSamples() +// +// Generate a sine wave that fits into the specified buffer. +// +// Buffer - Buffer to hold the samples +// BufferLength - Length of the buffer. +// +// Note: this function supports 16bit and 8bit samples only. +// +_Use_decl_annotations_ +void ToneGenerator::GenerateSine +( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ size_t BufferLength +) +{ + NTSTATUS status; + KFLOATING_SAVE saveData; + BYTE * buffer; + size_t length; + size_t copyBytes; + + // if muted, or tone generator disabled via registry, + // we deliver silence. + if (m_Mute || g_DisableToneGenerator) + { + goto ZeroBuffer; + } + + status = KeSaveFloatingPointState(&saveData); + if (!NT_SUCCESS(status)) + { + goto ZeroBuffer; + } + + buffer = Buffer; + length = BufferLength; + + // + // Check if we have any residual frame bytes from the last time. + // + if (m_PartialFrameBytes) + { + ASSERT(m_FrameSize > m_PartialFrameBytes); + DWORD offset = m_FrameSize - m_PartialFrameBytes; + copyBytes = MIN(m_PartialFrameBytes, length); + RtlCopyMemory(buffer, m_PartialFrame + offset, copyBytes); + RtlZeroMemory(m_PartialFrame + offset, copyBytes); + length -= copyBytes; + buffer += copyBytes; + m_PartialFrameBytes = 0; + } + + IF_TRUE_JUMP(length == 0, Done); + + // + // Copy all the aligned frames. + // + + size_t frames = length/m_FrameSize; + + for (size_t i = 0; i < frames; ++i) + { + InitNewFrame(buffer, m_FrameSize); + buffer += m_FrameSize; + length -= m_FrameSize; + } + + IF_TRUE_JUMP(length == 0, Done); + + // + // Copy any partial frame at the end. + // + ASSERT(m_FrameSize > length); + InitNewFrame(m_PartialFrame, m_FrameSize); + RtlCopyMemory(buffer, m_PartialFrame, length); + RtlZeroMemory(m_PartialFrame, length); + m_PartialFrameBytes = m_FrameSize - (DWORD)length; + +Done: + KeRestoreFloatingPointState(&saveData); + return; + +ZeroBuffer: + RtlZeroMemory(Buffer, BufferLength); + return; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS ToneGenerator::Init +( + _In_ DWORD ToneFrequency, + _In_ PWAVEFORMATEXTENSIBLE WfExt +) +{ + NTSTATUS status = STATUS_SUCCESS; + KFLOATING_SAVE saveData; + + PAGED_CODE(); + + // + // This sample supports PCM 16bit formats only. + // + if ((WfExt->Format.wFormatTag != WAVE_FORMAT_PCM && + !(WfExt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && + IsEqualGUIDAligned(WfExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))) || + (WfExt->Format.wBitsPerSample != 16 && + WfExt->Format.wBitsPerSample != 8)) + { + status = STATUS_NOT_SUPPORTED; + } + IF_FAILED_JUMP(status, Done); + + // + // Save floating state (just in case). + // + status = KeSaveFloatingPointState(&saveData); + IF_FAILED_JUMP(status, Done); + + // + // Basic init. + // + RtlZeroMemory(&m_Theta, sizeof(m_Theta)); + m_Frequency = ToneFrequency; + m_ChannelCount = WfExt->Format.nChannels; // # channels. + m_BitsPerSample = WfExt->Format.wBitsPerSample; // bits per sample. + m_SamplesPerSecond = WfExt->Format.nSamplesPerSec; // samples per sec. + m_Mute = false; + m_SampleIncrement = (m_Frequency * TWO_PI) / (double)m_SamplesPerSecond; + m_FrameSize = (DWORD)m_ChannelCount * m_BitsPerSample/8; + ASSERT(m_FrameSize == WfExt->Format.nBlockAlign); + + // + // Restore floating state. + // + KeRestoreFloatingPointState(&saveData); + + // + // Allocate a buffer to hold a partial frame. + // + m_PartialFrame = (BYTE*)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + m_FrameSize, + TONEGENERATOR_POOLTAG); + + IF_TRUE_ACTION_JUMP(m_PartialFrame == NULL, status = STATUS_INSUFFICIENT_RESOURCES, Done); + + status = STATUS_SUCCESS; + +Done: + return status; +} + + diff --git a/audio/Acx/Samples/Common/ToneGenerator.h b/audio/Acx/Samples/Common/ToneGenerator.h new file mode 100644 index 000000000..9de138f83 --- /dev/null +++ b/audio/Acx/Samples/Common/ToneGenerator.h @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + ToneGenerator.h + +Abstract: + + Declaration of sine wave generator for ACX driver samples. + + +--*/ +#pragma once + +#define _USE_MATH_DEFINES +#include +#include + +class ToneGenerator +{ +public: + DWORD m_Frequency; + WORD m_ChannelCount; + WORD m_BitsPerSample; + DWORD m_SamplesPerSecond; + double m_Theta; + double m_SampleIncrement; + bool m_Mute; + BYTE* m_PartialFrame; + DWORD m_PartialFrameBytes; + DWORD m_FrameSize; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ToneGenerator(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~ToneGenerator(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Init + ( + _In_ DWORD ToneFrequency, + _In_ PWAVEFORMATEXTENSIBLE WfExt + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + VOID + GenerateSine + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ size_t BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + SetMute + ( + _In_ bool Value + ) + { + PAGED_CODE(); + + m_Mute = Value; + } + +private: + __drv_maxIRQL(DISPATCH_LEVEL) + VOID InitNewFrame + ( + _Out_writes_bytes_(FrameSize) BYTE* Frame, + _In_ DWORD FrameSize + ); +}; + + diff --git a/audio/Acx/Samples/Common/Trace_macros.h b/audio/Acx/Samples/Common/Trace_macros.h new file mode 100644 index 000000000..5291b3916 --- /dev/null +++ b/audio/Acx/Samples/Common/Trace_macros.h @@ -0,0 +1,470 @@ +#pragma once + +#include // for va_start, etc. + +#pragma region Tracing level definitions + +#if !defined(FAILED_NTSTATUS) +#define FAILED_NTSTATUS(status) (((NTSTATUS)(status)) < 0) +#endif + +#if !defined(SUCCEEDED_NTSTATUS) +#define SUCCEEDED_NTSTATUS(status) (((NTSTATUS)(status)) >= 0) +#endif + +//! Define shorter versions of the ETW trace levels +#define LEVEL_CRITICAL TRACE_LEVEL_CRITICAL +#define LEVEL_ERROR TRACE_LEVEL_ERROR +#define LEVEL_WARNING TRACE_LEVEL_WARNING +#define LEVEL_INFO TRACE_LEVEL_INFORMATION +#define LEVEL_VERBOSE TRACE_LEVEL_VERBOSE + +//! This is a special LEVEL that changes the trace macro level from ERROR to VERBOSE +//! depending on whether the return value passed to the macro was non-zero or zero, +//! respectively. +#define LEVEL_COND 0xFF +#pragma endregion + +//! Logger and Enabled that supports both level and flag. +//! \link https://msdn.microsoft.com/en-us/library/windows/hardware/ff542492(v=vs.85).aspx +#define WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) WPP_LEVEL_LOGGER(FLAGS) +#define WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) (WPP_LEVEL_ENABLED(FLAGS) && (WPP_CONTROL(WPP_BIT_ ## FLAGS).Level >= LEVEL)) + +//! This macro is to be used by the WPP custom macros below that want to do conditional +//! logging based on return value. If LEVEL_VERBOSE is specified when calling a macro that +//! uses this, the level will be set to LEVEL_INFO if return code is 0 or +//! LEVEL_ERROR if the return code is not 0. This can be called in any PRE macro. +//! +//! The "LEVEL == LEVEL_COND" check generates a compiler warning that the "conditional +//! expression is constant" so we explicitly disable that. +#define WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) \ + BOOL bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS); \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4127)) \ + if (LEVEL == LEVEL_COND) \ + { \ + if (SUCCEEDED(HR)) \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_VERBOSE, FLAGS); \ + } \ + else \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_ERROR, FLAGS); \ + } \ + } \ + __pragma(warning(pop)) + +#define WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) \ + BOOLEAN bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS); \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4127)) \ + if (LEVEL == LEVEL_COND) \ + { \ + if (SUCCEEDED_NTSTATUS(STATUS)) \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_VERBOSE, FLAGS); \ + } \ + else \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_ERROR, FLAGS); \ + } \ + } \ + __pragma(warning(pop)) + + +#define WPP_LEVEL_FLAGS_IFRLOG_ENABLED(LEVEL, FLAGS, IFRLOG) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_LOGGER(LEVEL, FLAGS, IFRLOG) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) +#define WPP_LEVEL_IFRLOG_FLAGS_ENABLED(LEVEL, IFRLOG, FLAGS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_IFRLOG_FLAGS_LOGGER(LEVEL, IFRLOG, FLAGS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_HR_PRE(LEVEL, FLAGS, HR) { WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) +#define WPP_LEVEL_FLAGS_HR_POST(LEVEL, FLAGS, HR) ;} +#define WPP_LEVEL_FLAGS_HR_ENABLED(LEVEL, FLAGS, HR) bEnabled +#define WPP_LEVEL_FLAGS_HR_LOGGER(LEVEL, FLAGS, HR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETVAL_ENABLED(LEVEL, FLAGS, RETVAL) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETVAL_LOGGER(LEVEL, FLAGS, RETVAL) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_FI_ENABLED(LEVEL, FLAGS, FI) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_FI_LOGGER(LEVEL, FLAGS, FI) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_STATUS_PRE(LEVEL, FLAGS, STATUS) { WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) +#define WPP_LEVEL_FLAGS_STATUS_POST(LEVEL, FLAGS, STATUS) ;} +#define WPP_LEVEL_FLAGS_STATUS_ENABLED(LEVEL, FLAGS, STATUS) bEnabled +#define WPP_LEVEL_FLAGS_STATUS_LOGGER(LEVEL, FLAGS, STATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_PRE(LEVEL, FLAGS, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_POST(LEVEL, FLAGS, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_ENABLED(LEVEL, FLAGS, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_LOGGER(LEVEL, FLAGS, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_PRE(LEVEL, FLAGS, IFRLOG, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_POST(LEVEL, FLAGS, IFRLOG, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_PRE(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) do {\ +NTSTATUS __statusRet = (RETSTATUS);\ +if(__statusRet == ALLOWEDSTATUS)\ +{\ + __statusRet = STATUS_SUCCESS;\ +}\ +if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_POST(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETPTR_PRE(LEVEL, FLAGS, RETPTR) do { if ((RETPTR) == nullptr) { +#define WPP_LEVEL_FLAGS_RETPTR_POST(LEVEL, FLAGS, RETPTR) ; return STATUS_INSUFFICIENT_RESOURCES; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETPTR_ENABLED(LEVEL, FLAGS, RETPTR) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETPTR_LOGGER(LEVEL, FLAGS, RETPTR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_PRE(LEVEL, FLAGS, RETSTATUS, RETPTR) do { NTSTATUS __statusRet = (RETSTATUS); if ((RETPTR) == nullptr) { +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_POST(LEVEL, FLAGS, RETSTATUS, RETPTR) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_ENABLED(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_LOGGER(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_PRE(LEVEL, FLAGS, RETSTATUS, POSCOND) do { NTSTATUS __statusRet = (RETSTATUS); if ((POSCOND)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_POST(LEVEL, FLAGS, RETSTATUS, POSCOND) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_ENABLED(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_LOGGER(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_PRE(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if ((POSCOND)) { +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_POST(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_PRE(LEVEL, FLAGS, RETSTATUS, NEGCOND) do { NTSTATUS __statusRet = (RETSTATUS); if (!(NEGCOND)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_POST(LEVEL, FLAGS, RETSTATUS, NEGCOND) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_ENABLED(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_LOGGER(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#pragma region IFR Enablement Macros + +// Opt-in to a WPP recorder feature that enables independent evaluation of conditions to decide if a +// message needs to be sent to the recorder, an enabled session, or both. +#define ENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER 1 + +// Logger/Enabled macros used to decide if a message that is being sent to a custom recorder should +// also go to an enabled session. These do not depend on the custom recorder itself, so just +// delegate to the default. +#define WPP_IFRLOG_LEVEL_FLAGS_LOGGER(IFRLOG, LEVEL, FLAGS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) +#define WPP_IFRLOG_LEVEL_FLAGS_ENABLED(IFRLOG, LEVEL, FLAGS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) + +#define WPP_RECORDER_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) \ + ((LEVEL == LEVEL_COND) ? \ + (FAILED(HR) ? \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_ERROR, FLAGS) : WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_VERBOSE, FLAGS)) : \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)) + +#define WPP_RECORDER_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) \ + ((LEVEL == LEVEL_COND) ? \ + (FAILED_NTSTATUS(STATUS) ? \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_ERROR, FLAGS) : WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_VERBOSE, FLAGS)) : \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)) + +#define WPP_RECORDER_LEVEL_FLAGS_HR_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_HR_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETVAL_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETVAL_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_FI_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_FI_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_STATUS_ARGS(LEVEL, FLAGS, STATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_STATUS_FILTER(LEVEL, FLAGS, STATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_ARGS(LEVEL, FLAGS, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_FILTER(LEVEL, FLAGS, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETPTR_ARGS(LEVEL, FLAGS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETPTR_FILTER(LEVEL, FLAGS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_RETPTR_ARGS(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_RETPTR_FILTER(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_POSCOND_ARGS(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_POSCOND_FILTER(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_NEGCOND_ARGS(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_NEGCOND_FILTER(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) +#pragma endregion + +#pragma region Custom tracing macros + +// begin_wpp config +// USEPREFIX(DrvLogCritical, "%!STDPREFIX!CRIT: "); +// USEPREFIX(DrvLogError, "%!STDPREFIX!ERROR: "); +// USEPREFIX(DrvLogWarning, "%!STDPREFIX!WARN: "); +// USEPREFIX(DrvLogInfo, "%!STDPREFIX!INFO: "); +// USEPREFIX(DrvLogVerbose, "%!STDPREFIX!VERB: "); +// USEPREFIX(DrvLogEnter, "%!STDPREFIX!ENTER"); +// USEPREFIX(DrvLogExit, "%!STDPREFIX!EXIT"); +// end_wpp + +// begin_wpp config +// FUNC DrvLogCritical{LEVEL=TRACE_LEVEL_CRITICAL}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogError{LEVEL=TRACE_LEVEL_ERROR}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogWarning{LEVEL=TRACE_LEVEL_WARNING}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogInfo{LEVEL=TRACE_LEVEL_INFORMATION}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogEnter{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=FLAG_FUNCTION}(IFRLOG,...); +// FUNC DrvLogVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogExit{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=FLAG_FUNCTION}(IFRLOG,...); +// end_wpp + + +#ifdef __INTELLISENSE__ +#define FLAG_DEVICE_ALL 0x01 +#define FLAG_FUNCTION 0x02 +#define FLAG_INFO 0x04 +#define FLAG_PNP 0x08 +#define FLAG_POWER 0x10 +#define FLAG_STREAM 0x20 +#define FLAG_INIT 0x40 +#define FLAG_DDI 0x80 +#define FLAG_GENERIC 0x100 +void DrvLogCritical(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogError(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogWarning(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogInfo(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogEnter(void* log, ...); +void DrvLogVerbose(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogExit(void* log, ...); + +void RETURN_IF_FAILED(NTSTATUS status); +void RETURN_NTSTATUS_IF_FAILED(NTSTATUS status); +void RETURN_NTSTATUS_IF_FAILED_MSG(NTSTATUS status, const WCHAR* fmt, ...); +void RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED(NTSTATUS returnStatus, NTSTATUS allowedStatus); +void RETURN_NTSTATUS_IF_NULL_ALLOC(PVOID ptr); +void RETURN_NTSTATUS_IF_NULL(PVOID ptr); +void RETURN_NTSTATUS_IF_TRUE(BOOL condition, NTSTATUS status); +void RETURN_NTSTATUS_IF_TRUE_MSG(BOOL condition, NTSTATUS status, const WCHAR* fmt, ...); +void RETURN_NTSTATUS_IF_FALSE(BOOL condition, NTSTATUS status); +void RETURN_NTSTATUS(NTSTATUS status); +void RETURN_NTSTATUS_MSG(NTSTATUS status, const WCHAR* fmt, ...); +#endif// __INTELLISENSE__ + +//********************************************************* +// MACRO: TRACE_METHOD_LINE +// +// begin_wpp config +// FUNC TRACE_METHOD_LINE(LEVEL, FLAGS, MSG, ...); +// USESUFFIX (TRACE_METHOD_LINE, ", this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_ENTRY +// +// begin_wpp config +// FUNC TRACE_METHOD_ENTRY(LEVEL, FLAGS); +// USESUFFIX (TRACE_METHOD_ENTRY, "Enter, this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT(LEVEL, FLAGS); +// USESUFFIX (TRACE_METHOD_EXIT, "Exit, this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_HR +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_HR(LEVEL, FLAGS, HR); +// USESUFFIX (TRACE_METHOD_EXIT_HR, "Exit, this=0x%p, hr=%!HRESULT!", this, HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_DWORD +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_DWORD(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_METHOD_EXIT_DWORD, "Exit, this=0x%p, ret=0x%08Ix ", this, RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_PTR +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_PTR(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_METHOD_EXIT_PTR,"Exit, this=0x%p, retptr=0x%p", this, RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_STATUS +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_STATUS(LEVEL, FLAGS, STATUS); +// USESUFFIX (TRACE_METHOD_EXIT_STATUS, "Exit, this=0x%p, status=%!STATUS!", this, STATUS); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_ENTRY +// +// begin_wpp config +// FUNC TRACE_FUNCTION_ENTRY(LEVEL, FLAGS); +// USESUFFIX (TRACE_FUNCTION_ENTRY, "Enter"); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT(LEVEL, FLAGS); +// USESUFFIX (TRACE_FUNCTION_EXIT, "Exit"); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_HR +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_HR(LEVEL, FLAGS, HR); +// USESUFFIX (TRACE_FUNCTION_EXIT_HR, "Exit, hr=%!HRESULT!", HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_DWORD +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_DWORD(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_FUNCTION_EXIT_DWORD, "Exit, ret=0x%08Ix", RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_PTR +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_PTR(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_FUNCTION_EXIT_PTR, "Exit, retptr=0x%p", RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_STATUS +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_STATUS(LEVEL, FLAGS, STATUS); +// USESUFFIX (TRACE_FUNCTION_EXIT_STATUS, "Exit, status=%!STATUS!", STATUS); +// end_wpp + +//********************************************************* +// MACRO: TRACE_LINE +// +// begin_wpp config +// FUNC TRACE_LINE(LEVEL, FLAGS, MSG, ...); +// end_wpp + +//********************************************************* +// MACRO: TRACE_HRESULT +// +// begin_wpp config +// FUNC TRACE_HRESULT(LEVEL, FLAGS, HR, MSG, ...); +// USESUFFIX (TRACE_HRESULT, ", ret=%!HRESULT!", HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FAILURE_INFO (WIL FailureInfo logging) +// see: https://github.com/microsoft/wil/blob/master/include/wil/result_macros.h +// +// begin_wpp config +// FUNC TRACE_FAILURE_INFO(LEVEL, FLAGS, FI); +// USESUFFIX(TRACE_FAILURE_INFO, " [%04X] '%ws', hr=%!HRESULT! ['%s' (%u)]", FI.threadId, FI.pszMessage, FI.hr, FI.pszFile, FI.uLineNumber); +// end_wpp + +// MACRO: RETURN_IF_FAILED +// +// begin_wpp config +// FUNC RETURN_IF_FAILED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS); +// USEPREFIX(RETURN_IF_FAILED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_IF_FAILED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + + +// MACRO: RETURN_NTSTATUS_IF_FAILED +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS, MSG, ...); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED_MSG, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED_MSG, " - status=%!STATUS!",__statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS, ALLOWEDSTATUS); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_NULL_ALLOC +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_NULL_ALLOC{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETPTR); +// USESUFFIX(RETURN_NTSTATUS_IF_NULL, "status=STATUS_INSUFFICIENT_RESOURCES"); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_NULL +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_NULL{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETSTATUS, RETPTR); +// USESUFFIX(RETURN_NTSTATUS_IF_NULL, "status=%!STATUS!", __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_TRUE +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_TRUE{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(POSCOND, RETSTATUS); +// USESUFFIX(RETURN_NTSTATUS_IF_TRUE, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_TRUE_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_TRUE_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(POSCOND, RETSTATUS, MSG, ...); +// USESUFFIX(RETURN_NTSTATUS_IF_TRUE_MSG, " - status=%!STATUS!", __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FALSE +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FALSE{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETSTATUS, NEGCOND); +// USESUFFIX(RETURN_NTSTATUS_IF_FALSE, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS +// +// begin_wpp config +// FUNC RETURN_NTSTATUS{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS); +// USESUFFIX(RETURN_NTSTATUS, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_AudioDspLog}(RETSTATUS, MSG, ...); +// USESUFFIX(RETURN_NTSTATUS_MSG, " - status=%!STATUS!", __statusRet); +// end_wpp + +#define W32 +#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings + +#pragma endregion diff --git a/audio/Acx/Samples/Common/WaveReader.cpp b/audio/Acx/Samples/Common/WaveReader.cpp new file mode 100644 index 000000000..4fa6eae90 --- /dev/null +++ b/audio/Acx/Samples/Common/WaveReader.cpp @@ -0,0 +1,769 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + WaveReader.cpp + +Abstract: + Implementation of wave file reader for ACX sample drivers. + + To read data from disk, this class maintains a circular data buffer. This buffer is segmented into multiple chunks of + big buffer (Though we only need two, so it is set to two now). Initially we fill first two chunks and once a chunk gets emptied + by OS, we schedule a workitem to fill the next available chunk. + + +--*/ + +#pragma warning (disable : 4127) +#pragma warning (disable : 26165) + +#include "private.h" +#include +#include +#include +#include +#include "WaveReader.h" + +#define FILE_NAME_BUFFER_TAG 'WRT1' +#define WAVE_DATA_BUFFER_TAG 'WRT2' +#define WORK_ITEM_BUFFER_TAG 'WRT3' + +#define MAX_READ_WORKER_ITEM_COUNT 15 + +#define IF_FAILED_JUMP(result, tag) do {if (!NT_SUCCESS(result)) {goto tag;}} while(false) +#define IF_TRUE_JUMP(result, tag) do {if (result) {goto tag;}} while(false) +#define IF_TRUE_ACTION_JUMP(result, action, tag) do {if (result) {action; goto tag;}} while(false) + +PREADWORKER_PARAM CWaveReader::m_pWorkItems = NULL; +PDEVICE_OBJECT CWaveReader::m_pDeviceObject = NULL; + + +/*++ + +Routine Description: + Ctor: basic init. + +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +CWaveReader::CWaveReader() +: m_ChannelCount(0), + m_BitsPerSample(0), + m_SamplesPerSecond(0), + m_Mute(false), + m_FileHandle(NULL) +{ + PAGED_CODE(); + m_WaveDataQueue.pWavData = NULL; + KeInitializeMutex(&m_FileSync, 0); +} + +/*++ + +Routine Description: + Dtor: free resources. + +--*/ +_Use_decl_annotations_ +PAGED_CODE_SEG +CWaveReader::~CWaveReader() +{ + PAGED_CODE(); + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (m_WaveDataQueue.pWavData != NULL) + { + ExFreePoolWithTag(m_WaveDataQueue.pWavData, WAVE_DATA_BUFFER_TAG); + m_WaveDataQueue.pWavData = NULL; + } + + FileClose(); + KeReleaseMutex(&m_FileSync, FALSE); + } + +} + +/*++ + +Routine Description: + - Initializing the workitems. These workitems will be scheduled asynchronously by the OS. + - When these work items will be scheduled the wave file will be read and the data + - will be put inside the big chunks. + +Arguments: + Device object + +Return Value: + NT status code. + +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::InitializeWorkItems(_In_ PDEVICE_OBJECT DeviceObject) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_pWorkItems != NULL) + { + return ntStatus; + } + + m_pWorkItems = (PREADWORKER_PARAM) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + sizeof(READWORKER_PARAM) * MAX_READ_WORKER_ITEM_COUNT, + 'RDPT' + ); + if (m_pWorkItems) + { + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + + m_pWorkItems[i].WorkItem = IoAllocateWorkItem(DeviceObject); + if (m_pWorkItems[i].WorkItem == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + KeInitializeEvent + ( + &m_pWorkItems[i].EventDone, + NotificationEvent, + TRUE + ); + } + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + return ntStatus; +} + +/*++ + +Routine Description: +- Wait for all the scheduled workitems to finish. + +--*/ + + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void CWaveReader::WaitAllWorkItems() +{ + PAGED_CODE(); + + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + KeWaitForSingleObject + ( + &(m_pWorkItems[i].EventDone), + Executive, + KernelMode, + FALSE, + NULL + ); + } +} + +/*++ + +Routine Description: + - Deallocating the workitems. + +--*/ + + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID CWaveReader::DestroyWorkItems() +{ + PAGED_CODE(); + + if (m_pWorkItems) + { + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + if (m_pWorkItems[i].WorkItem != NULL) + { + IoFreeWorkItem(m_pWorkItems[i].WorkItem); + m_pWorkItems[i].WorkItem = NULL; + } + } + ExFreePoolWithTag(m_pWorkItems, WORK_ITEM_BUFFER_TAG); + m_pWorkItems = NULL; + } +} + +/*++ + +Routine Description: + - Get a free work item to schedule a file read operation. + +--*/ +_Use_decl_annotations_ +PREADWORKER_PARAM CWaveReader::GetNewWorkItem() +{ + LARGE_INTEGER timeOut = { 0 }; + NTSTATUS ntStatus; + + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + ntStatus = + KeWaitForSingleObject + ( + &m_pWorkItems[i].EventDone, + Executive, + KernelMode, + FALSE, + &timeOut + ); + if (STATUS_SUCCESS == ntStatus) + { + if (m_pWorkItems[i].WorkItem) + return &(m_pWorkItems[i]); + else + return NULL; + } + } + + return NULL; +} + +/*++ +Routine Description: +- This routine will enqueue a workitem for reading wave file and putting +- the data into the chunk buffer. + +Arguments: + Chunk descriptor for the chunk to be filled. +--*/ + +_Use_decl_annotations_ +VOID CWaveReader::ReadWavChunk(PCHUNKDESCRIPTOR pChunkDescriptor) +{ + PREADWORKER_PARAM pParam = NULL; + + pParam = GetNewWorkItem(); + if (pParam) + { + pParam->PtrWaveReader = this; + pParam->PtrChunkDescriptor = pChunkDescriptor; + KeResetEvent(&pParam->EventDone); + IoQueueWorkItem(pParam->WorkItem, ReadFrameWorkerCallback, + DelayedWorkQueue, (PVOID)pParam); + } +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; +/* +Routine Description: +- This routine will be called by the OS. It will fill the chunk buffer, defined by the chunk descriptor +- If end of file is reached it will mark the end of file as true. + +Arguments: + pDeviceObject - Device object + Context - pointer to reader worker params +*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID ReadFrameWorkerCallback +( + _In_ PDEVICE_OBJECT pDeviceObject, + _In_opt_ PVOID Context +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(pDeviceObject); + pWaveReader pWavRd; + PREADWORKER_PARAM pParam = (PREADWORKER_PARAM)Context; + + if (NULL == pParam) + { + // This is completely unexpected, assert here. + // + ASSERT(pParam); + goto exit; + } + + pWavRd = pParam->PtrWaveReader; + + if (pWavRd == NULL) + { + goto exit; + } + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &pWavRd->m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ASSERT(Context); + + IO_STATUS_BLOCK ioStatusBlock; + + if (pParam->WorkItem) + { + if (pWavRd->m_WaveDataQueue.bEofReached || pWavRd->m_WaveDataQueue.pWavData == NULL) + { + KeReleaseMutex(&pWavRd->m_FileSync, FALSE); + goto exit; + } + + if (pParam->PtrChunkDescriptor->pStartAddress != NULL) + { + ntStatus = ZwReadFile(pWavRd->m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + pParam->PtrChunkDescriptor->pStartAddress, + pParam->PtrChunkDescriptor->ulChunkLength, + NULL, + NULL); + + pParam->PtrChunkDescriptor->bIsChunkEmpty = false; + + if (ioStatusBlock.Information != pParam->PtrChunkDescriptor->ulChunkLength) + { + pWavRd->m_WaveDataQueue.bEofReached = true; + } + } + } + + KeReleaseMutex(&pWavRd->m_FileSync, FALSE); + } + +exit: + KeSetEvent(&pParam->EventDone, 0, FALSE); +} + +/*++ + +Routine Description: +- If all the chunks are empty this resturn true. + +--*/ + +_Use_decl_annotations_ +bool CWaveReader::IsAllChunkEmpty() +{ + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + if (!m_WaveDataQueue.sChunkDescriptor[i].bIsChunkEmpty) + { + return false; + } + } + return true; +} + +/*++ +Routine Description: + - This routine does the actual copy of data from the chunk buffer to the buffer provided by OS. + - If it empties the current chunk buffer, then it sets it state to empty and then enqueue a workitem + - to read data from the wave file and put it to the next available chunk buffer. + +Arguments: + Buffer - Pointer to the OS buffer + BufferLength - Length of the data to be filled (in bytes) + +--*/ +_Use_decl_annotations_ +VOID CWaveReader::CopyDataFromRingBuffer +( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength +) +{ + if (IsAllChunkEmpty()) + { + RtlZeroMemory(Buffer, BufferLength); + } + else + { + ULONG prevChunk = (m_WaveDataQueue.ulReadPtr*NUM_OF_CHUNK_FOR_FILE_READ )/ m_WaveDataQueue.ulLength; + + ///////////////// + BYTE *currentBuf = Buffer; + ULONG length = BufferLength; + while (length > 0) + { + ULONG runWrite = min(length, m_WaveDataQueue.ulLength - m_WaveDataQueue.ulReadPtr); + + // Copy the wave buffer data to OS buffer + RtlCopyMemory(currentBuf, m_WaveDataQueue.pWavData + m_WaveDataQueue.ulReadPtr, runWrite); + // Zero out the wave buffer, so that if wave end of file is reached we should copy only zeros + RtlZeroMemory(m_WaveDataQueue.pWavData + m_WaveDataQueue.ulReadPtr, runWrite); + // Update the read pointer + m_WaveDataQueue.ulReadPtr = (m_WaveDataQueue.ulReadPtr + runWrite) % m_WaveDataQueue.ulLength; + currentBuf += runWrite; + length = length - runWrite; + } + + ULONG curChunk = (m_WaveDataQueue.ulReadPtr*NUM_OF_CHUNK_FOR_FILE_READ) / m_WaveDataQueue.ulLength; + + if (curChunk != prevChunk) + { + m_WaveDataQueue.currentExecutedChunk++; + // Schedule a workitem to read data from the wave file + ULONG chunkNo = m_WaveDataQueue.currentExecutedChunk % NUM_OF_CHUNK_FOR_FILE_READ; + m_WaveDataQueue.sChunkDescriptor[chunkNo].bIsChunkEmpty = true; + if (!m_WaveDataQueue.bEofReached) + { + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[chunkNo]); + } + } + } +} + +/*++ +Routine Description: + - Just a high level read buffer call. + + Arguments: + Buffer - Pointer to the OS buffer + BufferLength - Length of the data to be filled (in bytes) +--*/ + +_Use_decl_annotations_ +VOID CWaveReader::ReadWaveData +( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength +) +{ + if (m_Mute) + { + RtlZeroMemory(Buffer, BufferLength); + } + else + { + CopyDataFromRingBuffer(Buffer, BufferLength); + } +} + +/*++ +Routine Description: +- initialization for the wavereader member variables, +- Allocating memory for the 1 second buffer +- Preread the one second buffer data, so that when OS comes to read the data we have it available in the memory. + +Arguments: + WfExt - Format which should be used for capture + fileNameString - name of the file to be read + +Return: + NTStatus +--*/ +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::Init +( + _In_ PWAVEFORMATEXTENSIBLE WfExt, + _In_ PUNICODE_STRING puiFileName +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + KFLOATING_SAVE saveData; + + // Save floating state (just in case). + ntStatus = KeSaveFloatingPointState(&saveData); + if (!NT_SUCCESS(ntStatus)) + { + return ntStatus; + } + + // + // This sample supports PCM 16bit formats only. + // + if ((WfExt->Format.wFormatTag != WAVE_FORMAT_PCM && + !(WfExt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && + IsEqualGUIDAligned(WfExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))) || + (WfExt->Format.wBitsPerSample != 16 && + WfExt->Format.wBitsPerSample != 8)) + { + ntStatus = STATUS_NOT_SUPPORTED; + } + IF_FAILED_JUMP(ntStatus, Done); + + // Basic init. + m_ChannelCount = WfExt->Format.nChannels; // # channels. + m_BitsPerSample = WfExt->Format.wBitsPerSample; // bits per sample. + m_SamplesPerSecond = WfExt->Format.nSamplesPerSec; // samples per sec. + m_Mute = false; + + // Wave data queue initialization + m_WaveDataQueue.ulLength = WfExt->Format.nAvgBytesPerSec; + m_WaveDataQueue.bEofReached = false; + m_WaveDataQueue.ulReadPtr = 0; + + // Mark all the chunk empty + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + m_WaveDataQueue.sChunkDescriptor[i].bIsChunkEmpty = true; + } + + ntStatus = OpenWaveFile(puiFileName); + IF_FAILED_JUMP(ntStatus, Done); + + ntStatus = AllocateBigBuffer(); + IF_FAILED_JUMP(ntStatus, Done); + + ntStatus = ReadHeaderAndFillBuffer(); + +Done: + (void)KeRestoreFloatingPointState(&saveData); + return ntStatus; +} + +/*++ +Routine Description: + This function read the wave header file and compare the header info with the + stream info. Currently we are using only number of channel, sampling frequency + and bits per sample as the primary parameters for the wave file to compare against + stream params. If the params don't match we return success but streams zeros. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::ReadHeaderAndFillBuffer() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + ntStatus = FileReadHeader(); + + if(NT_SUCCESS(ntStatus)) + { + if (m_WaveHeader.numChannels != m_ChannelCount || + m_WaveHeader.bitsPerSample != m_BitsPerSample || + m_WaveHeader.sampleRate != m_SamplesPerSecond) + { + // If the wave file format don't match we wont treat this as error + // and we will stream zeros. So we return from here and will not read the + // wave file and wont fill the buffers. + return STATUS_SUCCESS; + } + } + + if (NT_SUCCESS(ntStatus)) + { + // If the wave file format is same as the stream format we will stream the data + // else we will just stream zeros. + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[0]); // Fill the first chunk + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[1]); // Fill the second chunk + // Set the current executed chunk to 1. Once OS finishs the data for the first chunk + // use the currentExecutedChunk to find the next chunk and schedule a workitem to fill the + // data into the next chunk + m_WaveDataQueue.currentExecutedChunk = 1; + } + + return ntStatus; +} + +/*++ +Routine Description: + This function allocates 1 second buffer. + Segments the buffer into multiple (currently two) chunks. Assigns the start pointer and length + for each chunk. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::AllocateBigBuffer() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_WaveDataQueue.pWavData = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_WaveDataQueue.ulLength, + WAVE_DATA_BUFFER_TAG + ); + if (!m_WaveDataQueue.pWavData) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + ULONG chunklLength = m_WaveDataQueue.ulLength / NUM_OF_CHUNK_FOR_FILE_READ; + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + m_WaveDataQueue.sChunkDescriptor[i].pStartAddress = m_WaveDataQueue.pWavData + chunklLength*i; + m_WaveDataQueue.sChunkDescriptor[i].ulChunkLength = chunklLength; + } + } + return ntStatus; +} + +/*++ +Routine Description: + This function opens wave file. + +Arguments: + fileNameString - Name of the wave file + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::OpenWaveFile(PUNICODE_STRING puiFileName) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (NT_SUCCESS(ntStatus) && puiFileName->Buffer != NULL) + { + // Create data file. + InitializeObjectAttributes + ( + &m_objectAttributes, + puiFileName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL + ); + + // Open Wave File + ntStatus = FileOpen(); + } + + return ntStatus; +} + +/*++ +Routine Description: + This function closes wave file handle. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileClose() +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_FileHandle) + { + ntStatus = ZwClose(m_FileHandle); + m_FileHandle = NULL; + } + + return ntStatus; +} + +/*++ +Routine Description: + Reads the wave file file header information + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileReadHeader() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + + ntStatus = ZwReadFile(m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_WaveHeader, + sizeof(WAVEHEADER), + NULL, + NULL); + + return ntStatus; +} + +/*++ +Routine Description: + This function opens wave file. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileOpen() +{ + + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + if (!m_FileHandle) + { + ntStatus = + ZwCreateFile + ( + &m_FileHandle, + GENERIC_READ, + &m_objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + } + + return ntStatus; +} + diff --git a/audio/Acx/Samples/Common/WaveReader.h b/audio/Acx/Samples/Common/WaveReader.h new file mode 100644 index 000000000..08516be79 --- /dev/null +++ b/audio/Acx/Samples/Common/WaveReader.h @@ -0,0 +1,196 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + WaveReader.h + +Abstract: + + Declaration of wave reader for ACX sample drivers. + + +--*/ +#pragma once + +#define _USE_MATH_DEFINES +#include +#include + +#define NUM_OF_CHUNK_FOR_FILE_READ 2 + +class CWaveReader; + +// Wave header structure decleration +typedef CWaveReader *pWaveReader; +typedef struct _WAVEHEADER +{ + BYTE chunkId[4]; + ULONG chunkSize; + BYTE format[4]; + BYTE subChunkId[4]; + ULONG subChunkSize; + WORD audioFormat; + WORD numChannels; + ULONG sampleRate; + ULONG bytesPerSecond; + WORD blockAlign; + WORD bitsPerSample; + BYTE dataChunkId[4]; + ULONG dataSize; +}WAVEHEADER; + +typedef struct _CHUNKDESCRIPTOR +{ + PBYTE pStartAddress; // Starting address of the chunk + ULONG ulChunkLength; // Length of the chunk + bool bIsChunkEmpty; // If the chunk is empty +}CHUNKDESCRIPTOR; +typedef CHUNKDESCRIPTOR *PCHUNKDESCRIPTOR; + +/* + The idea here is to allocate one second long worth of buffer and divide it into NUM_OF_CHUNK_FOR_FILE_READ chunks. + In one file read operation we read and fill one chunk data . The chunk will be emptied every 10 ms by OS. + Once the OS empties one chunk data we schedule a workitem to read and fill next available chunk. +*/ + +typedef struct _WAVEDATAQUEUE +{ + PBYTE pWavData; // Pointer to the temporary buffer for reading one second worth of data from wave file + ULONG ulLength; // length of pWavData in bytes + ULONG ulReadPtr; // current reading position in pWavData in bytes + bool bEofReached; // This will be set once the eof is reached. + WORD currentExecutedChunk; + CHUNKDESCRIPTOR sChunkDescriptor[NUM_OF_CHUNK_FOR_FILE_READ]; +}WAVEDATAQUEUE; +typedef WAVEDATAQUEUE *PWAVEDATAQUEUE; + +// Parameter to workitem. +#include +typedef struct _READWORKER_PARAM { + PIO_WORKITEM WorkItem; // Pointer to the workitem + KEVENT EventDone; // Used for synchronizing a workitem for scheduling. + pWaveReader PtrWaveReader; // pointer to the wavereader class. + PCHUNKDESCRIPTOR PtrChunkDescriptor; // chunk descriptor for the chunk, which needs to be filled after file read +} READWORKER_PARAM; +typedef READWORKER_PARAM *PREADWORKER_PARAM; +#include + +__drv_maxIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; + +// Wave Reader class + +class CWaveReader +{ + +public: + HANDLE m_FileHandle; // Wave File handle. + WORD m_ChannelCount; // Number of Channels for the stream during stream init + WORD m_BitsPerSample; // Number of Bits per sample for the stream during stream init + DWORD m_SamplesPerSecond; // Number of Sample per second for the stream during stream init + bool m_Mute; // Capture Zero buffer if mute + OBJECT_ATTRIBUTES m_objectAttributes; // Used for opening file. + WAVEDATAQUEUE m_WaveDataQueue; // Big buffer data object and its current state + KMUTEX m_FileSync; // Synchronizes file access + WAVEHEADER m_WaveHeader; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CWaveReader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CWaveReader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS Init + ( + _In_ PWAVEFORMATEXTENSIBLE WfExt, + _In_ PUNICODE_STRING puiFileName + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + VOID ReadWaveData + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID SetMute(_In_ bool Value) + { + PAGED_CODE(); + + m_Mute = Value; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void WaitAllWorkItems(); + + // Static allocation totally related to the workitems for reading data from wavefile and putting it to chunk buffer + static PDEVICE_OBJECT m_pDeviceObject; + static PREADWORKER_PARAM m_pWorkItems; + PAGED_CODE_SEG + static NTSTATUS InitializeWorkItems(_In_ PDEVICE_OBJECT DeviceObject); + + __drv_maxIRQL(DISPATCH_LEVEL) + static PREADWORKER_PARAM GetNewWorkItem(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + static VOID DestroyWorkItems(); + +private: + __drv_maxIRQL(DISPATCH_LEVEL) + VOID ReadWavChunk(PCHUNKDESCRIPTOR PtrChunkDescriptor); + + __drv_maxIRQL(DISPATCH_LEVEL) + bool IsAllChunkEmpty(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS OpenWaveFile(PUNICODE_STRING puiFileName); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileClose(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileReadHeader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileOpen(); + + __drv_maxIRQL(DISPATCH_LEVEL) + VOID CopyDataFromRingBuffer + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS AllocateBigBuffer(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ReadHeaderAndFillBuffer(); + + friend IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; +}; + + diff --git a/audio/Acx/Samples/Inc/AudioFormats.h b/audio/Acx/Samples/Inc/AudioFormats.h new file mode 100644 index 000000000..8a48b1cfa --- /dev/null +++ b/audio/Acx/Samples/Inc/AudioFormats.h @@ -0,0 +1,959 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + AudioFormats.h + +Abstract: + + Contains Audio formats supported for the ACX Sample Drivers + +Environment: + + Kernel mode + +--*/ + +#pragma once + +#define NOBITMAP +#include + +// +// Basic-testing formats. +// +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 176400, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 352800, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 384000, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm192000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 44100, + 88200, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 48000, + 96000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 16000, + 32000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm32000c2 = +{ // 14 + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 32000, + 128000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm88200c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 88200, + 352800, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm96000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 96000, + 384000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm24000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 24000, + 96000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 16000, + 64000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm8000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 8000, + 16000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm11025c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 11025, + 22050, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm22050c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 22050, + 44100, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm24000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 24000, + 48000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm32000c1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 32000, + 64000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +// +// Definitions of HDMI specific audio formats. +// + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyDigital = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyDigitalPlus = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyDigitalPlusAtmos = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS_ATMOS), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS_ATMOS) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMlp = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMlpSurround = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1_SURROUND, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsSurround = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsHD = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsHDLowBitRate = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsXE1 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E1), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E1) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DtsXE2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E2), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DTSX_E2) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMAT20 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT20), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT20) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE DolbyMAT21 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT21), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 8, + 192000, + 3072000, + 16, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_7POINT1, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MAT21) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 176400, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +// No Mask version is used for 2ch Capture, where the mask is not meaningful +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 192000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c4nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 4, + 16000, + 128000, + 8, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; diff --git a/audio/Acx/Samples/Inc/cpp_utils.h b/audio/Acx/Samples/Inc/cpp_utils.h new file mode 100644 index 000000000..f4ed62207 --- /dev/null +++ b/audio/Acx/Samples/Inc/cpp_utils.h @@ -0,0 +1,71 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + cpp_utils.h + +Abstract: + + Contains CPP utilities + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// Function scope_exit instantiates scope_exit object +// Constructor accepts lamda as parameter. +// Assign tasks in lamdba to be executed on scope exit. +template +auto scope_exit(F f) +{ + class scope_exit + { + public: + scope_exit(F f) : + _f{ f } + { + } + + ~scope_exit() + { + if (_call) + { + _f(); + } + } + + // Ensures the scope_exit lambda will not be called + void release() + { + _call = false; + } + + // Executes the scope_exit lambda immediately if not yet run; ensures it will not run again + void reset() + { + if (_call) + { + _f(); + _call = false; + } + } + + private: + F _f; + bool _call = true; + }; + + return scope_exit{ f }; +}; + diff --git a/audio/Acx/Samples/Shared/Public.h b/audio/Acx/Samples/Shared/Public.h new file mode 100644 index 000000000..f1e9da3bd --- /dev/null +++ b/audio/Acx/Samples/Shared/Public.h @@ -0,0 +1,342 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + Public.h + +Abstract: + + Contains structure definitions and function prototypes for the driver + that are public. + +Environment: + + Kernel mode + +--*/ + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include "Trace.h" + +#include +#include + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +// Number of msec for idle timeout. +#define IDLE_POWER_TIMEOUT 5000 + +extern RECORDER_LOG g_AudioDspLog; +extern RECORDER_LOG g_AudioDspMcLog; + +// +// Define CODEC device context. +// +typedef struct _CODEC_DEVICE_CONTEXT { + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + WDF_TRI_STATE ExcludeD3Cold; +} CODEC_DEVICE_CONTEXT, * PCODEC_DEVICE_CONTEXT; + +// +// Codec driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD Codec_EvtBusDeviceAdd; +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_UNLOAD AudioCodecDriverUnload; + +// +// Codec device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE Codec_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Codec_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY Codec_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT Codec_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Codec_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_DEVICE_CONTEXT, GetCodecDeviceContext) + +// +// Define DSP device context. +// +typedef struct _DSP_DEVICE_CONTEXT { + ACXCIRCUIT Speaker; + ACXCIRCUIT MicArray; + ACXCIRCUIT SpeakerHp; + ACXCIRCUIT MicrophoneHp; + ACXCIRCUIT HDMI; + WDF_TRI_STATE ExcludeD3Cold; +} DSP_DEVICE_CONTEXT, * PDSP_DEVICE_CONTEXT; + +// +// Dsp driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD Dsp_EvtBusDeviceAdd; +EVT_WDF_DRIVER_UNLOAD AudioDspDriverUnload; + +// +// Dsp device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE Dsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Dsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY Dsp_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT Dsp_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Dsp_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_DEVICE_CONTEXT, GetDspDeviceContext) + +// +// Define CODECMC (multicircuit codec) device context. +// +typedef struct _CODECMC_DEVICE_CONTEXT +{ + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + ACXCOMPOSITETEMPLATE Composite[2]; + ULONG refComposite[2]; + WDF_TRI_STATE ExcludeD3Cold; +} CODECMC_DEVICE_CONTEXT, *PCODECMC_DEVICE_CONTEXT; + +// +// Multicircuit codec driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD CodecMc_EvtBusDeviceAdd; +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_UNLOAD AudioCodecMcDriverUnload; + +// +// Multicircuit codec device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE CodecMc_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE CodecMc_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY CodecMc_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT CodecMc_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecMc_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODECMC_DEVICE_CONTEXT, GetCodecMcDeviceContext) + +// +// Composite type definition used in multicircuit codec. +// +typedef enum +{ + CompositeType_RENDER, + CompositeType_CAPTURE +} CompositeType; + +// +// Define DSPMC (multicircuit dsp) device context. +// +typedef struct _DSPMC_DEVICE_CONTEXT +{ + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + WDF_TRI_STATE ExcludeD3Cold; +} DSPMC_DEVICE_CONTEXT, *PDSPMC_DEVICE_CONTEXT; + +// +// Multicircuit dsp driver prototypes. +// +EVT_WDF_DRIVER_DEVICE_ADD DspMc_EvtBusDeviceAdd; +EVT_WDF_DRIVER_UNLOAD AudioDspMcDriverUnload; + +// +// Multicircuit dsp device callbacks. +// +EVT_WDF_DEVICE_PREPARE_HARDWARE DspMc_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE DspMc_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY DspMc_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT DspMc_EvtDeviceD0Exit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspMc_EvtDeviceContextCleanup; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSPMC_DEVICE_CONTEXT, GetDspMcDeviceContext) + +// Factory circuit callbacks for multicircuit dsp. +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE RenderMCDsp_EvtAcxFactoryCircuitCreateCircuitDevice; +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUIT RenderMCDsp_EvtAcxFactoryCircuitCreateCircuit; + +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE CaptureMCDsp_EvtAcxFactoryCircuitCreateCircuitDevice; +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUIT CaptureMCDsp_EvtAcxFactoryCircuitCreateCircuit; + + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +// Used to store the registry settings path for the driver: +extern UNICODE_STRING g_RegistryPath; + +// Driver tag name: +extern ULONG DeviceDriverTag; + +// The idle timeout in msec for power policy structure: +extern ULONG IdleTimeoutMsec; + +#define DECLARE_CONST_ACXOBJECTBAG_MULTICIRCUIT_SAMPLE_PROPERTY_NAME(name) \ + DECLARE_CONST_UNICODE_STRING(name, L"mc_" #name) + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath +); + +PAGED_CODE_SEG +NTSTATUS +Codec_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +Dsp_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +CodecMc_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +DspMc_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +Speaker_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName, + _In_ BOOLEAN IsHeadphones +); + +PAGED_CODE_SEG +NTSTATUS +MicArray_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +MicrophoneHp_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ GUID MicCustomName, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +SpeakerHp_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +HDMI_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ GUID ComponentGuid, + _In_ UNICODE_STRING CircuitName +); + +PAGED_CODE_SEG +NTSTATUS +RenderMC_AddStaticRender( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri +); + +PAGED_CODE_SEG +NTSTATUS +CaptureMC_AddStaticCapture( + _In_ WDFDEVICE Device, + _In_ const GUID * ComponentGuid, + _In_ const GUID * MicCustomName, + _In_ const UNICODE_STRING * CircuitName, + _In_ const UNICODE_STRING * Uri +); + +PAGED_CODE_SEG +NTSTATUS +CodecC_CircuitCleanup( + _In_ ACXCIRCUIT Device +); + +PAGED_CODE_SEG +NTSTATUS +MicArray_CircuitCleanup( + _In_ ACXCIRCUIT Device +); + +PAGED_CODE_SEG +NTSTATUS +CaptureMCDsp_CircuitCleanup( + _In_ ACXCIRCUIT Device +); + +PAGED_CODE_SEG +NTSTATUS +DspMc_AddFactoryCircuit( + _In_ WDFDRIVER Driver, + _In_ WDFDEVICE Device +); + +NTSTATUS +CodecMc_AddRenderComposites(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS +CodecMc_AddCaptureComposites(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS +CodecMc_AddComposites(_In_ WDFDEVICE Device, _In_ CompositeType compositeType); + +NTSTATUS +CodecMc_RemoveComposites(_In_ WDFDEVICE Device); diff --git a/audio/Acx/Samples/Shared/Trace.h b/audio/Acx/Samples/Shared/Trace.h new file mode 100644 index 000000000..01478bfca --- /dev/null +++ b/audio/Acx/Samples/Shared/Trace.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + +Trace.h + +--*/ + +#pragma once + +#include +#include // For TRACE_LEVEL definitions + +#define WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE) +#define WPP_ERROR_PARTITION_SIZE (WPP_TOTAL_BUFFER_SIZE/4) + +// {1945C417-844C-48C6-9BCE-3AA2113A2B69} +#define WPP_CONTROL_GUIDS \ +WPP_DEFINE_CONTROL_GUID(DrvLogger,(1945C417,844C,48C6,9BCE,3AA2113A2B69), \ + WPP_DEFINE_BIT(FLAG_DEVICE_ALL) /* bit 0 = 0x00000001 */ \ + WPP_DEFINE_BIT(FLAG_FUNCTION) /* bit 1 = 0x00000002 */ \ + WPP_DEFINE_BIT(FLAG_INFO) /* bit 2 = 0x00000004 */ \ + WPP_DEFINE_BIT(FLAG_PNP) /* bit 3 = 0x00000008 */ \ + WPP_DEFINE_BIT(FLAG_POWER) /* bit 4 = 0x00000010 */ \ + WPP_DEFINE_BIT(FLAG_STREAM) /* bit 5 = 0x00000020 */ \ + WPP_DEFINE_BIT(FLAG_INIT) /* bit 6 = 0x00000040 */ \ + WPP_DEFINE_BIT(FLAG_DDI) /* bit 7 = 0x00000080 */ \ + WPP_DEFINE_BIT(FLAG_GENERIC) /* bit 8 = 0x00000100 */ \ + ) + +#include "trace_macros.h" diff --git a/audio/simpleaudiosample/Source/Filters/Filters.vcxproj b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj index 82fd07dc2..1bc012e00 100644 --- a/audio/simpleaudiosample/Source/Filters/Filters.vcxproj +++ b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj @@ -38,7 +38,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -62,7 +62,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -70,7 +70,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -78,7 +78,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary diff --git a/audio/simpleaudiosample/Source/Inc/Inc.vcxproj b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj index ab768d842..14fce7b39 100644 --- a/audio/simpleaudiosample/Source/Inc/Inc.vcxproj +++ b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj @@ -38,7 +38,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -62,7 +62,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -70,7 +70,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -78,7 +78,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary diff --git a/audio/simpleaudiosample/Source/Main/Main.vcxproj b/audio/simpleaudiosample/Source/Main/Main.vcxproj index a68d02422..be92b9d45 100644 --- a/audio/simpleaudiosample/Source/Main/Main.vcxproj +++ b/audio/simpleaudiosample/Source/Main/Main.vcxproj @@ -40,7 +40,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -48,7 +48,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -56,7 +56,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -64,7 +64,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -72,7 +72,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -80,7 +80,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver diff --git a/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx index a63bb0ba8..d0835f1f1 100644 Binary files a/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx and b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx differ diff --git a/audio/simpleaudiosample/Source/Main/adapter.cpp b/audio/simpleaudiosample/Source/Main/adapter.cpp index 105f7fdea..a66ee5a29 100644 --- a/audio/simpleaudiosample/Source/Main/adapter.cpp +++ b/audio/simpleaudiosample/Source/Main/adapter.cpp @@ -45,10 +45,10 @@ _Dispatch_type_(IRP_MJ_PNP) DRIVER_DISPATCH PnpHandler; // -// Rendering streams are saved to a file by default. Use the registry value -// DoNotCreateDataFiles (DWORD) > 0 to override this default. +// Rendering streams are not saved to a file by default. Use the registry value +// DoNotCreateDataFiles (DWORD) = 0 to override this default. // -DWORD g_DoNotCreateDataFiles = 0; // default is off. +DWORD g_DoNotCreateDataFiles = 1; // default is off. DWORD g_DisableToneGenerator = 0; // default is to generate tones. UNICODE_STRING g_RegistryPath; // This is used to store the registry settings path for the driver @@ -59,6 +59,8 @@ UNICODE_STRING g_RegistryPath; // This is used to store the registry settin #pragma code_seg("PAGE") void ReleaseRegistryStringBuffer() { + PAGED_CODE(); + if (g_RegistryPath.Buffer != NULL) { ExFreePool(g_RegistryPath.Buffer); @@ -192,7 +194,8 @@ Routine Description: { NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DoNotCreateDataFiles", &g_DoNotCreateDataFiles, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DoNotCreateDataFiles, sizeof(ULONG)}, @@ -202,29 +205,27 @@ Routine Description: DPF(D_TERSE, ("[GetRegistrySettings]")); - PAGED_CODE(); - - RtlInitUnicodeString(¶metersPath, NULL); + PAGED_CODE(); + UNREFERENCED_PARAMETER(RegistryPath); - parametersPath.MaximumLength = - RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(WCHAR); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - parametersPath.Buffer = (PWCH) ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINADAPTER_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, RegistryPath->Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); - - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); if (!NT_SUCCESS(ntStatus)) { @@ -240,10 +241,10 @@ Routine Description: DPF(D_VERBOSE, ("DoNotCreateDataFiles: %u", g_DoNotCreateDataFiles)); DPF(D_VERBOSE, ("DisableToneGenerator: %u", g_DisableToneGenerator)); - // - // Cleanup. - // - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return STATUS_SUCCESS; } @@ -292,15 +293,6 @@ Return Value: ntStatus, DPF(D_ERROR, ("Registry path copy error 0x%x", ntStatus)), Done); - - // - // Get registry configuration. - // - ntStatus = GetRegistrySettings(RegistryPathName); - IF_FAILED_ACTION_JUMP( - ntStatus, - DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), - Done); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); // @@ -323,6 +315,15 @@ Return Value: DPF(D_ERROR, ("WdfDriverCreate failed, 0x%x", ntStatus)), Done); + // + // Get registry configuration. + // + ntStatus = GetRegistrySettings(RegistryPathName); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), + Done); + // // Tell the class driver to initialize the driver. // diff --git a/audio/simpleaudiosample/Source/Main/common.cpp b/audio/simpleaudiosample/Source/Main/common.cpp index 8843d3a4d..457bdb17a 100644 --- a/audio/simpleaudiosample/Source/Main/common.cpp +++ b/audio/simpleaudiosample/Source/Main/common.cpp @@ -2547,6 +2547,7 @@ Return Value: return ntStatus; } +#pragma code_seg("PAGE") NTSTATUS CopyRegistryKey(HANDLE _hSourceKey, HANDLE _hDestinationKey, BOOL _bOverwrite = FALSE) /*++ @@ -2686,7 +2687,7 @@ Return Value: return ntStatus; } - +#pragma code_seg("PAGE") NTSTATUS CAdapterCommon::MigrateDeviceInterfaceTemplateParameters ( _In_ PUNICODE_STRING SymbolicLinkName, @@ -2729,6 +2730,8 @@ Return Value: UNICODE_STRING TemplateSymbolicLinkName; UNICODE_STRING referenceString; + PAGED_CODE(); + RtlInitUnicodeString(&TemplateSymbolicLinkName, NULL); RtlInitUnicodeString(&referenceString, TemplateReferenceString); diff --git a/audio/simpleaudiosample/Source/Main/minwavertstream.cpp b/audio/simpleaudiosample/Source/Main/minwavertstream.cpp index 27289a0ec..c189c9390 100644 --- a/audio/simpleaudiosample/Source/Main/minwavertstream.cpp +++ b/audio/simpleaudiosample/Source/Main/minwavertstream.cpp @@ -108,8 +108,8 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() PAGED_CODE(); NTSTATUS ntStatus; - UNICODE_STRING parametersPath; - + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureToneFrequency", &m_ulHostCaptureToneFrequency, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_ulHostCaptureToneFrequency, sizeof(DWORD) }, @@ -119,30 +119,37 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() { NULL, 0, NULL, NULL, 0, NULL, 0 } }; - RtlInitUnicodeString(¶metersPath, NULL); - - // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string. - parametersPath.MaximumLength = - g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus)); + // + // Don't return error because we will operate with default values. + // + } - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return ntStatus; } diff --git a/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj index 0a71bf42c..710bf7480 100644 --- a/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj +++ b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj @@ -38,7 +38,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -62,7 +62,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -70,7 +70,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -78,7 +78,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary diff --git a/audio/simpleaudiosample/Source/Utilities/savedata.cpp b/audio/simpleaudiosample/Source/Utilities/savedata.cpp index 7b2a11e9c..02c3f602e 100644 --- a/audio/simpleaudiosample/Source/Utilities/savedata.cpp +++ b/audio/simpleaudiosample/Source/Utilities/savedata.cpp @@ -44,8 +44,9 @@ Module Name: #define DEFAULT_FRAME_SIZE PAGE_SIZE * 4 #define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT -#define DEFAULT_FILE_NAME L"\\DosDevices\\C:\\STREAM" -#define OSDATA_FILE_NAME L"\\DosDevices\\O:\\STREAM" +#define DEFAULT_FILE_FOLDER1 L"\\DriverData\\Audio_Samples" +#define DEFAULT_FILE_FOLDER2 L"\\DriverData\\Audio_Samples\\SimpleAudioSample" +#define DEFAULT_FILE_NAME L"\\DriverData\\Audio_Samples\\SimpleAudioSample\\STREAM" #define OFFLOAD_FILE_NAME L"OFFLOAD" #define HOST_FILE_NAME L"HOST" @@ -444,59 +445,86 @@ CSaveData::Initialize { PAGED_CODE(); - NTSTATUS ntStatus = STATUS_SUCCESS; - WCHAR szTemp[MAX_PATH]; - size_t cLen; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING osDataVolumeString; - HANDLE osDataFileHandle = NULL; - IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen = 0; + IO_STATUS_BLOCK ioStatusBlock = {0}; + HANDLE fileHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fileName; DPF_ENTER(("[CSaveData::Initialize]")); m_ulStreamId++; - // Probe if OSData volume exists. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_probe.txt", OSDATA_FILE_NAME); - RtlInitUnicodeString(&osDataVolumeString, szTemp); - InitializeObjectAttributes - ( - &objectAttributes, - &osDataVolumeString, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL - ); - - ntStatus = - ZwCreateFile - ( - &osDataFileHandle, - GENERIC_WRITE | SYNCHRONIZE, + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER1); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_OVERWRITE_IF, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, - 0 - ); + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER2); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + } + } + if (NT_SUCCESS(ntStatus)) { - ZwClose(osDataFileHandle); + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, HOST_FILE_NAME, m_ulStreamId); + m_FileName.Length = 0; + ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); } - // Allocate data file name. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", NT_SUCCESS(ntStatus) ? OSDATA_FILE_NAME : DEFAULT_FILE_NAME, HOST_FILE_NAME, m_ulStreamId); - m_FileName.Length = 0; - ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); if (NT_SUCCESS(ntStatus)) { - m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL + m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL m_FileName.Buffer = (PWSTR) ExAllocatePool2 ( @@ -574,7 +602,7 @@ CSaveData::Initialize ( &m_objectAttributes, &m_FileName, - OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); diff --git a/audio/sysvad/APO/AecApo/AecApo.h b/audio/sysvad/APO/AecApo/AecApo.h index a62b69ce0..7c96314de 100644 --- a/audio/sysvad/APO/AecApo/AecApo.h +++ b/audio/sysvad/APO/AecApo/AecApo.h @@ -99,13 +99,8 @@ DECLARE_PROTECT_FINAL_CONSTRUCT() ) override; // IAudioSystemEffects3 - STDMETHODIMP GetControllableSystemEffectsList(_Outptr_result_buffer_maybenull_(*numEffects) AUDIO_SYSTEMEFFECT** effects, _Out_ UINT* numEffects, _In_opt_ HANDLE event) override - { - UNREFERENCED_PARAMETER(effects); - UNREFERENCED_PARAMETER(numEffects); - UNREFERENCED_PARAMETER(event); - return S_OK; - } + STDMETHOD(GetControllableSystemEffectsList)( + _Outptr_result_buffer_maybenull_(*numEffects) AUDIO_SYSTEMEFFECT** effects, _Out_ UINT* numEffects, _In_opt_ HANDLE event) override; STDMETHODIMP SetAudioSystemEffectState(GUID, AUDIO_SYSTEMEFFECT_STATE) override {return S_OK;} diff --git a/audio/sysvad/APO/AecApo/AecApo.vcxproj b/audio/sysvad/APO/AecApo/AecApo.vcxproj index f40ce919b..3602ba64c 100644 --- a/audio/sysvad/APO/AecApo/AecApo.vcxproj +++ b/audio/sysvad/APO/AecApo/AecApo.vcxproj @@ -39,7 +39,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -48,7 +48,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -57,7 +57,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -66,7 +66,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -75,7 +75,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -84,7 +84,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -350,4 +350,4 @@ - \ No newline at end of file + diff --git a/audio/sysvad/APO/AecApo/AecApoMfx.cpp b/audio/sysvad/APO/AecApo/AecApoMfx.cpp index 21f2c20de..0c16f3485 100644 --- a/audio/sysvad/APO/AecApo/AecApoMfx.cpp +++ b/audio/sysvad/APO/AecApo/AecApoMfx.cpp @@ -375,6 +375,39 @@ STDMETHODIMP CAecApoMFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffe return S_OK; } +STDMETHODIMP CAecApoMFX::GetControllableSystemEffectsList(_Outptr_result_buffer_maybenull_(*numEffects) AUDIO_SYSTEMEFFECT** effects, _Out_ UINT* numEffects, _In_opt_ HANDLE event) +{ + UNREFERENCED_PARAMETER(event); + + RETURN_HR_IF_NULL(E_POINTER, effects); + RETURN_HR_IF_NULL(E_POINTER, numEffects); + + *effects = nullptr; + *numEffects = 0; + + if (m_audioSignalProcessingMode == AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS) + { + // Return the list of effects implemented by this APO for COMMUNICATIONS processing mode + static const GUID effectsList[] = {AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION}; + + wil::unique_cotaskmem_array_ptr audioEffects( + static_cast(CoTaskMemAlloc(ARRAYSIZE(effectsList) * sizeof(AUDIO_SYSTEMEFFECT))), ARRAYSIZE(effectsList)); + RETURN_IF_NULL_ALLOC(audioEffects.get()); + + for (UINT i = 0; i < ARRAYSIZE(effectsList); i++) + { + audioEffects[i].id = effectsList[i]; + audioEffects[i].state = AUDIO_SYSTEMEFFECT_STATE_ON; + audioEffects[i].canSetState = FALSE; + } + + *numEffects = (UINT)audioEffects.size(); + *effects = audioEffects.release(); + } + + return S_OK; +} + HRESULT IsInputFormatSupportedForAec(IAudioMediaType* pMediaType, BOOL * pSupported) { ASSERT_NONREALTIME(); diff --git a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj index ecdaf3213..86f493956 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj +++ b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj @@ -39,7 +39,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -48,7 +48,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -57,7 +57,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -66,7 +66,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -75,7 +75,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -84,7 +84,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 diff --git a/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp b/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp index 8778b2528..af67571b8 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp +++ b/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp @@ -292,7 +292,7 @@ STDMETHODIMP CDelayAPOMFX::LockForProcess(UINT32 u32NumInputConnections, // // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important - m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); + m_pf32DelayBuffer.Allocate((size_t) GetSamplesPerFrame() * m_nDelayFrames); WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); if (nullptr == m_pf32DelayBuffer) { @@ -430,7 +430,8 @@ HRESULT CDelayAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // @@ -1165,4 +1166,4 @@ HRESULT CDelayAPOMFX::CheckCustomFormats(IAudioMediaType *pRequestedFormat) } return hResult; -} \ No newline at end of file +} diff --git a/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp b/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp index 81594bb7e..67ae2788f 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp +++ b/audio/sysvad/APO/DelayAPO/DelayAPOSFX.cpp @@ -241,7 +241,7 @@ STDMETHODIMP CDelayAPOSFX::LockForProcess(UINT32 u32NumInputConnections, // // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important - m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); + m_pf32DelayBuffer.Allocate((size_t) GetSamplesPerFrame() * m_nDelayFrames); WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); if (nullptr == m_pf32DelayBuffer) @@ -388,7 +388,8 @@ HRESULT CDelayAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // diff --git a/audio/sysvad/APO/KWSApo/KWSApo.vcxproj b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj index b34e03d92..592686b44 100644 --- a/audio/sysvad/APO/KWSApo/KWSApo.vcxproj +++ b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj @@ -39,7 +39,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -48,7 +48,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -57,7 +57,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -66,7 +66,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -75,7 +75,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -84,7 +84,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -352,4 +352,4 @@ - \ No newline at end of file + diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.h b/audio/sysvad/APO/SwapAPO/SwapAPO.h index aeb9d2591..d169d9dba 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.h +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.h @@ -195,7 +195,8 @@ DECLARE_PROTECT_FINAL_CONSTRUCT() public: LONG m_fEnableSwapMFX; GUID m_AudioProcessingMode; - wil::com_ptr_nothrow m_device; + wil::com_ptr_nothrow m_deviceTopologyMMDevice; + wil::com_ptr_nothrow m_audioEndpoint; CComPtr m_spAPOSystemEffectsProperties; CComPtr m_spEnumerator; static const CRegAPOProperties<1> sm_RegProperties; // registration properties @@ -315,7 +316,8 @@ DECLARE_PROTECT_FINAL_CONSTRUCT() LONG m_fEnableSwapSFX; LONG m_fEnableDelaySFX; GUID m_AudioProcessingMode; - wil::com_ptr_nothrow m_device; + wil::com_ptr_nothrow m_deviceTopologyMMDevice; + wil::com_ptr_nothrow m_audioEndpoint; CComPtr m_spAPOSystemEffectsProperties; CComPtr m_spEnumerator; static const CRegAPOProperties<1> sm_RegProperties; // registration properties diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj index 2a26307ec..8ceee8eac 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj @@ -1,4 +1,4 @@ - + @@ -39,7 +39,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -48,7 +48,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -57,7 +57,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -66,7 +66,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -75,7 +75,7 @@ Windows10 False - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -84,7 +84,7 @@ Windows10 True - Universal + Windows Driver false WindowsApplicationForDrivers10.0 @@ -427,4 +427,4 @@ - \ No newline at end of file + diff --git a/audio/sysvad/APO/SwapAPO/swapapomfx.cpp b/audio/sysvad/APO/SwapAPO/swapapomfx.cpp index 7a772a071..b05b15686 100644 --- a/audio/sysvad/APO/SwapAPO/swapapomfx.cpp +++ b/audio/sysvad/APO/SwapAPO/swapapomfx.cpp @@ -458,10 +458,38 @@ HRESULT CSwapAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) // that need to run at a real-time priority. The work queue ID is used with the Rtwq APIs. hr = apoRtQueueService->GetRealTimeWorkQueue(&m_queueId); IF_FAILED_JUMP(hr, Exit); - + // Windows should pass a valid collection. ATLASSERT(papoSysFxInit3->pDeviceCollection != nullptr); IF_TRUE_ACTION_JUMP(papoSysFxInit3->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + + // Use IMMDevice to activate IAudioSystemEffectsPropertyStore that contains the default, user and + // volatile settings. + IMMDeviceCollection* deviceCollection = reinterpret_cast(pbyData)->pDeviceCollection; + UINT32 numDevices; + // Get the endpoint on which this APO has been created + // (It is the last device in the device collection) + hr = deviceCollection->GetCount(&numDevices); + IF_FAILED_JUMP(hr, Exit); + + hr = numDevices > 0 ? S_OK : E_UNEXPECTED; + IF_FAILED_JUMP(hr, Exit); + + hr = deviceCollection->Item(numDevices - 1, &m_audioEndpoint); + IF_FAILED_JUMP(hr, Exit); + + wil::unique_prop_variant activationParam; + hr = InitPropVariantFromCLSID(SWAP_APO_SFX_CONTEXT, &activationParam); + IF_FAILED_JUMP(hr, Exit); + + wil::com_ptr_nothrow effectsPropertyStore; + hr = m_audioEndpoint->Activate(__uuidof(effectsPropertyStore), CLSCTX_ALL, &activationParam, effectsPropertyStore.put_void()); + IF_FAILED_JUMP(hr, Exit); + + // This is where an APO might want to open the volatile or default property stores as well + // Use STGM_READWRITE if IPropertyStore::SetValue is needed. + hr = effectsPropertyStore->OpenUserPropertyStore(STGM_READ, m_userStore.put()); + IF_FAILED_JUMP(hr, Exit); // Save the processing mode being initialized. processingMode = papoSysFxInit3->AudioProcessingMode; @@ -523,7 +551,8 @@ HRESULT CSwapAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // @@ -755,7 +784,7 @@ HRESULT CSwapAPOMFX::SetAudioSystemEffectState(GUID effectId, AUDIO_SYSTEMEFFECT if (oldState != effectInfo.state) { SetEvent(m_hEffectsChangedEvent); - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOMFX::SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); } m_EffectsLock.Leave(); @@ -772,8 +801,6 @@ HRESULT CSwapAPOMFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO *apoNotifications = nullptr; *count = 0; - RETURN_HR_IF_NULL(E_FAIL, m_device); - // Let the OS know what notifications we are interested in by returning an array of // APO_NOTIFICATION_DESCRIPTORs. constexpr DWORD numDescriptors = 1; @@ -785,7 +812,7 @@ HRESULT CSwapAPOMFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO // Our APO wants to get notified when a endpoint property changes on the audio endpoint. apoNotificationDescriptors[0].type = APO_NOTIFICATION_TYPE_ENDPOINT_PROPERTY_CHANGE; - (void)m_device.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); + (void)m_audioEndpoint.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); *apoNotifications = apoNotificationDescriptors.release(); *count = numDescriptors; @@ -811,7 +838,7 @@ void CSwapAPOMFX::HandleNotification(APO_NOTIFICATION *apoNotification) {PKEY_Endpoint_Enable_Channel_Swap_MFX, &m_fEnableSwapMFX}, }; - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOMFX::HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); for (int i = 0; i < ARRAYSIZE(controls); i++) { @@ -847,11 +874,11 @@ HRESULT CSwapAPOMFX::ProprietaryCommunicationWithDriver(IMMDeviceCollection *pDe } // Get the target IMMDevice - hr = pDeviceCollection->Item(nSoftwareIoDeviceInCollection, &m_device); + hr = pDeviceCollection->Item(nSoftwareIoDeviceInCollection, &m_deviceTopologyMMDevice); IF_FAILED_JUMP(hr, Exit); // Instantiate a device topology instance - hr = m_device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); IF_FAILED_JUMP(hr, Exit); // retrieve connect instance @@ -859,7 +886,7 @@ HRESULT CSwapAPOMFX::ProprietaryCommunicationWithDriver(IMMDeviceCollection *pDe IF_FAILED_JUMP(hr, Exit); // activate IKsControl on the IMMDevice - hr = m_device->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, NULL, (void**)&spKsControl); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, NULL, (void**)&spKsControl); IF_FAILED_JUMP(hr, Exit); // get KS pin id diff --git a/audio/sysvad/APO/SwapAPO/swapaposfx.cpp b/audio/sysvad/APO/SwapAPO/swapaposfx.cpp index 8483d8dfa..ef418f758 100644 --- a/audio/sysvad/APO/SwapAPO/swapaposfx.cpp +++ b/audio/sysvad/APO/SwapAPO/swapaposfx.cpp @@ -297,48 +297,48 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) hr = papoSysFxInit3->pServiceProvider->QueryService(SID_AudioProcessingObjectLoggingService, IID_PPV_ARGS(&m_apoLoggingService)); IF_FAILED_JUMP(hr, Exit); - // SampleApo supports the new IAudioSystemEffects3 interface so it will receive APOInitSystemEffects3 + // SampleApo supports the new IAudioSystemEffects3 interface so it will receive APOInitSystemEffects3 // in pbyData if the audio driver has declared support for this. + // Windows should pass a valid collection. + ATLASSERT(papoSysFxInit3->pDeviceCollection != nullptr); + IF_TRUE_ACTION_JUMP(papoSysFxInit3->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + // Use IMMDevice to activate IAudioSystemEffectsPropertyStore that contains the default, user and // volatile settings. IMMDeviceCollection* deviceCollection = reinterpret_cast(pbyData)->pDeviceCollection; - if (deviceCollection != nullptr) - { - UINT32 numDevices; - wil::com_ptr_nothrow endpoint; + UINT32 numDevices; + // Get the endpoint on which this APO has been created + // (It is the last device in the device collection) + hr = deviceCollection->GetCount(&numDevices); + IF_FAILED_JUMP(hr, Exit); - // Get the endpoint on which this APO has been created - // (It is the last device in the device collection) - if (SUCCEEDED(deviceCollection->GetCount(&numDevices)) && numDevices > 0 && - SUCCEEDED(deviceCollection->Item(numDevices - 1, &endpoint))) - { - wil::unique_prop_variant activationParam; - hr = InitPropVariantFromCLSID(SWAP_APO_SFX_CONTEXT, &activationParam); - IF_FAILED_JUMP(hr, Exit); - - wil::com_ptr_nothrow effectsPropertyStore; - hr = endpoint->Activate(__uuidof(effectsPropertyStore), CLSCTX_ALL, &activationParam, effectsPropertyStore.put_void()); - IF_FAILED_JUMP(hr, Exit); - - // This is where an APO might want to open the volatile or default property stores as well - // Use STGM_READWRITE if IPropertyStore::SetValue is needed. - hr = effectsPropertyStore->OpenUserPropertyStore(STGM_READ, m_userStore.put()); - IF_FAILED_JUMP(hr, Exit); - } - } + hr = numDevices > 0 ? S_OK : E_UNEXPECTED; + IF_FAILED_JUMP(hr, Exit); - // Windows should pass a valid collection. - ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr); - IF_TRUE_ACTION_JUMP(papoSysFxInit3->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + hr = deviceCollection->Item(numDevices - 1, &m_audioEndpoint); + IF_FAILED_JUMP(hr, Exit); + + wil::unique_prop_variant activationParam; + hr = InitPropVariantFromCLSID(SWAP_APO_SFX_CONTEXT, &activationParam); + IF_FAILED_JUMP(hr, Exit); + + wil::com_ptr_nothrow effectsPropertyStore; + hr = m_audioEndpoint->Activate(__uuidof(effectsPropertyStore), CLSCTX_ALL, &activationParam, effectsPropertyStore.put_void()); + IF_FAILED_JUMP(hr, Exit); + + // This is where an APO might want to open the volatile or default property stores as well + // Use STGM_READWRITE if IPropertyStore::SetValue is needed. + hr = effectsPropertyStore->OpenUserPropertyStore(STGM_READ, m_userStore.put()); + IF_FAILED_JUMP(hr, Exit); // Get the IDeviceTopology and IConnector interfaces to communicate with this // APO's counterpart audio driver. This can be used for any proprietary // communication. - hr = papoSysFxInit3->pDeviceCollection->Item(papoSysFxInit3->nSoftwareIoDeviceInCollection, &m_device); + hr = papoSysFxInit3->pDeviceCollection->Item(papoSysFxInit3->nSoftwareIoDeviceInCollection, &m_deviceTopologyMMDevice); IF_FAILED_JUMP(hr, Exit); - hr = m_device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); IF_FAILED_JUMP(hr, Exit); hr = spMyDeviceTopology->GetConnector(papoSysFxInit3->nSoftwareIoConnectorIndex, &spMyConnector); @@ -365,10 +365,10 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) // Get the IDeviceTopology and IConnector interfaces to communicate with this // APO's counterpart audio driver. This can be used for any proprietary // communication. - hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &m_device); + hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &m_deviceTopologyMMDevice); IF_FAILED_JUMP(hr, Exit); - hr = m_device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + hr = m_deviceTopologyMMDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); IF_FAILED_JUMP(hr, Exit); hr = spMyDeviceTopology->GetConnector(papoSysFxInit2->nSoftwareIoConnectorIndex, &spMyConnector); @@ -407,7 +407,8 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS && processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH && processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA && - processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit); + processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE && + processingMode != AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION), hr = E_INVALIDARG, Exit); m_AudioProcessingMode = processingMode; // @@ -640,7 +641,7 @@ HRESULT CSwapAPOSFX::SetAudioSystemEffectState(GUID effectId, AUDIO_SYSTEMEFFECT if (oldState != effectInfo.state) { SetEvent(m_hEffectsChangedEvent); - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOSFX::SetAudioSystemEffectState - effect: " GUID_FORMAT_STRING L", state: %i", effectInfo.id, effectInfo.state); } m_EffectsLock.Leave(); @@ -733,8 +734,6 @@ HRESULT CSwapAPOSFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO *apoNotifications = nullptr; *count = 0; - RETURN_HR_IF_NULL(E_FAIL, m_device); - // Let the OS know what notifications we are interested in by returning an array of // APO_NOTIFICATION_DESCRIPTORs. constexpr DWORD numDescriptors = 1; @@ -746,7 +745,7 @@ HRESULT CSwapAPOSFX::GetApoNotificationRegistrationInfo(_Out_writes_(*count) APO // Our APO wants to get notified when a endpoint property changes on the audio endpoint. apoNotificationDescriptors[0].type = APO_NOTIFICATION_TYPE_ENDPOINT_PROPERTY_CHANGE; - (void)m_device.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); + (void)m_audioEndpoint.query_to(&apoNotificationDescriptors[0].audioEndpointPropertyChange.device); *apoNotifications = apoNotificationDescriptors.release(); *count = numDescriptors; @@ -772,7 +771,7 @@ void CSwapAPOSFX::HandleNotification(APO_NOTIFICATION *apoNotification) {PKEY_Endpoint_Enable_Channel_Swap_SFX, &m_fEnableSwapSFX}, }; - m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); + m_apoLoggingService->ApoLog(APO_LOG_LEVEL_INFO, L"CSwapAPOSFX::HandleNotification - pkey: " GUID_FORMAT_STRING L" %d", GUID_FORMAT_ARGS(apoNotification->audioEndpointPropertyChange.propertyKey.fmtid), apoNotification->audioEndpointPropertyChange.propertyKey.pid); for (int i = 0; i < ARRAYSIZE(controls); i++) { diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj index 5b819cf34..4c59e3c1a 100644 --- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj +++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj @@ -38,7 +38,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -62,7 +62,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -70,7 +70,7 @@ Windows10 False - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -78,7 +78,7 @@ Windows10 True - Universal + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary diff --git a/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp index 34477606e..8c3979f21 100644 --- a/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp +++ b/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp @@ -57,9 +57,9 @@ Called at PASSIVE_LEVEL } KSAUDIOENGINE_DESCRIPTOR, *PKSAUDIOENGINE_DESCRIPTOR; The fields are defined as: - nHostPinId – The ID of the pin factory connected to the audio engine node that is intended for host processed audio data. This is the pin factory on which a software audio engine will run. - nOffloadPinId – The ID of the pin factory connected to the audio engine node that is intended for offloaded streams. - nLoopbackPinId – The ID of the pin factory connected to the audio engine that is intended for supplying a post-mix loopback or reference stream. + nHostPinId - The ID of the pin factory connected to the audio engine node that is intended for host processed audio data. This is the pin factory on which a software audio engine will run. + nOffloadPinId - The ID of the pin factory connected to the audio engine node that is intended for offloaded streams. + nLoopbackPinId - The ID of the pin factory connected to the audio engine that is intended for supplying a post-mix loopback or reference stream. All pin ids need to be unique for each audio engine node. diff --git a/audio/sysvad/EndpointsCommon/mintopo.cpp b/audio/sysvad/EndpointsCommon/mintopo.cpp index c1e4bc14b..9fb2cc21e 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.cpp +++ b/audio/sysvad/EndpointsCommon/mintopo.cpp @@ -578,6 +578,100 @@ Return Value: return ntStatus; } +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopology::PropertyHandlerJackDescription3 +( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions, + _In_ ULONG ConfigId +) +/*++ + +Routine Description: + + Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION3 ) + +Arguments: + + PropertyRequest - + cJackDescriptions - # of elements in the jack descriptions array. + JackDescriptions - Array of jack descriptions pointers. + ConfigId - Current endpoint config id + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(PropertyRequest); + + DPF_ENTER(("[PropertyHandlerJackDescription3]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + ULONG nPinId = (ULONG)-1; + + if (PropertyRequest->InstanceSize >= sizeof(ULONG)) + { + nPinId = *(PULONG(PropertyRequest->Instance)); + + if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL)) + { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = + PropertyHandler_BasicSupport + ( + PropertyRequest, + KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET, + VT_ILLEGAL + ); + } + else + { + ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION3); + + if (PropertyRequest->ValueSize == 0) + { + PropertyRequest->ValueSize = cbNeeded; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (PropertyRequest->ValueSize < cbNeeded) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else + { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value; + PKSJACK_DESCRIPTION3 pDesc = (PKSJACK_DESCRIPTION3)(pMI+1); + + pMI->Size = cbNeeded; + pMI->Count = 1; + + RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION3)); + + // + // hardware config id + // + pDesc->ConfigId = ConfigId; + + ntStatus = STATUS_SUCCESS; + } + } + } + } + } + + return ntStatus; +} + //============================================================================= #pragma code_seg("PAGE") NTSTATUS diff --git a/audio/sysvad/EndpointsCommon/mintopo.h b/audio/sysvad/EndpointsCommon/mintopo.h index 596e13b1a..f0bae44d3 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.h +++ b/audio/sysvad/EndpointsCommon/mintopo.h @@ -100,6 +100,14 @@ class CMiniportTopology : _In_ DWORD JackCapabilities ); + NTSTATUS PropertyHandlerJackDescription3 + ( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions, + _In_ ULONG ConfigId + ); + NTSTATUS PropertyHandlerAudioResourceGroup ( _In_ PPCPROPERTY_REQUEST PropertyRequest diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp index bd81c110f..c6b8e8c3c 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.cpp +++ b/audio/sysvad/EndpointsCommon/minwavert.cpp @@ -3452,7 +3452,8 @@ NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() PAGED_CODE(); NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength @@ -3461,30 +3462,37 @@ NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() { NULL, 0, NULL, NULL, 0, NULL, 0 } }; - RtlInitUnicodeString(¶metersPath, NULL); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string. - parametersPath.MaximumLength = - g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR); - - parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus)); + // + // Don't return error because we will operate with default values. + // + } - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return ntStatus; } diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp index 08467e057..adea0c824 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp +++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp @@ -121,7 +121,8 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() PAGED_CODE(); NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength @@ -136,30 +137,37 @@ NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings() { NULL, 0, NULL, NULL, 0, NULL, 0 } }; - RtlInitUnicodeString(¶metersPath, NULL); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string. - parametersPath.MaximumLength = - g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR); - - parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + if (!NT_SUCCESS(ntStatus)) + { + DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus)); + // + // Don't return error because we will operate with default values. + // + } - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return ntStatus; } diff --git a/audio/sysvad/EndpointsCommon/speakertopo.cpp b/audio/sysvad/EndpointsCommon/speakertopo.cpp index fba720368..002b11747 100644 --- a/audio/sysvad/EndpointsCommon/speakertopo.cpp +++ b/audio/sysvad/EndpointsCommon/speakertopo.cpp @@ -75,6 +75,15 @@ Return Value: 0 // jack capabilities ); } + else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION3) + { + ntStatus = pMiniport->PropertyHandlerJackDescription3( + PropertyRequest, + ARRAYSIZE(SpeakerJackDescriptions), + SpeakerJackDescriptions, + 42 // jack config id + ); + } } else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioResourceManagement)) { diff --git a/audio/sysvad/EndpointsCommon/speakertoptable.h b/audio/sysvad/EndpointsCommon/speakertoptable.h index 3d31d7a46..ea3890f7c 100644 --- a/audio/sysvad/EndpointsCommon/speakertoptable.h +++ b/audio/sysvad/EndpointsCommon/speakertoptable.h @@ -141,6 +141,13 @@ PCPROPERTY_ITEM PropertiesSpeakerTopoFilter[] = KSPROPERTY_TYPE_BASICSUPPORT, PropertyHandler_SpeakerTopoFilter }, + { + &KSPROPSETID_Jack, + KSPROPERTY_JACK_DESCRIPTION3, + KSPROPERTY_TYPE_GET | + KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_SpeakerTopoFilter + }, { &KSPROPSETID_AudioResourceManagement, KSPROPERTY_AUDIORESOURCEMANAGEMENT_RESOURCEGROUP, diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj index d16752018..7151399e4 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj @@ -1,4 +1,4 @@ - + @@ -39,7 +39,7 @@ Windows10 False - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -47,7 +47,7 @@ Windows10 False - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -55,7 +55,7 @@ Windows10 True - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -63,7 +63,7 @@ Windows10 True - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -71,7 +71,7 @@ Windows10 False - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -79,7 +79,7 @@ Windows10 True - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary diff --git a/audio/sysvad/adapter.cpp b/audio/sysvad/adapter.cpp index ef48e5f4f..0f44c593f 100644 --- a/audio/sysvad/adapter.cpp +++ b/audio/sysvad/adapter.cpp @@ -246,10 +246,10 @@ _Dispatch_type_(IRP_MJ_PNP) DRIVER_DISPATCH PnpHandler; // -// Rendering streams are saved to a file by default. Use the registry value -// DoNotCreateDataFiles (DWORD) > 0 to override this default. +// Rendering streams are not saved to a file by default. Use the registry value +// DoNotCreateDataFiles (DWORD) = 0 to override this default. // -DWORD g_DoNotCreateDataFiles = 0; // default is off. +DWORD g_DoNotCreateDataFiles = 1; // default is off. DWORD g_DisableToneGenerator = 0; // default is to generate tones. UNICODE_STRING g_RegistryPath; // This is used to store the registry settings path for the driver @@ -425,7 +425,8 @@ Routine Description: { NTSTATUS ntStatus; - UNICODE_STRING parametersPath; + PDRIVER_OBJECT DriverObject; + HANDLE DriverKey; RTL_QUERY_REGISTRY_TABLE paramTable[] = { // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DoNotCreateDataFiles", &g_DoNotCreateDataFiles, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DoNotCreateDataFiles, sizeof(ULONG)}, @@ -441,29 +442,27 @@ Routine Description: DPF(D_TERSE, ("[GetRegistrySettings]")); - PAGED_CODE(); - - RtlInitUnicodeString(¶metersPath, NULL); + PAGED_CODE(); + UNREFERENCED_PARAMETER(RegistryPath); - parametersPath.MaximumLength = - RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(WCHAR); + DriverObject = WdfDriverWdmGetDriverObject(WdfGetDriver()); + DriverKey = NULL; + ntStatus = IoOpenDriverRegistryKey(DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &DriverKey); - parametersPath.Buffer = (PWCH) ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINADAPTER_POOLTAG); - if (parametersPath.Buffer == NULL) + if (!NT_SUCCESS(ntStatus)) { - return STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; } - RtlAppendUnicodeToString(¶metersPath, RegistryPath->Buffer); - RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); - - ntStatus = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - parametersPath.Buffer, - ¶mTable[0], - NULL, - NULL - ); + ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PCWSTR) DriverKey, + ¶mTable[0], + NULL, + NULL); if (!NT_SUCCESS(ntStatus)) { @@ -485,10 +484,10 @@ Routine Description: DPF(D_VERBOSE, ("DisableUsbSideband: %u", g_DisableUsbSideband)); #endif // SYSVAD_USB_SIDEBAND - // - // Cleanup. - // - ExFreePool(parametersPath.Buffer); + if (DriverKey) + { + ZwClose(DriverKey); + } return STATUS_SUCCESS; } @@ -537,15 +536,6 @@ Return Value: ntStatus, DPF(D_ERROR, ("Registry path copy error 0x%x", ntStatus)), Done); - - // - // Get registry configuration. - // - ntStatus = GetRegistrySettings(RegistryPathName); - IF_FAILED_ACTION_JUMP( - ntStatus, - DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), - Done); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); // @@ -568,6 +558,15 @@ Return Value: DPF(D_ERROR, ("WdfDriverCreate failed, 0x%x", ntStatus)), Done); + // + // Get registry configuration. + // + ntStatus = GetRegistrySettings(RegistryPathName); + IF_FAILED_ACTION_JUMP( + ntStatus, + DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)), + Done); + // // Tell the class driver to initialize the driver. // diff --git a/audio/sysvad/common.cpp b/audio/sysvad/common.cpp index 9bc3e6446..1334411e5 100644 --- a/audio/sysvad/common.cpp +++ b/audio/sysvad/common.cpp @@ -50,7 +50,6 @@ Module Name: // CSaveData statics //----------------------------------------------------------------------------- -PSAVEWORKER_PARAM CSaveData::m_pWorkItems = NULL; PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL; //============================================================================= // Classes @@ -642,8 +641,6 @@ Return Value: delete m_pHW; m_pHW = NULL; } - - CSaveData::DestroyWorkItems(); SAFE_RELEASE(m_pPortClsEtwHelper); SAFE_RELEASE(m_pServiceGroupWave); @@ -841,8 +838,6 @@ Return Value: // Initialize SaveData class. // CSaveData::SetDeviceObject(DeviceObject); //device object is needed by CSaveData - ntStatus = CSaveData::InitializeWorkItems(DeviceObject); - IF_FAILED_JUMP(ntStatus, Done); Done: return ntStatus; diff --git a/audio/sysvad/savedata.cpp b/audio/sysvad/savedata.cpp index cb5f5cfc7..39789f3b9 100644 --- a/audio/sysvad/savedata.cpp +++ b/audio/sysvad/savedata.cpp @@ -47,12 +47,13 @@ Module Name: #define DEFAULT_FRAME_SIZE PAGE_SIZE * 4 #define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT -#define DEFAULT_FILE_NAME L"\\DosDevices\\C:\\STREAM" -#define OSDATA_FILE_NAME L"\\DosDevices\\O:\\STREAM" +#define DEFAULT_FILE_FOLDER1 L"\\DriverData\\Audio_Samples" +#define DEFAULT_FILE_FOLDER2 L"\\DriverData\\Audio_Samples\\Sysvad" +#define DEFAULT_FILE_NAME L"\\DriverData\\Audio_Samples\\Sysvad\\STREAM" #define OFFLOAD_FILE_NAME L"OFFLOAD" #define HOST_FILE_NAME L"HOST" -#define MAX_WORKER_ITEM_COUNT 15 +#define MAX_WORKER_ITEM_COUNT 8 //============================================================================= // Statics @@ -91,6 +92,7 @@ CSaveData::CSaveData() m_DataHeader.dwData = DATA_TAG; m_DataHeader.dwDataLength = 0; + RtlZeroMemory(&m_FileName, sizeof(m_FileName)); RtlZeroMemory(&m_objectAttributes, sizeof(m_objectAttributes)); } // CSaveData @@ -101,6 +103,12 @@ CSaveData::~CSaveData() DPF_ENTER(("[CSaveData::~CSaveData]")); + // + // All write activity is done at this point (see acquire->stop stream transition). + // Safe to call even if the Initialize function failed. + // + DestroyWorkItems(); + // Update the wave header in data file with real file size. // if(m_pFilePtr) @@ -415,6 +423,7 @@ CSaveData::GetNewWorkItem { LARGE_INTEGER timeOut = { 0 }; NTSTATUS ntStatus; + PSAVEWORKER_PARAM saveWorker = NULL; for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++) { @@ -430,13 +439,16 @@ CSaveData::GetNewWorkItem if (STATUS_SUCCESS == ntStatus) { if (m_pWorkItems[i].WorkItem) - return &(m_pWorkItems[i]); - else - return NULL; + { + saveWorker = &(m_pWorkItems[i]); + KeResetEvent(&saveWorker->EventDone); + break; + } } } - return NULL; + + return saveWorker; } // GetNewWorkItem #pragma code_seg("PAGE") @@ -449,13 +461,13 @@ CSaveData::Initialize { PAGED_CODE(); - NTSTATUS ntStatus = STATUS_SUCCESS; - WCHAR szTemp[MAX_PATH]; - size_t cLen; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING osDataVolumeString; - HANDLE osDataFileHandle = NULL; - IO_STATUS_BLOCK ioStatusBlock; + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen = 0; + IO_STATUS_BLOCK ioStatusBlock = {0}; + HANDLE fileHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING fileName; DPF_ENTER(("[CSaveData::Initialize]")); @@ -468,47 +480,74 @@ CSaveData::Initialize m_ulStreamId++; } - // Probe if OSData volume exists. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_probe.txt", OSDATA_FILE_NAME); - RtlInitUnicodeString(&osDataVolumeString, szTemp); - InitializeObjectAttributes - ( - &objectAttributes, - &osDataVolumeString, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL - ); - - ntStatus = - ZwCreateFile - ( - &osDataFileHandle, - GENERIC_WRITE | SYNCHRONIZE, + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER1); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_OVERWRITE_IF, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, - 0 - ); + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + + RtlInitUnicodeString(&fileName, DEFAULT_FILE_FOLDER2); + InitializeObjectAttributes( + &objectAttributes, + &fileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // Create the folder. + ntStatus = ZwCreateFile( + &fileHandle, + 0, + &objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if (NT_SUCCESS(ntStatus)) + { + ZwClose(fileHandle); + fileHandle = NULL; + } + } + if (NT_SUCCESS(ntStatus)) { - ZwClose(osDataFileHandle); + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : m_ulStreamId); + m_FileName.Length = 0; + ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); } - // Allocate data file name. - // - RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", NT_SUCCESS(ntStatus) ? OSDATA_FILE_NAME : DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : m_ulStreamId); - m_FileName.Length = 0; - ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen); if (NT_SUCCESS(ntStatus)) { - m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL + m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL m_FileName.Buffer = (PWSTR) ExAllocatePool2 ( @@ -572,6 +611,13 @@ CSaveData::Initialize // KeInitializeMutex( &m_FileSync, 1 ) ; + // Allocate work-items. + // + if (NT_SUCCESS(ntStatus)) + { + ntStatus = InitializeWorkItems(m_pDeviceObject); + } + // Open the data file. // if (NT_SUCCESS(ntStatus)) @@ -586,7 +632,7 @@ CSaveData::Initialize ( &m_objectAttributes, &m_FileName, - OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); @@ -896,7 +942,6 @@ CSaveData::SaveFrame pParam->ulFrameNo = ulFrameNo; pParam->ulDataSize = ulDataSize; pParam->pData = m_pDataBuffer + ulFrameNo * m_ulFrameSize; - KeResetEvent(&pParam->EventDone); IoQueueWorkItem(pParam->WorkItem, SaveFrameWorkerCallback, CriticalWorkQueue, (PVOID)pParam); } diff --git a/audio/sysvad/savedata.h b/audio/sysvad/savedata.h index a1525bdab..942210251 100644 --- a/audio/sysvad/savedata.h +++ b/audio/sysvad/savedata.h @@ -98,7 +98,7 @@ class CSaveData static PDEVICE_OBJECT m_pDeviceObject; static ULONG m_ulStreamId; static ULONG m_ulOffloadStreamId; - static PSAVEWORKER_PARAM m_pWorkItems; + PSAVEWORKER_PARAM m_pWorkItems; BOOL m_fWriteDisabled; @@ -108,11 +108,11 @@ class CSaveData CSaveData(); ~CSaveData(); - static NTSTATUS InitializeWorkItems + NTSTATUS InitializeWorkItems ( _In_ PDEVICE_OBJECT DeviceObject ); - static void DestroyWorkItems + void DestroyWorkItems ( void ); @@ -120,7 +120,7 @@ class CSaveData ( _In_ BOOL fDisable ); - static PSAVEWORKER_PARAM GetNewWorkItem + PSAVEWORKER_PARAM GetNewWorkItem ( void ); diff --git a/avstream/avscamera/DMFT/AvsCameraDMFT.cpp b/avstream/avscamera/DMFT/AvsCameraDMFT.cpp new file mode 100644 index 000000000..e12cff652 --- /dev/null +++ b/avstream/avscamera/DMFT/AvsCameraDMFT.cpp @@ -0,0 +1,1311 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// + +#include "stdafx.h" +#ifdef MF_WPP +#include "AvsCameraDMFT.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif +// +// This DeviceMFT is a stripped down implementation of the device MFT Sample present in the sample Repo +// The original DMFT is present at https://github.com/microsoft/Windows-driver-samples/tree/main/avstream/sampledevicemft +// +CMultipinMft::CMultipinMft() +: m_nRefCount( 0 ), + m_InputPinCount( 0 ), + m_OutputPinCount( 0 ), + m_dwWorkQueueId ( MFASYNC_CALLBACK_QUEUE_MULTITHREADED ), + m_lWorkQueuePriority ( 0 ), + m_spAttributes( nullptr ), + m_spSourceTransform( nullptr ), + m_SymbolicLink(nullptr) + +{ + HRESULT hr = S_OK; + ComPtr pAttributes = nullptr; + MFCreateAttributes( &pAttributes, 0 ); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32( MF_TRANSFORM_ASYNC, TRUE ),done); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32( MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE ),done); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32( MF_SA_D3D_AWARE, TRUE ), done); + DMFTCHECKHR_GOTO(pAttributes->SetString( MFT_ENUM_HARDWARE_URL_Attribute, L"SampleMultiPinMft" ),done); + m_spAttributes = pAttributes; +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); +} + +CMultipinMft::~CMultipinMft( ) +{ + m_OutPins.clear(); + SAFE_ARRAYDELETE(m_SymbolicLink); + m_spSourceTransform = nullptr; + +} + +IFACEMETHODIMP_(ULONG) CMultipinMft::AddRef( + void + ) +{ + return InterlockedIncrement(&m_nRefCount); +} + +IFACEMETHODIMP_(ULONG) CMultipinMft::Release( + void + ) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + + if ( uCount == 0 ) + { + delete this; + } + return uCount; +} + +IFACEMETHODIMP CMultipinMft::QueryInterface( + _In_ REFIID iid, + _COM_Outptr_ void** ppv + ) +{ + + HRESULT hr = S_OK; + *ppv = NULL; + + if ((iid == __uuidof(IMFDeviceTransform)) || (iid == __uuidof(IUnknown))) + { + *ppv = static_cast< IMFDeviceTransform* >(this); + } + else if ( iid == __uuidof( IMFMediaEventGenerator ) ) + { + *ppv = static_cast< IMFMediaEventGenerator* >(this); + } + else if ( iid == __uuidof( IMFShutdown ) ) + { + *ppv = static_cast< IMFShutdown* >( this ); + } + else if ( iid == __uuidof( IKsControl ) ) + { + *ppv = static_cast< IKsControl* >( this ); + } + else if ( iid == __uuidof( IMFRealTimeClientEx ) ) + { + *ppv = static_cast< IMFRealTimeClientEx* >( this ); + } + else + { + hr = E_NOINTERFACE; + goto done; + } + AddRef(); +done: + return hr; +} + +/*++ + Description: + This function is the entry point of the transform + The following things may be initialized here + 1) Query for MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL on the attributes supplied + 2) From the IUnknown acquired get the IMFTransform interface. + 3) Get the stream count.. The output streams are of consequence to the tranform. + The input streams should correspond to the output streams exposed by the source transform + acquired from the Attributes supplied. + 4) Get the IKSControl which is used to send KSPROPERTIES, KSEVENTS and KSMETHODS to the driver for the filer level. Store it in your filter class + 5) Get the OutPutStreamAttributes for the output pins of the source transform. This can further be used to QI and acquire + the IKSControl related to the specific pin. This can be used to send PIN level KSPROPERTIES, EVENTS and METHODS to the pins + 6) Create the output pins + +--*/ + +IFACEMETHODIMP CMultipinMft::InitializeTransform ( + _In_ IMFAttributes *pAttributes + ) +{ + HRESULT hr = S_OK; + ComPtr spFilterUnk = nullptr; + DWORD *pcInputStreams = NULL, *pcOutputStreams = NULL; + DWORD inputStreams = 0; + DWORD outputStreams = 0; + GUID* outGuids = NULL; + GUID streamCategory = GUID_NULL; + ULONG ulOutPinIndex = 0; + UINT32 uiSymLinkLen = 0; + DMFTCHECKNULL_GOTO( pAttributes, done, E_INVALIDARG ); + // + // The attribute passed with MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL is the source transform. This generally represents a filter + // This needs to be stored so that we know the device properties. We cache it. We query for the IKSControl which is used to send + // controls to the driver. + // + DMFTCHECKHR_GOTO( pAttributes->GetUnknown( MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL,IID_PPV_ARGS( &spFilterUnk ) ),done ); + + if (SUCCEEDED(pAttributes->GetStringLength(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &uiSymLinkLen))) // Not available prior to RS5 + { + m_SymbolicLink = new (std::nothrow) WCHAR[++uiSymLinkLen]; + DMFTCHECKNULL_GOTO(m_SymbolicLink, done, E_OUTOFMEMORY); + DMFTCHECKHR_GOTO(pAttributes->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, m_SymbolicLink, uiSymLinkLen, &uiSymLinkLen), done); + } + + DMFTCHECKHR_GOTO( spFilterUnk.As( &m_spSourceTransform ), done ); + + DMFTCHECKHR_GOTO( m_spSourceTransform.As( &m_spIkscontrol ), done ); + + DMFTCHECKHR_GOTO(m_spSourceTransform->GetStreamCount(&inputStreams, &outputStreams), done); + + spFilterUnk = nullptr; + + // + //The number of input pins created by the device transform should match the pins exposed by + //the source transform i.e. outputStreams from SourceTransform or DevProxy = Input pins of the Device MFT + // + + if ( inputStreams > 0 || outputStreams > 0 ) + { + pcInputStreams = new (std::nothrow) DWORD[ inputStreams ]; + DMFTCHECKNULL_GOTO( pcInputStreams, done, E_OUTOFMEMORY); + + pcOutputStreams = new (std::nothrow) DWORD[ outputStreams ]; + DMFTCHECKNULL_GOTO( pcOutputStreams, done, E_OUTOFMEMORY ); + + DMFTCHECKHR_GOTO( m_spSourceTransform->GetStreamIDs( inputStreams, pcInputStreams, + outputStreams, + pcOutputStreams ),done ); + + for ( ULONG ulIndex = 0; ulIndex < outputStreams; ulIndex++ ) + { + ComPtr spInAttributes; + ComPtr spInPin; + + DMFTCHECKHR_GOTO(m_spSourceTransform->GetOutputStreamAttributes(ulIndex, &spInAttributes),done); + spInPin = new (std::nothrow) CInPin(spInAttributes.Get(), ulIndex, this); + DMFTCHECKNULL_GOTO(spInPin.Get(), done, E_OUTOFMEMORY); + + hr = ExceptionBoundary([&]() + { + m_InPins.push_back(spInPin.Get()); + }); + DMFTCHECKHR_GOTO(hr, done); + DMFTCHECKHR_GOTO(spInPin->Init(m_spSourceTransform.Get()), done); + } + + // + // Create one on one mapping + // + for (ULONG ulIndex = 0; ulIndex < m_InPins.size(); ulIndex++) + { + + ComPtr spInPin = (CInPin*)m_InPins[ulIndex].Get(); + + if (spInPin.Get()) + { + ComPtr spOutPin; + ComPtr spKscontrol; + GUID pinGuid = GUID_NULL; + UINT32 uiFrameSourceType = 0; + + DMFTCHECKHR_GOTO(spInPin.As(&spKscontrol), done); // Grab the IKSControl off the input pin + DMFTCHECKHR_GOTO(spInPin->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &pinGuid), done); // Get the Stream Category. Advertise on the output pin + + + spOutPin = new (std::nothrow) COutPin( + ulIndex, + this, + spKscontrol.Get()); // Create the output pin + DMFTCHECKNULL_GOTO(spOutPin.Get(), done, E_OUTOFMEMORY); + + DMFTCHECKHR_GOTO(spOutPin->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, pinGuid), done); // Advertise the Stream category to the Pipeline + DMFTCHECKHR_GOTO(spOutPin->SetUINT32(MF_DEVICESTREAM_STREAM_ID, ulIndex), done); + if (SUCCEEDED(spInPin->GetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, &uiFrameSourceType))) + { + DMFTCHECKHR_GOTO(spOutPin->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, uiFrameSourceType), done); + } + + hr = BridgeInputPinOutputPin(spInPin.Get(), spOutPin.Get()); + if (SUCCEEDED(hr)) + { + DMFTCHECKHR_GOTO(ExceptionBoundary([&]() + { + m_OutPins.push_back(spOutPin.Get()); + }), done); + ulOutPinIndex++; + } + DMFTCHECKHR_GOTO(hr, done); + } + } + + } + + m_InputPinCount = ULONG ( m_InPins.size() ); + m_OutputPinCount = ULONG ( m_OutPins.size() ); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!",hr,hr); + + if ( pcInputStreams ) + { + delete[ ] ( pcInputStreams ); + } + if ( pcOutputStreams ) + { + delete[ ] ( pcOutputStreams ); + } + if ( outGuids ) + { + delete [] ( outGuids ); + } + if ( FAILED( hr ) ) + { + //Release the pins and the resources acquired + m_InPins.clear(); + m_OutPins.clear(); + // + // Simply clear the custom pins since the input pins must have deleted the pin + // + m_spSourceTransform = nullptr; + m_spIkscontrol = nullptr; + } + return hr; +} + + +IFACEMETHODIMP CMultipinMft::SetWorkQueueEx( + _In_ DWORD dwWorkQueueId, + _In_ LONG lWorkItemBasePriority + ) +/*++ + Description: + + Implements IMFRealTimeClientEx::SetWorkQueueEx function + +--*/ +{ + CAutoLock lock( m_critSec ); + // + // Cache the WorkQueuId and WorkItemBasePriority. This is called once soon after the device MFT is initialized + // + m_dwWorkQueueId = dwWorkQueueId; + m_lWorkQueuePriority = lWorkItemBasePriority; + // Set it on the pins + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_InPins.size(); dwIndex++) + { + m_InPins[dwIndex]->SetWorkQueue(dwWorkQueueId); + } + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_OutPins.size(); dwIndex++) + { + m_OutPins[dwIndex]->SetWorkQueue(dwWorkQueueId); + } + return S_OK; + +} + +// +// IMFDeviceTransform functions +// +IFACEMETHODIMP CMultipinMft::GetStreamCount( + _Inout_ DWORD *pdwInputStreams, + _Inout_ DWORD *pdwOutputStreams + ) +/*++ + Description: Implements IMFTransform::GetStreamCount function +--*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + DMFTCHECKNULL_GOTO(pdwInputStreams, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(pdwOutputStreams, done, E_INVALIDARG); + *pdwInputStreams = m_InputPinCount; + *pdwOutputStreams = m_OutputPinCount; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); +done: + return hr; +} + +// +//Doesn't strictly conform to the GetStreamIDs on IMFTransform Interface! +// +IFACEMETHODIMP CMultipinMft::GetStreamIDs( + _In_ DWORD dwInputIDArraySize, + _When_(dwInputIDArraySize >= m_InputPinCount, _Out_writes_(dwInputIDArraySize)) DWORD* pdwInputIDs, + _In_ DWORD dwOutputIDArraySize, + _When_(dwOutputIDArraySize >= m_OutputPinCount && (pdwInputIDs && (dwInputIDArraySize > 0)), + _Out_writes_(dwOutputIDArraySize)) _On_failure_(_Valid_) DWORD* pdwOutputIDs + ) +/*++ + Description: + Implements IMFTransform::GetStreamIDs function +--*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + if ( ( dwInputIDArraySize < m_InputPinCount ) && ( dwOutputIDArraySize < m_OutputPinCount ) ) + { + hr = MF_E_BUFFERTOOSMALL; + goto done; + } + + if ( dwInputIDArraySize ) + { + DMFTCHECKNULL_GOTO( pdwInputIDs, done, E_POINTER ); + for ( DWORD dwIndex = 0; dwIndex < ((dwInputIDArraySize > m_InputPinCount) ? m_InputPinCount: + dwInputIDArraySize); dwIndex++ ) + { + pdwInputIDs[ dwIndex ] = ( m_InPins[dwIndex] )->streamId(); + } + } + + if ( dwOutputIDArraySize ) + { + DMFTCHECKNULL_GOTO( pdwOutputIDs, done, E_POINTER ); + for ( DWORD dwIndex = 0; dwIndex < ((dwOutputIDArraySize > m_OutputPinCount)? m_OutputPinCount: + dwOutputIDArraySize); dwIndex++ ) + { + pdwOutputIDs[ dwIndex ] = (m_OutPins[ dwIndex ])->streamId(); + } + } +done: + return hr; +} + +/*++ +Name: CMultipinMft::GetInputAvailableType +Description: +Implements IMFTransform::GetInputAvailableType function. This function +gets the media type supported by the specified stream based on the +index dwTypeIndex. +--*/ +IFACEMETHODIMP CMultipinMft::GetInputAvailableType( + _In_ DWORD dwInputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppMediaType + ) +{ + HRESULT hr = S_OK; + + ComPtr spiPin = GetInPin( dwInputStreamID ); + DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO( spiPin, done, MF_E_INVALIDSTREAMNUMBER ); + + *ppMediaType = nullptr; + + hr = spiPin->GetOutputAvailableType( dwTypeIndex,ppMediaType ); + + if (FAILED(hr)) + { + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin: %d Index: %d exiting %!HRESULT!", + dwInputStreamID, + dwTypeIndex, + hr); + } + +done: + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetOutputAvailableType( + _In_ DWORD dwOutputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppMediaType + ) +/*++ + Description: + + Implements IMFTransform::GetOutputAvailableType function. This function + gets the media type supported by the specified stream based on the + index dwTypeIndex. + +--*/ +{ + HRESULT hr = S_OK; + CAutoLock Lock(m_critSec); + + ComPtr spoPin = GetOutPin( dwOutputStreamID ); + + DMFTCHECKNULL_GOTO( spoPin.Get(), done, MF_E_INVALIDSTREAMNUMBER ); + DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); + + *ppMediaType = nullptr; + + hr = spoPin->GetOutputAvailableType( dwTypeIndex, ppMediaType ); + + if ( FAILED( hr ) ) + { + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin: %d Index: %d exiting %!HRESULT!", + dwOutputStreamID, + dwTypeIndex, + hr ); + } + +done: + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetInputCurrentType( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFMediaType** ppMediaType + ) +/*++ + Description: + Implements IMFTransform::GetInputCurrentType function. This function + returns the current media type set on the specified stream. +--*/ +{ + // + // The input current types will not come to this transform. + // The outputs of this transform matter. The DTM manages the + // output of this transform and the inptuts of the source transform + // + UNREFERENCED_PARAMETER(dwInputStreamID); + UNREFERENCED_PARAMETER(ppMediaType); + return S_OK; +} + +IFACEMETHODIMP CMultipinMft::GetOutputCurrentType( + _In_ DWORD dwOutputStreamID, + _Out_ IMFMediaType** ppMediaType + ) +/*++ + Description: + + Implements IMFTransform::GetOutputCurrentType function. This function + returns the current media type set on the specified stream. + +--*/ +{ + HRESULT hr = S_OK; + ComPtr spoPin; + CAutoLock lock( m_critSec ); + + DMFTCHECKNULL_GOTO( ppMediaType, done, E_INVALIDARG ); + + *ppMediaType = nullptr; + + spoPin = GetOutPin( dwOutputStreamID ); + + DMFTCHECKNULL_GOTO(spoPin, done, MF_E_INVALIDSTREAMNUMBER ); + + DMFTCHECKHR_GOTO(spoPin->getMediaType( ppMediaType ),done ); + + DMFTCHECKNULL_GOTO( *ppMediaType, done, MF_E_TRANSFORM_TYPE_NOT_SET ); + +done: + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); + return hr; +} + + +IFACEMETHODIMP CMultipinMft::ProcessEvent( + _In_ DWORD dwInputStreamID, + _In_ IMFMediaEvent* pEvent + ) + /*++ + Description: + + Implements IMFTransform::ProcessEvent function. This function + processes events that come to the MFT. + + --*/ +{ + UNREFERENCED_PARAMETER(dwInputStreamID); + UNREFERENCED_PARAMETER(pEvent); + return S_OK; +} + + + +IFACEMETHODIMP CMultipinMft::ProcessMessage( + _In_ MFT_MESSAGE_TYPE eMessage, + _In_ ULONG_PTR ulParam + ) +/*++ + Description: + + Implements IMFTransform::ProcessMessage function. This function + processes messages coming to the MFT. + +--*/ +{ + HRESULT hr = S_OK; + + UNREFERENCED_PARAMETER(ulParam); + + CAutoLock _lock( m_critSec ); + + switch ( eMessage ) + { + case MFT_MESSAGE_COMMAND_FLUSH: + // + // This is MFT wide flush.. Flush all output pins + // + (VOID)FlushAllStreams(); + break; + case MFT_MESSAGE_COMMAND_DRAIN: + // + // There is no draining for Device MFT. Just kept here for reference + // + break; + case MFT_MESSAGE_NOTIFY_START_OF_STREAM: + // + // No op for device MFTs + // + break; + case MFT_MESSAGE_SET_D3D_MANAGER: + { + if ( ulParam ) + { + ComPtr< IDirect3DDeviceManager9 > spD3D9Manager; + ComPtr< IMFDXGIDeviceManager > spDXGIManager; + + hr = ( ( IUnknown* ) ulParam )->QueryInterface( IID_PPV_ARGS( &spD3D9Manager ) ); + if ( SUCCEEDED( hr ) ) + { + m_spDeviceManagerUnk = ( IUnknown* )ulParam; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! IDirect3DDeviceManager9 %p, is passed", spD3D9Manager.Get() ); + } + else + { + hr = ( ( IUnknown* ) ulParam )->QueryInterface( IID_PPV_ARGS( &spDXGIManager ) ); + if ( SUCCEEDED(hr) ) + { + m_spDeviceManagerUnk = (IUnknown*)ulParam; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! IMFDXGIDeviceManager %p, is passed", spDXGIManager.Get()); + } + } + } + else + { + m_spDeviceManagerUnk = nullptr; + hr = S_OK; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC!IDirect3DDeviceManager9 was not passed in"); + } + // + // set it on the pins. Can happen anytime + // + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_InPins.size(); dwIndex++) + { + m_InPins[dwIndex]->SetD3DManager(m_spDeviceManagerUnk.Get()); + } + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_OutPins.size(); dwIndex++) + { + m_OutPins[dwIndex]->SetD3DManager(m_spDeviceManagerUnk.Get()); + } + } + break; + case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING: + { + SetStreamingState( DeviceStreamState_Run ); + } + break; + case MFT_MESSAGE_NOTIFY_END_STREAMING: + { + SetStreamingState(DeviceStreamState_Stop); + } + break; + case MFT_MESSAGE_NOTIFY_END_OF_STREAM: + { + SetStreamingState(DeviceStreamState_Stop); + } + break; + default: + ; + } + + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); + return hr; +} + +IFACEMETHODIMP CMultipinMft::ProcessInput( + _In_ DWORD dwInputStreamID, + _In_ IMFSample* pSample, + _In_ DWORD dwFlags + ) +/*++ + Description: + + Implements IMFTransform::ProcessInput function.This function is called + when the sourcetransform has input to feed. the pins will try to deliver the + samples to the active output pins conencted. if none are connected then just + returns the sample back to the source transform + +--*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER( dwFlags ); + CAutoLock lock(m_critSec); + + ComPtr spInPin = GetInPin( dwInputStreamID ); + DMFTCHECKNULL_GOTO(spInPin, done, MF_E_INVALIDSTREAMNUMBER); + + if ( !IsStreaming() ) + { + goto done; + } + + DMFTCHECKHR_GOTO(spInPin->SendSample( pSample ), done ); +done: + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); + // + //@@@@ README : There is a bug in the sample that the device transform manager which manages the + // device MFT does not release the sample after passing it to Device MFT in processInput like it should. The + // Device MFT therefore unfortunately has to make sure that the sample that leaves processoutput has a reference count of 1 + // + SAFE_RELEASE(pSample); + return hr; + +} + +IFACEMETHODIMP CMultipinMft::ProcessOutput( + _In_ DWORD dwFlags, + _In_ DWORD cOutputBufferCount, + _Inout_updates_(cOutputBufferCount) MFT_OUTPUT_DATA_BUFFER *pOutputSamples, + _Out_ DWORD *pdwStatus +) +/*++ +Description: + +Implements IMFTransform::ProcessOutput function. This is called by the DTM when +the DT indicates it has samples to give. The DTM will send enough MFT_OUTPUT_DATA_BUFFER +pointers to be filled up as is the number of output pins available. The DT should traverse its +output pins and populate the corresponding MFT_OUTPUT_DATA_BUFFER with the samples available + +--*/ +{ + HRESULT hr = S_OK; + BOOL gotOne = false; + ComPtr spOpin; + UNREFERENCED_PARAMETER( dwFlags ); + + if (cOutputBufferCount > m_OutputPinCount ) + { + DMFTCHECKHR_GOTO( E_INVALIDARG, done ); + } + *pdwStatus = 0; + + for ( DWORD i = 0; i < cOutputBufferCount; i++ ) + { + DWORD dwStreamID = pOutputSamples[i].dwStreamID; + { + CAutoLock _lock(m_critSec); + spOpin = nullptr; + spOpin = GetOutPin(dwStreamID); + GUID pinGuid = GUID_NULL; + DMFTCHECKNULL_GOTO(spOpin.Get(), done, E_INVALIDARG); + } + if ( SUCCEEDED(spOpin->ProcessOutput( dwFlags, &pOutputSamples[i], + pdwStatus ) ) ) + { + if (pOutputSamples[i].pSample) + { + ProcessMetadata(pOutputSamples[i].pSample); + } + gotOne = true; + } + } + if (gotOne) + { + hr = S_OK; + } + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetInputStreamAttributes( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFAttributes** ppAttributes + ) +/*++ + Description: + + Implements IMFTransform::GetInputStreamAttributes function. This function + gets the specified input stream's attributes. + +--*/ +{ + HRESULT hr = S_OK; + ComPtr spIPin; + CAutoLock Lock(m_critSec); + + DMFTCHECKNULL_GOTO( ppAttributes, done, E_INVALIDARG ); + *ppAttributes = nullptr; + + spIPin = GetInPin( dwInputStreamID ); + + DMFTCHECKNULL_GOTO(spIPin, done, E_INVALIDARG ); + + hr = spIPin->getPinAttributes(ppAttributes); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetOutputStreamAttributes( + _In_ DWORD dwOutputStreamID, + _Out_ IMFAttributes** ppAttributes + ) +/*++ + Description: + + Implements IMFTransform::GetOutputStreamAttributes function. This function + gets the specified output stream's attributes. + +--*/ +{ + HRESULT hr = S_OK; + ComPtr spoPin; + CAutoLock Lock(m_critSec); + + DMFTCHECKNULL_GOTO(ppAttributes, done, E_INVALIDARG); + + *ppAttributes = nullptr; + + spoPin = GetOutPin(dwOutputStreamID); + + DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG ); + + DMFTCHECKHR_GOTO(spoPin->getPinAttributes(ppAttributes), done ); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +_Requires_no_locks_held_ +IFACEMETHODIMP CMultipinMft::SetInputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::SetInputStreamState function. + Sets the input stream state. + + The control lock is not taken here. The lock is taken for operations on + output pins. This operation is a result of the DT notifying the DTM that + output pin change has resulted in the need for the input to be changed. In + this case the DTM sends a getpreferredinputstate and then this call + + --*/ +{ + HRESULT hr = S_OK; + ComPtr spiPin = GetInPin(dwStreamID); + CAutoLock Lock(m_critSec); + + DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER); + + DMFTCHECKHR_GOTO(spiPin->SetInputStreamState(pMediaType, value, dwFlags),done); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetInputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *value + ) +{ + HRESULT hr = S_OK; + ComPtr piPin = GetInPin(dwStreamID); + + DMFTCHECKNULL_GOTO(piPin, done, MF_E_INVALIDSTREAMNUMBER); + + *value = piPin->GetState(); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + + +IFACEMETHODIMP CMultipinMft::SetOutputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState state, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::SetOutputStreamState function. + Sets the output stream state. This is called whenever the stream + is selected or deslected i.e. started or stopped. + + The control lock taken here and this operation should be atomic. + This function should check the input pins connected to the output pin + switch off the state of the input pin. Check if any other Pin connected + to the input pin is in a conflicting state with the state requested on this + output pin. Accordinly it calculates the media type to be set on the input pin + and the state to transition into. It then might recreate the other output pins + connected to it + --*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwFlags); + CAutoLock Lock(m_critSec); + + DMFTCHECKHR_GOTO(ChangeMediaTypeEx(dwStreamID, pMediaType, state),done); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetOutputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *pState + ) + /*++ + Description: + + Implements IMFdeviceTransform::GetOutputStreamState function. + Gets the output stream state. + Called by the DTM to checks states. Atomic operation. needs a lock + --*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + + ComPtr spoPin = GetOutPin(dwStreamID); + DMFTCHECKNULL_GOTO(pState, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(spoPin, done, MF_E_INVALIDSTREAMNUMBER); + *pState = spoPin->GetState(); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::GetInputStreamPreferredState( + _In_ DWORD dwStreamID, + _Inout_ DeviceStreamState *value, + _Outptr_opt_result_maybenull_ IMFMediaType **ppMediaType + ) + /*++ + Description: + + Implements IMFdeviceTransform::GetInputStreamPreferredState function. + Gets the preferred state and the media type to be set on the input pin. + The lock is not held as this will always be called only when we notify + DTM to call us. We notify DTM only from the context on operations + happening on the output pin + --*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + ComPtr spiPin = GetInPin(dwStreamID); + DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER); + hr = spiPin->GetInputStreamPreferredState(value, ppMediaType); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::FlushInputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::FlushInputStream function. + --*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwStreamIndex); + UNREFERENCED_PARAMETER(dwFlags); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP CMultipinMft::FlushOutputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::FlushOutputStream function. + Called by the DTM to flush streams + --*/ +{ + + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwFlags); + CAutoLock Lock(m_critSec); + + ComPtr spoPin = GetOutPin(dwStreamIndex); + DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG); + DeviceStreamState oldState = spoPin->SetState(DeviceStreamState_Disabled); + DMFTCHECKHR_GOTO(spoPin->FlushQueues(),done); + spoPin->SetState(oldState); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + + +/*++ + Description: + + Called when the Device Transform gets a MFT_MESSAGE_COMMAND_FLUSH. We drain all the queues. + This is called in device source when the source gets end of streaming. + --*/ +IFACEMETHODIMP_(VOID) CMultipinMft::FlushAllStreams( + VOID + ) +{ + DeviceStreamState oldState; + CAutoLock Lock(m_critSec); + for ( DWORD dwIndex = 0, dwSize = (DWORD)m_OutPins.size(); dwIndex < dwSize; dwIndex++ ) + { + ComPtr spoPin = (COutPin *)m_OutPins[dwIndex].Get(); + oldState = spoPin->SetState(DeviceStreamState_Disabled); + spoPin->FlushQueues(); + // + //Restore state + // + spoPin->SetState(oldState); + } +} + +// +// IKsControl interface functions +// +IFACEMETHODIMP CMultipinMft::KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pvPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pulBytesReturned + ) + /*++ + Description: + + Implements IKSProperty::KsProperty function. + used to pass control commands to the driver (generally) + This can be used to intercepted the control to figure out + if it needs to be propogated to the driver or not + --*/ +{ + HRESULT hr = S_OK; + + DMFTCHECKHR_GOTO(m_spIkscontrol->KsProperty(pProperty, + ulPropertyLength, + pvPropertyData, + ulDataLength, + pulBytesReturned),done); +done: + return hr; +} + +IFACEMETHODIMP CMultipinMft::KsMethod( + _In_reads_bytes_(ulPropertyLength) PKSMETHOD pMethod, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pvPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pulBytesReturned + ) + /*++ + Description: + + Implements IKSProperty::KsMethod function. We can trap ksmethod calls here. + --*/ +{ + HRESULT hr = S_OK; + + DMFTCHECKHR_GOTO(m_spIkscontrol->KsMethod( + pMethod, + ulPropertyLength, + pvPropertyData, + ulDataLength, + pulBytesReturned + ), done); +done: + return hr; +} + +IFACEMETHODIMP CMultipinMft::KsEvent( + _In_reads_bytes_(ulEventLength) PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_updates_bytes_opt_(ulDataLength) LPVOID pEventData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ) + /*++ + Description: + + Implements IKSProperty::KsEvent function. + --*/ +{ + + HRESULT hr = S_OK; + // Handle the events here if you want, This sample passes the events to the driver + DMFTCHECKHR_GOTO(m_spIkscontrol->KsEvent(pEvent, + ulEventLength, + pEventData, + ulDataLength, + pBytesReturned), done); +done: + return hr; +} + +// +// HELPER FUNCTIONS +// + +// +// A lock here could mean a deadlock because this will be called when the lock is already held +// in another thread. +// +CInPin* CMultipinMft::GetInPin( + _In_ DWORD dwStreamId +) +{ + CInPin *inPin = NULL; + for (DWORD dwIndex = 0, dwSize = (DWORD)m_InPins.size(); dwIndex < dwSize; dwIndex++) + { + inPin = (CInPin *)m_InPins[dwIndex].Get(); + if (dwStreamId == inPin->streamId()) + { + break; + } + inPin = NULL; + } + return inPin; +} + +COutPin* CMultipinMft::GetOutPin( + _In_ DWORD dwStreamId + ) +{ + COutPin *outPin = NULL; + for ( DWORD dwIndex = 0, dwSize = (DWORD) m_OutPins.size(); dwIndex < dwSize; dwIndex++ ) + { + outPin = ( COutPin * )m_OutPins[ dwIndex ].Get(); + + if ( dwStreamId == outPin->streamId() ) + { + break; + } + + outPin = NULL; + } + + return outPin; +} +_Requires_lock_held_(m_Critsec) +HRESULT CMultipinMft::GetConnectedInpin(_In_ ULONG ulOutpin, _Out_ ULONG &ulInPin) +{ + HRESULT hr = S_OK; + map::iterator it = m_outputPinMap.find(ulOutpin); + if (it != m_outputPinMap.end()) + { + ulInPin = it->second; + } + else + { + hr = MF_E_INVALIDSTREAMNUMBER; + } + return hr; +} + +// +// The Below function changes media type on the pins exposed by device MFT +// +__requires_lock_held(m_critSec) +HRESULT CMultipinMft::ChangeMediaTypeEx( + _In_ ULONG pinId, + _In_opt_ IMFMediaType *pMediaType, + _In_ DeviceStreamState reqState +) +{ + HRESULT hr = S_OK; + ComPtr spoPin = GetOutPin(pinId); + ComPtr spinPin; + DeviceStreamState oldOutPinState, oldInputStreamState, newOutStreamState, newRequestedInPinState; + ComPtr pFullType, pInputMediaType; + ULONG ulInPinId = 0; + DWORD dwFlags = 0; + + + DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG); + + if (pMediaType) + { + if (!spoPin->IsMediaTypeSupported(pMediaType, &pFullType)) + { + DMFTCHECKHR_GOTO(MF_E_INVALIDMEDIATYPE, done); + } + } + + DMFTCHECKHR_GOTO(GetConnectedInpin(pinId, ulInPinId), done); + spinPin = GetInPin(ulInPinId); // Get the input pin + + (VOID)spinPin->getMediaType(&pInputMediaType); + oldInputStreamState = spinPin->SetState(DeviceStreamState_Disabled); // Disable input pin + oldOutPinState = spoPin->SetState(DeviceStreamState_Disabled); // Disable output pin + (void)spoPin->FlushQueues(); // Flush the output queues + (void)spinPin->FlushQueues(); // Flush the input queues + newOutStreamState = pinStateTransition[oldOutPinState][reqState]; // New state needed + + // The Old input and the output pin states should be the same + newRequestedInPinState = newOutStreamState; + + if ((newOutStreamState != oldOutPinState) /*State change*/ + ||((pFullType.Get() != nullptr) && (pInputMediaType.Get()!=nullptr) && (S_OK != (pFullType->IsEqual(pInputMediaType.Get(), &dwFlags)))) /*Media Types dont match*/ + ||((pFullType == nullptr)||(pInputMediaType == nullptr))/*Either one of the mediatypes is null*/ + ) + { + // + // State has change or media type has changed so we need to change the media type on the + // underlying kernel pin + // + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "Changing Mediatype on the input "); + spinPin->setPreferredMediaType(pFullType.Get()); + spinPin->setPreferredStreamState(newRequestedInPinState); + // Let the pipline know that the input needs to be changed. + SendEventToManager(METransformInputStreamStateChanged, GUID_NULL, spinPin->streamId()); + // + // The media type will be set on the input pin by the time we return from the wait + // + m_critSec.Unlock(); + hr = spinPin->WaitForSetInputPinMediaChange(); + m_critSec.Lock(); + // Change the media type on the output.. + DMFTCHECKHR_GOTO(spoPin->ChangeMediaTypeFromInpin( pMediaType , reqState), done); + // + // Notify the pipeline that the output stream media type has changed + // + DMFTCHECKHR_GOTO(SendEventToManager(MEUnknown, MEDeviceStreamCreated, spoPin->streamId()), done); + spoPin->SetFirstSample(TRUE); + } + else + { + // Restore back old states as we have nothing to do + spinPin->SetState(oldInputStreamState); + spoPin->SetState(oldOutPinState); + } + + +done: + return hr; +} + +// +// The below function sends events to the pipeline. +// + +HRESULT CMultipinMft::SendEventToManager( + _In_ MediaEventType eventType, + _In_ REFGUID pGuid, + _In_ UINT32 context + ) + /*++ + Description: + Used to send the event to DTM. + --*/ + { + HRESULT hr = S_OK; + ComPtr pEvent = nullptr; + + DMFTCHECKHR_GOTO(MFCreateMediaEvent(eventType, pGuid, S_OK, NULL, &pEvent ),done); + DMFTCHECKHR_GOTO(pEvent->SetUINT32(MF_EVENT_MFT_INPUT_STREAM_ID, (ULONG)context),done); + DMFTCHECKHR_GOTO(QueueEvent(pEvent.Get()),done); + done: + + return hr; + } +/*++ +Description: +This function connects the input and output pins. +Any media type filtering can happen here +--*/ +HRESULT CMultipinMft::BridgeInputPinOutputPin( + _In_ CInPin* piPin, + _In_ COutPin* poPin + ) +{ + HRESULT hr = S_OK; + ULONG ulIndex = 0; + ULONG ulAddedMediaTypeCount = 0; + ComPtr spMediaType; + + DMFTCHECKNULL_GOTO( piPin, done, E_INVALIDARG ); + DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG ); + + while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, spMediaType.ReleaseAndGetAddressOf() ))) + { + DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, spMediaType.Get() ), done ); + ulAddedMediaTypeCount++; + } + + if (ulAddedMediaTypeCount == 0) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Make Sure Pin %d has one media type exposed ", piPin->streamId()); + DMFTCHECKHR_GOTO( MF_E_INVALID_STREAM_DATA, done ); + } + // + //Add the Input Pin to the output Pin + // + DMFTCHECKHR_GOTO(poPin->AddPin(piPin->streamId()), done); + hr = ExceptionBoundary([&](){ + // + // Add the output pin to the input pin. + // Create the pin map. So that we know which pin input pin is connected to which output pin + // + piPin->ConnectPin(poPin); + m_outputPinMap.insert(std::pair< int, int >(poPin->streamId(), piPin->streamId())); + }); +done: + // + //Failed adding media types + // + if (FAILED(hr)) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + } + return hr; +} + +// +// IMFShutdown interface functions +// + +/*++ +Description: +Implements the Shutdown from IMFShutdown +--*/ +IFACEMETHODIMP CMultipinMft::Shutdown( + void + ) +{ + CAutoLock Lock(m_critSec); + + for (ULONG ulIndex = 0, ulSize = (ULONG)m_InPins.size(); ulIndex < ulSize; ulIndex++ ) + { + CInPin *pInPin = static_cast(m_InPins[ulIndex].Get()); + + // Deref on the connected outpins to break reference loop + (VOID)pInPin->ShutdownPin(); + } + return ShutdownEventGenerator(); +} + +// +// Static method to create an instance of the MFT. +// +HRESULT CMultipinMft::CreateInstance(REFIID iid, void **ppMFT) +{ + HRESULT hr = S_OK; + ComPtr spMFT; + DMFTCHECKNULL_GOTO(ppMFT, done, E_POINTER); + spMFT = new (std::nothrow) CMultipinMft(); + DMFTCHECKNULL_GOTO(spMFT.Get(), done, E_OUTOFMEMORY); + + DMFTCHECKHR_GOTO(spMFT->QueryInterface(iid, ppMFT), done); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} diff --git a/avstream/avscamera/DMFT/AvsCameraDMFT.h b/avstream/avscamera/DMFT/AvsCameraDMFT.h new file mode 100644 index 000000000..27b8607b5 --- /dev/null +++ b/avstream/avscamera/DMFT/AvsCameraDMFT.h @@ -0,0 +1,334 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// + +#pragma once +#include "common.h" +#include "mftpeventgenerator.h" +#include "basepin.h" + +// +// The Below GUID is needed to transfer photoconfirmation sample successfully in the pipeline +// It is used to propagate the mediatype of the sample to the pipeline which will consume the sample +// This attribute is known to the OS, but not publicly defined. +// + +DEFINE_GUID(MFSourceReader_SampleAttribute_MediaType_priv, + 0x0ea5c1e8, 0x9845, 0x41e0, 0xa2, 0x43, 0x72, 0x32, 0x07, 0xfc, 0x78, 0x1f); + + +interface IDirect3DDeviceManager9; + +// +// Forward declarations +// +class CMFAttributes; +class CPinCreationFactory; +// +// CMultipinMft class: +// Implements a device proxy MFT. +// +class CMultipinMft : + public IMFDeviceTransform + , public IMFShutdown + , public CMediaEventGenerator + , public IMFRealTimeClientEx + , public IKsControl + , public CDMFTModuleLifeTimeManager +{ + friend class CPinCreationFactory; +public: + CMultipinMft( + void ); + + virtual ~CMultipinMft(); + + // + // IUnknown + // + IFACEMETHODIMP_(ULONG) AddRef( + void ); + + IFACEMETHODIMP_(ULONG) Release( + void ); + + IFACEMETHODIMP QueryInterface( + _In_ REFIID iid, + _COM_Outptr_ void** ppv); + + + // + // IMFDeviceTransform functions + // + IFACEMETHODIMP GetStreamCount ( + _Inout_ DWORD *pdwInputStreams, + _Inout_ DWORD *pdwOutputStreams); + + + IFACEMETHODIMP GetStreamIDs ( + _In_ DWORD dwInputIDArraySize, + _When_(dwInputIDArraySize >= m_InputPinCount, _Out_writes_(dwInputIDArraySize)) DWORD* pdwInputIDs, + _In_ DWORD dwOutputIDArraySize, + _When_(dwOutputIDArraySize >= m_OutputPinCount && (pdwInputIDs && (dwInputIDArraySize > 0)), + _Out_writes_(dwOutputIDArraySize)) _On_failure_(_Valid_) DWORD* pdwOutputIDs + ); + + IFACEMETHODIMP GetInputStreamAttributes( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFAttributes** ppAttributes); + + IFACEMETHODIMP GetOutputStreamAttributes( + _In_ DWORD dwOutputStreamID, + _Out_ IMFAttributes** ppAttributes); + + IFACEMETHODIMP GetInputAvailableType( + _In_ DWORD dwInputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppType); + + IFACEMETHODIMP GetOutputAvailableType( + _In_ DWORD dwOutputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppMediaType); + + IFACEMETHODIMP GetInputCurrentType( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFMediaType** ppMediaType); + + IFACEMETHODIMP GetOutputCurrentType( + _In_ DWORD dwOutputStreamID, + _Out_ IMFMediaType** ppMediaType); + + IFACEMETHODIMP ProcessMessage( + _In_ MFT_MESSAGE_TYPE eMessage, + _In_ ULONG_PTR ulParam ); + + IFACEMETHODIMP ProcessEvent( + _In_ DWORD dwInputStreamID, + _In_ IMFMediaEvent *pEvent); + + + IFACEMETHODIMP ProcessInput( + _In_ DWORD dwInputStreamID, + _In_ IMFSample* pSample, + _In_ DWORD dwFlags ); + + IFACEMETHODIMP ProcessOutput( + _In_ DWORD dwFlags, + _In_ DWORD cOutputBufferCount, + _Inout_updates_(cOutputBufferCount) MFT_OUTPUT_DATA_BUFFER *pOutputSamples, + _Out_ DWORD *pdwStatus ); + + // + // IMFRealTimeClientEx + // + IFACEMETHODIMP RegisterThreadsEx( + _Inout_ DWORD* pdwTaskIndex, + _In_ LPCWSTR wszClassName, + _In_ LONG lBasePriority ) + { + UNREFERENCED_PARAMETER(pdwTaskIndex); + UNREFERENCED_PARAMETER(wszClassName); + UNREFERENCED_PARAMETER(lBasePriority); + return S_OK; + } + + IFACEMETHODIMP UnregisterThreads() + { + return S_OK; + } + + IFACEMETHODIMP SetWorkQueueEx( + _In_ DWORD dwWorkQueueId, + _In_ LONG lWorkItemBasePriority ); + + // + // IMFShutdown + // + IFACEMETHODIMP Shutdown( + void ); + + IFACEMETHODIMP GetShutdownStatus( + MFSHUTDOWN_STATUS *pStatus) + { + UNREFERENCED_PARAMETER(pStatus); + return(m_eShutdownStatus); + }; + + // + // IMFDeviceTransform function declarations + // + IFACEMETHODIMP InitializeTransform( + _In_ IMFAttributes *pAttributes ); + + _Requires_no_locks_held_ + IFACEMETHODIMP SetInputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags ); + + IFACEMETHODIMP GetInputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *value ); + + IFACEMETHODIMP SetOutputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags ); + + IFACEMETHODIMP GetOutputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *value ); + + IFACEMETHODIMP GetInputStreamPreferredState( + _In_ DWORD dwStreamID, + _Inout_ DeviceStreamState *value, + _Outptr_opt_result_maybenull_ IMFMediaType **ppMediaType ); + + IFACEMETHODIMP FlushInputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags ); + + IFACEMETHODIMP FlushOutputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags ); + + IFACEMETHODIMP_(VOID) FlushAllStreams( + VOID + ); + + // + //IKSControl Inferface function declarations + // + IFACEMETHODIMP KsEvent( + _In_reads_bytes_(ulEventLength) PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_updates_bytes_opt_(ulDataLength) LPVOID pEventData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ); + IFACEMETHODIMP KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ); + IFACEMETHODIMP KsMethod( + _In_reads_bytes_(ulPropertyLength) PKSMETHOD pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ); + + static HRESULT CreateInstance( + REFIID iid, void **ppMFT); + + __inline BOOL isPhotoModePhotoSequence() + { + return m_PhotoModeIsPhotoSequence; + } + + __inline DWORD GetQueueId() + { + return m_dwWorkQueueId; + } + + // + //Will be used from Pins to get the D3D manager once set!!! + // + __inline IFACEMETHODIMP_(VOID) GetD3DDeviceManager( + IUnknown** ppDeviceManagerUnk + ) + { + m_spDeviceManagerUnk.CopyTo( ppDeviceManagerUnk ); + } + + HRESULT SendEventToManager( + _In_ MediaEventType, + _In_ REFGUID, + _In_ UINT32 + ); + +protected: + + // + //Helper functions + // + + CInPin* GetInPin( + _In_ DWORD dwStreamID + ); + + COutPin* GetOutPin( + _In_ DWORD dwStreamID + ); + + HRESULT GetConnectedInpin(_In_ ULONG ulOutpin, _Out_ ULONG &ulInPin); + + __requires_lock_held(m_critSec) + HRESULT ChangeMediaTypeEx( + _In_ ULONG pinId, + _In_opt_ IMFMediaType *pMediaType, + _In_ DeviceStreamState newState + ); + HRESULT BridgeInputPinOutputPin( + _In_ CInPin* pInPin, + _In_ COutPin* pOutPin); + // + //Inline functions + // + + __inline IMFDeviceTransform* Parent() + { + return m_spSourceTransform.Get(); + } + + __inline VOID SetStreamingState(DeviceStreamState state) + { + InterlockedExchange((LONG*)&m_StreamingState, state); + } + + __inline DeviceStreamState GetStreamingState() + { + return (DeviceStreamState)InterlockedCompareExchange((LONG*)&m_StreamingState, 0L, 0L); + } + + __inline BOOL IsStreaming() + { + return (InterlockedCompareExchange((LONG*)&m_StreamingState, DeviceStreamState_Run, DeviceStreamState_Run) == DeviceStreamState_Run); + } + +private: + ULONG m_InputPinCount; + ULONG m_OutputPinCount; + ULONG m_CustomPinCount; + DeviceStreamState m_StreamingState; + CBasePinArray m_OutPins; + CBasePinArray m_InPins; + BOOL m_PhotoModeIsPhotoSequence; // used to store if the filter is in photo sequence or not + long m_nRefCount; // Reference count + CCritSec m_critSec; // Control lock.. taken only durign state change operations + ComPtr m_spDeviceManagerUnk; // D3D Manager set, when MFT_MESSAGE_SET_D3D_MANAGER is called through ProcessMessage + ComPtr m_spSourceTransform; // The sources transform. This is the pipeline DevProxy + MFSHUTDOWN_STATUS m_eShutdownStatus; + DWORD m_dwWorkQueueId; + LONG m_lWorkQueuePriority; + UINT32 m_punValue; + ComPtr m_spIkscontrol; + ComPtr m_spAttributes; + map m_outputPinMap; // How output pins are connected to input pins i-><0..outpins> + PWCHAR m_SymbolicLink; +}; + + + +inline HRESULT MFT_CreateInstance(REFIID riid, void **ppv) +{ + return CMultipinMft::CreateInstance(riid, ppv); +} + + diff --git a/avstream/avscamera/DMFT/AvsCameraDMFT.vcxproj b/avstream/avscamera/DMFT/AvsCameraDMFT.vcxproj new file mode 100644 index 000000000..3f6180f26 --- /dev/null +++ b/avstream/avscamera/DMFT/AvsCameraDMFT.vcxproj @@ -0,0 +1,250 @@ + + + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + x64 + + + Release + x64 + + + + {E77657CD-A270-49E1-823A-8A14FF8596C8} + $(MSBuildProjectName) + false + Debug + Win32 + {D6CB33D6-DEF2-497E-A72D-6E6E29C67F48} + AvsCameraDMFT + $(LatestTargetPlatformVersion) + + + + Windows10 + False + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + + + Windows10 + True + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + + + Windows10 + False + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + + + Windows10 + True + Universal + + WindowsApplicationForDrivers10.0 + DynamicLibrary + + + + $(IntDir) + + + + + + + + + + + + + + + + true + true + DMFTRACE(FLAG,LEVEL,MSG,...) + {um-default.tpl}*.tmh + ;%(AdditionalIncludeDirectories) + stdafx.h + Use + $(IntDir)\stdafx.h.pch + common.h + + + true + true + DMFTRACE(FLAG,LEVEL,MSG,...) + {um-default.tpl}*.tmh + ;%(AdditionalIncludeDirectories) + stdafx.h + Use + $(IntDir)\stdafx.h.pch + common.h + + + true + true + DMFTRACE(FLAG,LEVEL,MSG,...) + {um-default.tpl}*.tmh + ;%(AdditionalIncludeDirectories) + stdafx.h + Use + $(IntDir)\stdafx.h.pch + common.h + + + true + true + DMFTRACE(FLAG,LEVEL,MSG,...) + {um-default.tpl}*.tmh + ;%(AdditionalIncludeDirectories) + stdafx.h + Use + $(IntDir)\stdafx.h.pch + common.h + + + true + true + DMFTRACE(FLAG,LEVEL,MSG,...) + {um-default.tpl}*.tmh + ;%(AdditionalIncludeDirectories) + stdafx.h + Use + $(IntDir)\stdafx.h.pch + common.h + + + + AvsCameraDMFT + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\wil\include + + + + Sync + + + + + Sync + + + + + Sync + + + + + Sync + + + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + $(IntDir);%(AdditionalIncludeDirectories);..\..\common;..\common + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + Source.def + + + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + $(IntDir);%(AdditionalIncludeDirectories);..\..\common;..\common + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + Source.def + + + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + $(IntDir);%(AdditionalIncludeDirectories);..\..\common;..\common + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + Source.def + + + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + $(IntDir);%(AdditionalIncludeDirectories);..\..\common;..\common + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD + + + %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + Source.def + + + + + ;%(AdditionalIncludeDirectories) + stdafx.h + Create + $(IntDir)\stdafx.h.pch + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/print/XPSDrvSmpl/src/filters/booklet/xdbook.vcxproj.Filters b/avstream/avscamera/DMFT/AvsCameraDMFT.vcxproj.Filters similarity index 56% rename from print/XPSDrvSmpl/src/filters/booklet/xdbook.vcxproj.Filters rename to avstream/avscamera/DMFT/AvsCameraDMFT.vcxproj.Filters index 3f281a6cb..c3679c843 100644 --- a/print/XPSDrvSmpl/src/filters/booklet/xdbook.vcxproj.Filters +++ b/avstream/avscamera/DMFT/AvsCameraDMFT.vcxproj.Filters @@ -3,63 +3,55 @@ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* - {27EE07C8-4A3B-416F-9266-E7701F9FB1DB} + {39379DB7-5CE0-407A-A6D4-F2F23BB3BF3C} h;hpp;hxx;hm;inl;inc;xsd - {6811EDBB-9803-4589-BAAE-09AD34EC922A} + {05E63691-6953-4F79-BEC2-1CF881B618BA} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml - {68346DB5-5823-45D6-8621-B9323A164F62} + {B10F4398-9892-4AA8-8653-E5A7F4726726} - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files + + Source Files + + + Source Files + - - Resource Files - - - - + Header Files - - - + Header Files - - - + Header Files - + Header Files - + Header Files - - - Source Files - - \ No newline at end of file diff --git a/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp b/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp new file mode 100644 index 000000000..4a4c75fce --- /dev/null +++ b/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp @@ -0,0 +1,805 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// + +#include "stdafx.h" + +#pragma comment(lib, "d2d1") +#ifdef MF_WPP +#include "AvsCameraDMFTutils.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif + +// Critical sections + +CCritSec::CCritSec() +{ + InitializeCriticalSection(&m_criticalSection); +} + +CCritSec::~CCritSec() +{ + DeleteCriticalSection(&m_criticalSection); +} + +_Requires_lock_not_held_(m_criticalSection) _Acquires_lock_(m_criticalSection) +void CCritSec::Lock() +{ + EnterCriticalSection(&m_criticalSection); +} + +_Requires_lock_held_(m_criticalSection) _Releases_lock_(m_criticalSection) +void CCritSec::Unlock() +{ + LeaveCriticalSection(&m_criticalSection); +} + + +_Acquires_lock_(this->m_pCriticalSection->m_criticalSection) +CAutoLock::CAutoLock(CCritSec& crit) +{ + m_pCriticalSection = &crit; + m_pCriticalSection->Lock(); +} +_Acquires_lock_(this->m_pCriticalSection->m_criticalSection) +CAutoLock::CAutoLock(CCritSec* crit) +{ + m_pCriticalSection = crit; + m_pCriticalSection->Lock(); +} +_Releases_lock_(this->m_pCriticalSection->m_criticalSection) +CAutoLock::~CAutoLock() +{ + m_pCriticalSection->Unlock(); +} + +// +//Some utility functions.. +/*++ + Description: + Helper function to return back if the Pin is in stopped stateo or not +--*/ +STDMETHODIMP_(BOOL) IsPinStateInActive( _In_ DeviceStreamState state) +{ + if ((state == DeviceStreamState_Disabled) || + (state == DeviceStreamState_Stop)) + { + return TRUE; + } + return FALSE; +} + + +#ifndef IF_EQUAL_RETURN +#define IF_EQUAL_RETURN(param, val) if(val == param) return #val +#endif + +#define checkAdjustBufferCap(a,len){\ + char* tStore = NULL; \ +if (a && strlen(a) > ((len * 7) / 10)){\ + tStore = a; \ + len *= 2; \ + a = new (std::nothrow) char[len]; \ +if (!a){\ +goto done;}\ + a[0] = 0; \ + strcat_s(a, len, tStore); \ + delete(tStore); }\ +} + +// +// Queue implementation +// +CPinQueue::CPinQueue(_In_ DWORD dwPinId, _In_ IMFDeviceTransform* pParent) : + m_dwInPinId(dwPinId), m_pTransform(pParent), m_cRef(1) + +/* +Description +dwPinId is the input pin Id to which this queue corresponds +*/ +{ + m_streamCategory = GUID_NULL; +} +CPinQueue::~CPinQueue() +{ +} + +/*++ +Description: + Insert sample into the list once we reach the open queue +--*/ +STDMETHODIMP CPinQueue::Insert(_In_ IMFSample* pSample) +{ + HRESULT hr = ExceptionBoundary([&]() { + m_sampleList.push_back(pSample); + }); + + if (SUCCEEDED(hr) && m_pTransform) + { + hr = reinterpret_cast(m_pTransform)->QueueEvent(METransformHaveOutput, GUID_NULL, S_OK, NULL); + } + + if (FAILED(hr)) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + // There is a bug in the pipeline that doesn't release the sample fed from processinput. We have to explicitly release the sample here + SAFE_RELEASE(pSample); + } + return hr; +} + + +/*++ +Description: + This extracts the first sample from the queue. called from Pin's ProcessOutput +--*/ + +STDMETHODIMP CPinQueue::Remove(_Outptr_result_maybenull_ IMFSample** ppSample) +{ + HRESULT hr = S_OK; + DMFTCHECKNULL_GOTO(ppSample, done, E_INVALIDARG); + *ppSample = nullptr; + + if (!m_sampleList.empty()) + { + *ppSample = m_sampleList.front().Detach(); + } + + DMFTCHECKNULL_GOTO(*ppSample, done, MF_E_TRANSFORM_NEED_MORE_INPUT); + m_sampleList.erase(m_sampleList.begin()); +done: + return hr; +} + +/*++ +Description: + Empties the Queue. used by the flush +--*/ +VOID CPinQueue::Clear() +{ + while (!Empty()) + { + ComPtr spSample; + Remove(spSample.GetAddressOf()); + } +} + +// Handle Metadata + +#if (NTDDI_VERSION >= NTDDI_WINBLUE) +///////////////////////////////////////////////////////////////////// +// +// Handle the Metadata with the buffer +// + +HRESULT ParseMetadata_FaceDetection( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +); + +HRESULT ParseMetadata_PreviewAggregation( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +); + +HRESULT ParseMetadata_ImageAggregation( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +); + +HRESULT ParseMetadata_Histogram( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +); + +HRESULT ProcessMetadata(_In_ IMFSample* pSample) +{ + ComPtr spMetadata; + ComPtr spSample = pSample; + HRESULT hr = spSample->GetUnknown(MFSampleExtension_CaptureMetadata, IID_PPV_ARGS(spMetadata.ReleaseAndGetAddressOf())); + if (FAILED(hr)) + { + return hr; + } + + ComPtr spBuffer; + hr = spMetadata->GetUnknown(MF_CAPTURE_METADATA_FRAME_RAWSTREAM, IID_PPV_ARGS(spBuffer.ReleaseAndGetAddressOf())); + if (FAILED(hr)) + { + return hr; + } + + MediaBufferLock bufferLock(spBuffer.Get()); + BYTE* pData = NULL; + DWORD dwLength = 0; + hr = bufferLock.LockBuffer(&pData, NULL, &dwLength); + if (FAILED(hr)) + { + return hr; + } + + // OEM put meta data passing logic here, + if (FAILED(hr)) + { + return hr; + } + + LONG lBufferLeft = static_cast(dwLength); + if (lBufferLeft < sizeof(KSCAMERA_METADATA_ITEMHEADER)) + { + return E_UNEXPECTED; + } + + PKSCAMERA_METADATA_ITEMHEADER pItem = (PKSCAMERA_METADATA_ITEMHEADER)pData; + + while (lBufferLeft > 0) + { + switch (pItem->MetadataId) + { + case MetadataId_Custom_PreviewAggregation: + hr = ParseMetadata_PreviewAggregation(pItem, spMetadata.Get()); + if (FAILED(hr)) + { + return hr; + } + break; + case MetadataId_Custom_ImageAggregation: + hr = ParseMetadata_ImageAggregation(pItem, spMetadata.Get()); + if (FAILED(hr)) + { + return hr; + } + break; + case MetadataId_Custom_Histogram: + hr = ParseMetadata_Histogram(pItem, spMetadata.Get()); + if (FAILED(hr)) + { + return hr; + } + break; + case MetadataId_Custom_FaceDetection: + hr = ParseMetadata_FaceDetection(pItem, spMetadata.Get()); + if (FAILED(hr)) + { + return hr; + } + } + + if (!pItem->Size) + { + // 0 size item will cause the loop to break and + // we will report buffer malformated + break; + } + lBufferLeft -= (LONG)pItem->Size; + if (lBufferLeft < sizeof(KSCAMERA_METADATA_ITEMHEADER)) + { + break; + } + pItem = reinterpret_cast + (reinterpret_cast(pItem) + pItem->Size); + } + + if (lBufferLeft != 0) + { + //Check and log for malformated data + return E_UNEXPECTED; + } + + return S_OK; +} + +HRESULT ParseMetadata_PreviewAggregation( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +) +{ + HRESULT hr = S_OK; + if (pItem->Size < sizeof(CAMERA_METADATA_PREVIEWAGGREGATION)) + { + return E_UNEXPECTED; + } + + PCAMERA_METADATA_PREVIEWAGGREGATION pFixedStruct = + (PCAMERA_METADATA_PREVIEWAGGREGATION)pItem; + + if (pFixedStruct->Data.FocusState.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_FOCUSSTATE, + pFixedStruct->Data.FocusState.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.ExposureTime.Set) + { + hr = pMetaDataAttributes->SetUINT64( + MF_CAPTURE_METADATA_EXPOSURE_TIME, + pFixedStruct->Data.ExposureTime.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.ISOSpeed.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_ISO_SPEED, + pFixedStruct->Data.ISOSpeed.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.LensPosition.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_LENS_POSITION, + pFixedStruct->Data.LensPosition.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.FlashOn.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_FLASH, + pFixedStruct->Data.FlashOn.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.WhiteBalanceMode.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_WHITEBALANCE, + pFixedStruct->Data.WhiteBalanceMode.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.EVCompensation.Set) + { + CapturedMetadataExposureCompensation EVCompensation; + + EVCompensation.Flags = pFixedStruct->Data.EVCompensation.Flags; + EVCompensation.Value = pFixedStruct->Data.EVCompensation.Value; + + hr = pMetaDataAttributes->SetBlob( + MF_CAPTURE_METADATA_EXPOSURE_COMPENSATION, + (const UINT8*)&EVCompensation, + sizeof(EVCompensation)); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.SensorFrameRate.Set) + { + hr = pMetaDataAttributes->SetUINT64( + MF_CAPTURE_METADATA_SENSORFRAMERATE, + pFixedStruct->Data.SensorFrameRate.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.IsoAnalogGain.Set || + pFixedStruct->Data.IsoDigitalGain.Set) + { + CapturedMetadataISOGains IsoGains; + + if (pFixedStruct->Data.IsoAnalogGain.Set) + { + IsoGains.AnalogGain = + FLOAT(pFixedStruct->Data.IsoAnalogGain.Numerator) / + FLOAT(pFixedStruct->Data.IsoAnalogGain.Denominator); + } + if (pFixedStruct->Data.IsoDigitalGain.Set) + { + IsoGains.DigitalGain = + FLOAT(pFixedStruct->Data.IsoDigitalGain.Numerator) / + FLOAT(pFixedStruct->Data.IsoDigitalGain.Denominator); + } + + hr = pMetaDataAttributes->SetBlob( + MF_CAPTURE_METADATA_ISO_GAINS, + (const UINT8*)&IsoGains, + sizeof(IsoGains)); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.WhiteBalanceGain_R.Set || + pFixedStruct->Data.WhiteBalanceGain_G.Set || + pFixedStruct->Data.WhiteBalanceGain_B.Set) + { + CapturedMetadataWhiteBalanceGains WhiteBalanceGains; + + if (pFixedStruct->Data.WhiteBalanceGain_R.Set) + { + WhiteBalanceGains.R = + FLOAT(pFixedStruct->Data.WhiteBalanceGain_R.Numerator) / + FLOAT(pFixedStruct->Data.WhiteBalanceGain_R.Denominator); + } + if (pFixedStruct->Data.WhiteBalanceGain_G.Set) + { + WhiteBalanceGains.G = + FLOAT(pFixedStruct->Data.WhiteBalanceGain_G.Numerator) / + FLOAT(pFixedStruct->Data.WhiteBalanceGain_G.Denominator); + } + if (pFixedStruct->Data.WhiteBalanceGain_B.Set) + { + WhiteBalanceGains.B = + FLOAT(pFixedStruct->Data.WhiteBalanceGain_B.Numerator) / + FLOAT(pFixedStruct->Data.WhiteBalanceGain_B.Denominator); + } + + hr = pMetaDataAttributes->SetBlob( + MF_CAPTURE_METADATA_WHITEBALANCE_GAINS, + (const UINT8*)&WhiteBalanceGains, + sizeof(WhiteBalanceGains)); + if (FAILED(hr)) + { + return hr; + } + } + + return S_OK; +} + +HRESULT ParseMetadata_ImageAggregation( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +) +{ + HRESULT hr = S_OK; + if (pItem->Size < sizeof(CAMERA_METADATA_IMAGEAGGREGATION)) + { + return E_UNEXPECTED; + } + + PCAMERA_METADATA_IMAGEAGGREGATION pFixedStruct = + (PCAMERA_METADATA_IMAGEAGGREGATION)pItem; + + if (pFixedStruct->Data.FrameId.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_REQUESTED_FRAME_SETTING_ID, + pFixedStruct->Data.FrameId.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.ExposureTime.Set) + { + hr = pMetaDataAttributes->SetUINT64( + MF_CAPTURE_METADATA_EXPOSURE_TIME, + pFixedStruct->Data.ExposureTime.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.ISOSpeed.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_ISO_SPEED, + pFixedStruct->Data.ISOSpeed.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.LensPosition.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_LENS_POSITION, + pFixedStruct->Data.LensPosition.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.SceneMode.Set) + { + hr = pMetaDataAttributes->SetUINT64( + MF_CAPTURE_METADATA_SCENE_MODE, + pFixedStruct->Data.SceneMode.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.FlashOn.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_FLASH, + pFixedStruct->Data.FlashOn.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.FlashPower.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_FLASH_POWER, + pFixedStruct->Data.FlashPower.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.WhiteBalanceMode.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_WHITEBALANCE, + pFixedStruct->Data.WhiteBalanceMode.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.ZoomFactor.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_ZOOMFACTOR, + pFixedStruct->Data.ZoomFactor.Value); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.EVCompensation.Set) + { + CapturedMetadataExposureCompensation EVCompensation; + + EVCompensation.Flags = pFixedStruct->Data.EVCompensation.Flags; + EVCompensation.Value = pFixedStruct->Data.EVCompensation.Value; + + hr = pMetaDataAttributes->SetBlob( + MF_CAPTURE_METADATA_EXPOSURE_COMPENSATION, + (const UINT8*)&EVCompensation, + sizeof(EVCompensation)); + if (FAILED(hr)) + { + return hr; + } + } + + if (pFixedStruct->Data.FocusState.Set) + { + hr = pMetaDataAttributes->SetUINT32( + MF_CAPTURE_METADATA_FOCUSSTATE, + pFixedStruct->Data.FocusState.Value); + if (FAILED(hr)) + { + return hr; + } + } + return S_OK; +} +#endif // (NTDDI_VERSION >= NTDDI_WINBLUE) +struct HistogramData +{ + HistogramDataHeader Header; + ULONG Color[256]; + + HistogramData() + { + Header.Size = sizeof(*this); + Header.ChannelMask = 0; + Header.Linear = 1; + RtlZeroMemory(Color, sizeof(Color)); + } +}; + +// This is the blob we pass back every time. +template +struct Histogram +{ + HistogramBlobHeader Blob; + // RGB or YUV Histograms. + HistogramHeader Header; + HistogramData Data[I]; + + Histogram( + _In_ ULONG Width = 0, + _In_ ULONG Height = 0 + ) + { + Blob.Histograms = 1; + Blob.Size = sizeof(*this); + + Header.Size = sizeof(Header) + sizeof(Data); + Header.Bins = 256; + Header.Grid.Height = Height; + Header.Grid.Width = Width; + Header.Grid.Region.top = 0; + Header.Grid.Region.left = 0; + Header.Grid.Region.bottom = Height - 1; + Header.Grid.Region.right = Width - 1; + } +}; + +#if (NTDDI_VERSION >= NTDDI_WINBLUE) +#define MF_HISTOGRAM_RGB (MF_HISTOGRAM_CHANNEL_R | MF_HISTOGRAM_CHANNEL_G | MF_HISTOGRAM_CHANNEL_B ) +#define MF_HISTOGRAM_YCrCb (MF_HISTOGRAM_CHANNEL_Y | MF_HISTOGRAM_CHANNEL_Cr | MF_HISTOGRAM_CHANNEL_Cb) + +HRESULT ParseMetadata_Histogram( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +) +{ + if (pItem->Size < sizeof(CAMERA_METADATA_HISTOGRAM)) + { + return E_UNEXPECTED; + } + + PCAMERA_METADATA_HISTOGRAM pHistogram = (PCAMERA_METADATA_HISTOGRAM)pItem; + + if ((pHistogram->Data.ChannelMask & MF_HISTOGRAM_RGB) == MF_HISTOGRAM_RGB) + { + Histogram<4> Blob(pHistogram->Data.Width, pHistogram->Data.Height); + + Blob.Header.FourCC = pHistogram->Data.FourCC; + Blob.Header.ChannelMasks = pHistogram->Data.ChannelMask; + + // For a RGB Histogram, we fake the Y channel by copying the G channel. + Blob.Data[0].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Y; + RtlCopyMemory(Blob.Data[0].Color, pHistogram->Data.P1Data, sizeof(Blob.Data[0].Color)); + + // Now just copy the RGB channels normally. + Blob.Data[1].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_R; + RtlCopyMemory(Blob.Data[1].Color, pHistogram->Data.P0Data, sizeof(Blob.Data[1].Color)); + Blob.Data[2].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_G; + RtlCopyMemory(Blob.Data[2].Color, pHistogram->Data.P1Data, sizeof(Blob.Data[2].Color)); + Blob.Data[3].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_B; + RtlCopyMemory(Blob.Data[3].Color, pHistogram->Data.P2Data, sizeof(Blob.Data[3].Color)); + + return pMetaDataAttributes->SetBlob( + MF_CAPTURE_METADATA_HISTOGRAM, + (PBYTE)&Blob, + sizeof(Blob) + ); + } + else if ((pHistogram->Data.ChannelMask & MF_HISTOGRAM_YCrCb) == MF_HISTOGRAM_YCrCb) + { + Histogram<3> Blob(pHistogram->Data.Width, pHistogram->Data.Height); + + Blob.Header.FourCC = pHistogram->Data.FourCC; + Blob.Header.ChannelMasks = pHistogram->Data.ChannelMask; + + Blob.Data[0].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Y; + RtlCopyMemory(Blob.Data[0].Color, pHistogram->Data.P0Data, sizeof(Blob.Data[0].Color)); + Blob.Data[1].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Cr; + RtlCopyMemory(Blob.Data[1].Color, pHistogram->Data.P1Data, sizeof(Blob.Data[1].Color)); + Blob.Data[2].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Cb; + RtlCopyMemory(Blob.Data[2].Color, pHistogram->Data.P2Data, sizeof(Blob.Data[2].Color)); + + //TODO: + return pMetaDataAttributes->SetBlob( + MF_CAPTURE_METADATA_HISTOGRAM, + (PBYTE)&Blob, + sizeof(Blob) + ); + } + return E_UNEXPECTED; +} + +HRESULT ParseMetadata_FaceDetection( + _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, + _In_ IMFAttributes* pMetaDataAttributes +) +{ + HRESULT hr = S_OK; + + if (pItem->Size < sizeof(CAMERA_METADATA_FACEHEADER)) + { + return E_UNEXPECTED; + } + + PCAMERA_METADATA_FACEHEADER pFaceHeader = (PCAMERA_METADATA_FACEHEADER)pItem; + + if (pItem->Size < (sizeof(CAMERA_METADATA_FACEHEADER) + (sizeof(METADATA_FACEDATA) * pFaceHeader->Count))) + { + return E_UNEXPECTED; + } + PMETADATA_FACEDATA pFaceData = (PMETADATA_FACEDATA)(pFaceHeader + 1); + UINT32 cbRectSize = sizeof(FaceRectInfoBlobHeader) + (sizeof(FaceRectInfo) * (pFaceHeader->Count)); + BYTE* pRectBuf = new (std::nothrow) BYTE[cbRectSize]; + if (pRectBuf == NULL) + { + return E_OUTOFMEMORY; + } + + UINT32 cbCharSize = sizeof(FaceCharacterizationBlobHeader) + (sizeof(FaceCharacterization) * (pFaceHeader->Count)); + BYTE* pCharBuf = new (std::nothrow) BYTE[cbCharSize]; + if (pCharBuf == NULL) + { + delete[] pRectBuf; + return E_OUTOFMEMORY; + } + + FaceRectInfoBlobHeader* pFaceRectHeader = (FaceRectInfoBlobHeader*)pRectBuf; + pFaceRectHeader->Size = cbRectSize; + pFaceRectHeader->Count = pFaceHeader->Count; + + FaceCharacterizationBlobHeader* pFaceCharHeader = (FaceCharacterizationBlobHeader*)pCharBuf; + pFaceCharHeader->Size = cbCharSize; + pFaceCharHeader->Count = pFaceHeader->Count; + + FaceRectInfo* FaceRegions = (FaceRectInfo*)(pFaceRectHeader + 1); + FaceCharacterization* FaceChars = (FaceCharacterization*)(pFaceCharHeader + 1); + + for (UINT i = 0; i < pFaceHeader->Count; i++) + { + FaceRegions[i].Region = pFaceData[i].Region; + FaceRegions[i].confidenceLevel = pFaceData[i].confidenceLevel; + + FaceChars[i].BlinkScoreLeft = pFaceData[i].BlinkScoreLeft; + FaceChars[i].BlinkScoreRight = pFaceData[i].BlinkScoreRight; + FaceChars[i].FacialExpression = (pFaceData[i].FacialExpression == EXPRESSION_SMILE) ? MF_METADATAFACIALEXPRESSION_SMILE : 0; + FaceChars[i].FacialExpressionScore = pFaceData[i].FacialExpressionScore; + } + + hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROIS, pRectBuf, cbRectSize); + if (FAILED(hr)) + { + goto done; + } + + MetadataTimeStamps timestamp; + timestamp.Flags = MF_METADATATIMESTAMPS_DEVICE; + timestamp.Device = pFaceHeader->Timestamp; + + hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROITIMESTAMPS, (const UINT8*)×tamp, sizeof(MetadataTimeStamps)); + if (FAILED(hr)) + { + goto done; + } + +#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) + // Include characterization data if any of the associated bits were set. + if (pFaceHeader->Flags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_ADVANCED_MASK) + { + hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROICHARACTERIZATIONS, pCharBuf, cbCharSize); + } +#endif // (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) + +done: + delete[] pRectBuf; + delete[] pCharBuf; + + return hr; +} +#endif diff --git a/avstream/avscamera/DMFT/Source.def b/avstream/avscamera/DMFT/Source.def new file mode 100644 index 000000000..752ef2ea8 --- /dev/null +++ b/avstream/avscamera/DMFT/Source.def @@ -0,0 +1,5 @@ +EXPORTS + DllCanUnloadNow PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + DllGetClassObject PRIVATE diff --git a/avstream/avscamera/DMFT/basepin.cpp b/avstream/avscamera/DMFT/basepin.cpp new file mode 100644 index 000000000..e01783906 --- /dev/null +++ b/avstream/avscamera/DMFT/basepin.cpp @@ -0,0 +1,625 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#include "stdafx.h" + +#ifdef MF_WPP +#include "basepin.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif +/* -------> New STATE + | + |old State +DeviceStreamState_Stop DeviceStreamState_Pause DeviceStreamState_Run DeviceStreamState_Disabled +DeviceStreamState_Pause +DeviceStreamState_Run +DeviceStreamState_Disabled +*/ + +DeviceStreamState pinStateTransition[4][4] = { + { DeviceStreamState_Stop, DeviceStreamState_Pause, DeviceStreamState_Run, DeviceStreamState_Disabled }, + { DeviceStreamState_Stop, DeviceStreamState_Pause, DeviceStreamState_Run, DeviceStreamState_Disabled }, + { DeviceStreamState_Stop, DeviceStreamState_Pause, DeviceStreamState_Run, DeviceStreamState_Disabled }, + { DeviceStreamState_Disabled, DeviceStreamState_Disabled, DeviceStreamState_Disabled, DeviceStreamState_Disabled } +}; + +CBasePin::CBasePin( _In_ ULONG id, _In_ CMultipinMft *parent) : + m_StreamId(id) + , m_Parent(parent) + , m_setMediaType(nullptr) + , m_nRefCount(0) + , m_state(DeviceStreamState_Stop) + , m_dwWorkQueueId(MFASYNC_CALLBACK_QUEUE_UNDEFINED) +{ + +} + +CBasePin::~CBasePin() +{ + m_listOfMediaTypes.clear(); + m_spAttributes = nullptr; +} + +IFACEMETHODIMP_(DeviceStreamState) CBasePin::GetState() +{ + return (DeviceStreamState) InterlockedCompareExchange((PLONG)&m_state, 0L,0L); +} + +IFACEMETHODIMP_(DeviceStreamState) CBasePin::SetState(_In_ DeviceStreamState state) +{ + return (DeviceStreamState) InterlockedExchange((LONG*)&m_state, state); +} + +HRESULT CBasePin::AddMediaType( _Inout_ DWORD *pos, _In_ IMFMediaType *pMediaType) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + + DMFTCHECKNULL_GOTO(pMediaType, done, E_INVALIDARG); + hr = ExceptionBoundary([&]() + { + m_listOfMediaTypes.push_back(pMediaType); + }); + DMFTCHECKHR_GOTO(hr, done); + if (pos) + { + *pos = (DWORD)(m_listOfMediaTypes.size() - 1); + } + +done: + return hr; +} + +HRESULT CBasePin::GetMediaTypeAt( _In_ DWORD pos, _Outptr_result_maybenull_ IMFMediaType **ppMediaType ) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + ComPtr spMediaType; + DMFTCHECKNULL_GOTO(ppMediaType,done,E_INVALIDARG); + *ppMediaType = nullptr; + if (pos >= m_listOfMediaTypes.size()) + { + DMFTCHECKHR_GOTO(MF_E_NO_MORE_TYPES,done); + } + spMediaType = m_listOfMediaTypes[pos]; + *ppMediaType = spMediaType.Detach(); +done: + return hr; +} + +IFACEMETHODIMP_(BOOL) CBasePin::IsMediaTypeSupported +( + _In_ IMFMediaType *pMediaType, + _When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_) + IMFMediaType **ppIMFMediaTypeFull +) +{ + HRESULT hr = S_OK; + BOOL bFound = FALSE; + CAutoLock Lock(lock()); + DMFTCHECKNULL_GOTO(pMediaType,done,E_INVALIDARG); + if (ppIMFMediaTypeFull) + { + *ppIMFMediaTypeFull = nullptr; + } + + for (UINT uIIndex = 0, uISize = (UINT)m_listOfMediaTypes.size(); uIIndex < uISize ; uIIndex++ ) + { + DWORD dwResult = 0; + hr = m_listOfMediaTypes[ uIIndex ]->IsEqual( pMediaType, &dwResult ); + if (hr == S_FALSE) + { + + if ((dwResult & MF_MEDIATYPE_EQUAL_MAJOR_TYPES) && + (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_TYPES) && + (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_DATA)) + { + hr = S_OK; + } + } + if (hr == S_OK) + { + bFound = TRUE; + if (ppIMFMediaTypeFull) { + DMFTCHECKHR_GOTO(m_listOfMediaTypes[uIIndex].CopyTo(ppIMFMediaTypeFull), done); + } + break; + } + else if (FAILED(hr)) + { + DMFTCHECKHR_GOTO(hr,done); + } + } +done: + return SUCCEEDED(hr) ? TRUE : FALSE; +} + +IFACEMETHODIMP CBasePin::GetOutputAvailableType( + _In_ DWORD dwTypeIndex, + _Out_opt_ IMFMediaType** ppType) +{ + return GetMediaTypeAt( dwTypeIndex, ppType ); +} + +HRESULT CBasePin::QueryInterface( + _In_ REFIID iid, + _Outptr_result_maybenull_ void** ppv + ) +{ + HRESULT hr = S_OK; + + DMFTCHECKNULL_GOTO(ppv, done, E_POINTER); + *ppv = nullptr; + if ( iid == __uuidof( IUnknown ) ) + { + *ppv = static_cast(this); + } + else if ( iid == __uuidof( IMFAttributes ) ) + { + *ppv = static_cast< IMFAttributes* >( this ); + } + else if ( iid == __uuidof( IKsControl ) ) + { + *ppv = static_cast< IKsControl* >( this ); + } + else + { + hr = E_NOINTERFACE; + goto done; + } + AddRef(); +done: + return hr; +} + +VOID CBasePin::SetD3DManager(_In_opt_ IUnknown* pManager) +{ + // + // Should release the old dxgi manager.. We will not invalidate the pins or allocators + // We will recreate all allocator when the media types are set, so we should be fine + // And the pipeline will not set the dxgimanager when the pipeline is already built + // + CAutoLock Lock(lock()); + m_spDxgiManager = pManager; + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Setting D3DManager on pin %d", m_StreamId); +} +// +//Input Pin implementation +// +CInPin::CInPin( + _In_opt_ IMFAttributes *pAttributes, + _In_ ULONG ulPinId, + _In_ CMultipinMft *pParent) + : + CBasePin(ulPinId, pParent), + m_stStreamType(GUID_NULL), + m_waitInputMediaTypeWaiter(NULL), + m_preferredStreamState(DeviceStreamState_Stop) +{ + setAttributes(pAttributes); +} + +CInPin::~CInPin() +{ + setAttributes( nullptr ); + m_spSourceTransform = nullptr; + + if (m_waitInputMediaTypeWaiter) + { + CloseHandle(m_waitInputMediaTypeWaiter); + } +} + +IFACEMETHODIMP CInPin::Init( + _In_ IMFDeviceTransform* pTransform + ) +{ + + HRESULT hr = S_OK; + + DMFTCHECKNULL_GOTO( pTransform, done, E_INVALIDARG ); + + m_spSourceTransform = pTransform; + + DMFTCHECKHR_GOTO( GetGUID( MF_DEVICESTREAM_STREAM_CATEGORY, &m_stStreamType ), done ); + + // + //Get the DevProxy IKSControl.. used to send the KSControls or the device control IOCTLS over to devproxy and finally on to the driver!!!! + // + DMFTCHECKHR_GOTO( m_spAttributes.As( &m_spIkscontrol ), done ); + + m_waitInputMediaTypeWaiter = CreateEvent( NULL, + FALSE, + FALSE, + nullptr + ); + DMFTCHECKNULL_GOTO( m_waitInputMediaTypeWaiter, done, E_OUTOFMEMORY ); + + DMFTCHECKHR_GOTO( GenerateMFMediaTypeListFromDevice(streamId()),done ); + +done: + if ( FAILED(hr) ) + { + m_spSourceTransform = nullptr; + + if ( m_waitInputMediaTypeWaiter ) + { + CloseHandle( m_waitInputMediaTypeWaiter ); + m_waitInputMediaTypeWaiter = NULL; + } + + m_stStreamType = GUID_NULL; + } + + return hr; +} + +HRESULT CInPin::GenerateMFMediaTypeListFromDevice( + _In_ UINT uiStreamId + ) +{ + HRESULT hr = S_OK; + GUID stSubType = { 0 }; + //This is only called in the begining when the input pin is constructed + DMFTCHECKNULL_GOTO( m_spSourceTransform, done, MF_E_TRANSFORM_TYPE_NOT_SET ); + for (UINT iMediaType = 0; SUCCEEDED(hr) ; iMediaType++) + { + ComPtr spMediaType; + DWORD pos = 0; + + hr = m_spSourceTransform->GetOutputAvailableType(uiStreamId, iMediaType, spMediaType.GetAddressOf()); + if (hr != S_OK) + break; + + DMFTCHECKHR_GOTO(AddMediaType(&pos, spMediaType.Get()), done); + } +done: + if (hr == MF_E_NO_MORE_TYPES) { + hr = S_OK; + } + return hr; +} + +IFACEMETHODIMP CInPin::SendSample( + _In_ IMFSample *pSample + ) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + if (FAILED(Active())) + { + goto done; + } + COutPin *poPin = static_cast(m_outpin.Get()); + DMFTCHECKNULL_GOTO(pSample, done, S_OK); + DMFTCHECKHR_GOTO(poPin->AddSample(pSample, this), done); + + done: + return hr; +} + +IFACEMETHODIMP_(VOID) CInPin::ConnectPin( _In_ CBasePin * poPin ) +{ + CAutoLock Lock(lock()); + if (poPin!=nullptr) + { + m_outpin = poPin; + } +} + +IFACEMETHODIMP CInPin::WaitForSetInputPinMediaChange() +{ + DWORD dwWait = 0; + HRESULT hr = S_OK; + + dwWait = WaitForSingleObject( m_waitInputMediaTypeWaiter, INFINITE ); + + if ( dwWait != WAIT_OBJECT_0 ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto done; + } +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +HRESULT CInPin::GetInputStreamPreferredState( + _Inout_ DeviceStreamState* value, + _Outptr_opt_result_maybenull_ IMFMediaType** ppMediaType + ) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + + if (value!=nullptr) + { + *value = m_preferredStreamState; + } + + if (ppMediaType ) + { + *ppMediaType = nullptr; + if (m_spPrefferedMediaType != nullptr ) + { + m_spPrefferedMediaType.CopyTo(ppMediaType); + } + } + + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +HRESULT CInPin::SetInputStreamState( + _In_ IMFMediaType* pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags + ) +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwFlags); + + CAutoLock Lock(lock()); + // + //Set the media type + // + setMediaType(pMediaType); + SetState(value); + // + //Set the event. This event is being waited by an output media/state change operation + // + m_spPrefferedMediaType = nullptr; + SetEvent(m_waitInputMediaTypeWaiter); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +IFACEMETHODIMP_(VOID) CInPin::ShutdownPin() +{ + m_spSourceTransform = nullptr; + m_outpin = nullptr; +} +// +//Output Pin Implementation +// +COutPin::COutPin( + _In_ ULONG ulPinId, + _In_opt_ CMultipinMft *pparent, + _In_ IKsControl* pIksControl + ) + : CBasePin(ulPinId, pparent) + , m_firstSample(false) + , m_queue(nullptr) +{ + HRESULT hr = S_OK; + ComPtr spAttributes; + + // + //Get the input pin IKS control.. the pin IKS control talks to sourcetransform's IKS control + // + m_spIkscontrol = pIksControl; + + MFCreateAttributes( &spAttributes, 3 ); //Create the space for the attribute store!! + setAttributes( spAttributes.Get()); + DMFTCHECKHR_GOTO( SetUINT32( MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE ), done ); + DMFTCHECKHR_GOTO( SetString( MFT_ENUM_HARDWARE_URL_Attribute, L"Sample_CameraExtensionMft" ),done ); + DMFTCHECKHR_GOTO( SetUINT32( MF_TRANSFORM_ASYNC, TRUE ),done ); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); +} + +COutPin::~COutPin() +{ + m_spAttributes = nullptr; + SAFE_DELETE(m_queue); +} + +/*++ +COutPin::AddPin +Description: +Called from AddSample if the Output Pin is in open state. This function looks for the queue +corresponding to the input pin and adds it in the queue. +--*/ +IFACEMETHODIMP COutPin::AddPin( + _In_ DWORD inputPinId + ) +{ + // + //Add a new queue corresponding to the input pin + // + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + + m_queue = new (std::nothrow) CPinQueue(inputPinId,Parent()); + DMFTCHECKNULL_GOTO(m_queue, done, E_OUTOFMEMORY ); +done: + + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return S_OK; +} +/*++ +COutPin::AddSample +Description: +Called when ProcessInput is called on the Device Transform. The Input Pin puts the samples +in the pins connected. If the Output pins are in open state the sample lands in the queues +--*/ + +IFACEMETHODIMP COutPin::AddSample( + _In_ IMFSample *pSample, + _In_ CBasePin *pPin) +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(pPin); + + CAutoLock Lock(lock()); // Serialize + + DMFTCHECKNULL_GOTO(pSample, done, E_INVALIDARG); + if (FAILED(Active())) + { + goto done; + } + DMFTCHECKHR_GOTO(m_queue->Insert(pSample), done); +done: + if (FAILED(hr)) + { + // Throw an Error to the pipeline + DMFTCHECKHR_GOTO(Parent()->QueueEvent(MEError, GUID_NULL, hr, NULL), done); + } + return hr; +} + +/*++ +COutPin::SetState +Description: +State setter for the output pin +--*/ +IFACEMETHODIMP_(VOID) COutPin::SetFirstSample( + _In_ BOOL fisrtSample ) +{ + m_firstSample = fisrtSample; +} + +/*++ +COutPin::FlushQueues +Description: +Called from the device Transform when the output queues have to be flushed + +--*/ +HRESULT COutPin::FlushQueues() +{ + HRESULT hr = S_OK; + CAutoLock Lock( lock() ); + (VOID)m_queue->Clear(); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} +/*++ +COutPin::ChangeMediaTypeFromInpin +Description: +called from the Device Transform when the input media type is changed. This will result in +the xvp being possibly installed in the queue if the media types set on the input +and the output dont match +--*/ +HRESULT COutPin::ChangeMediaTypeFromInpin( + _In_ IMFMediaType* pOutMediaType, + _In_ DeviceStreamState state) +{ + HRESULT hr = S_OK; + CAutoLock Lock(lock()); + // + //Set the state to disabled and while going out we will reset the state back to the requested state + //Flush so that we drop any samples we have in store!! + // + SetState(DeviceStreamState_Disabled); + DMFTCHECKHR_GOTO(FlushQueues(),done); + DMFTCHECKNULL_GOTO(m_queue,done, E_UNEXPECTED); // The queue should alwaye be set + if ( SUCCEEDED( hr ) ) + { + (VOID)setMediaType( pOutMediaType ); + (VOID)SetState( state ); + } +done: + return hr; +} + +/*++ +Description: + called from the IMFdeviceTransform's +--*/ + +IFACEMETHODIMP COutPin::GetOutputStreamInfo( + _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo + ) +{ + HRESULT hr = S_OK; + IMFMediaType* pMediatype = nullptr; + getMediaType( &pMediatype ); + + if (SUCCEEDED(hr) && !pMediatype) { + pMediatype->Release(); + pStreamInfo->cbAlignment = 0; + pStreamInfo->cbSize = 0; + pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; + pStreamInfo->dwFlags |= MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + //We provide our samples.. + } + else { + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + } + return hr; +} + + +/*++ +COutPin::ProcessOutput +Description: + called from the Device Transform when the transform manager demands output samples.. + If we have samples we forward it. + If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have received the transform or not. + If we have received the sample and we are passing out a sample we should reset the trigger set on the Device Transform +--*/ + +IFACEMETHODIMP COutPin::ProcessOutput(_In_ DWORD dwFlags, + _Inout_ MFT_OUTPUT_DATA_BUFFER *pOutputSample, + _Out_ DWORD *pdwStatus + ) +{ + HRESULT hr = S_OK; + ComPtr spSample; + UNREFERENCED_PARAMETER(pdwStatus); + UNREFERENCED_PARAMETER(dwFlags); + CAutoLock lock(lock()); + MFTIME llTime = 0; + if (FAILED(Active())) + { + goto done; + } + DMFTCHECKNULL_GOTO(m_queue, done, MF_E_INVALID_STREAM_STATE); + pOutputSample->dwStatus = S_OK; + + DMFTCHECKHR_GOTO(m_queue->Remove(spSample.GetAddressOf()), done); + + if (FAILED(spSample->GetSampleTime(&llTime))) + { + spSample->SetSampleTime(MFGetSystemTime()); + } + if (m_firstSample) + { + spSample->SetUINT32(MFSampleExtension_Discontinuity,TRUE); + SetFirstSample(FALSE); + } + // + // Any processing before we pass the sample to further in the pipeline should be done here + // PROCESSSAMPLE(pSample); There is a bug in the pipeline and to circumvent that we have to + // keep a reference on the sample. The pipeline is not releasing a reference when the sample + // is fed in ProcessInput. We are explicitly releasing it for the pipeline. + // + pOutputSample->pSample = spSample.Detach(); + pOutputSample->dwStatus = S_OK; +done: + return hr; +} + +/*++ + COutPin::KsProperty +Description: +The KsProperty for the Pin.. this is to reroute all pin kscontrols to the input pin +--*/ +IFACEMETHODIMP COutPin::KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ) +{ + // + //Route it to input pin + // + return m_spIkscontrol->KsProperty(pProperty, + ulPropertyLength, + pPropertyData, + ulDataLength, + pBytesReturned); +} + diff --git a/avstream/avscamera/DMFT/basepin.h b/avstream/avscamera/DMFT/basepin.h new file mode 100644 index 000000000..8051188a4 --- /dev/null +++ b/avstream/avscamera/DMFT/basepin.h @@ -0,0 +1,568 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#pragma once +#include "stdafx.h" + +extern DeviceStreamState pinStateTransition[][4]; + + +class CPinQueue; +class CPinState; +class CMultipinMft; + +class CBasePin: + public IMFAttributes, + public IKsControl +{ +public: + CBasePin( _In_ ULONG _id=0, _In_ CMultipinMft *parent=NULL); + + virtual ~CBasePin() = 0; + virtual IFACEMETHODIMP_(DeviceStreamState) GetState(); + virtual IFACEMETHODIMP_(DeviceStreamState) SetState( _In_ DeviceStreamState State); + + + // + //IUnknown Interface functions + // + + IFACEMETHODIMP_(ULONG) AddRef( + void + ) + { + return InterlockedIncrement(&m_nRefCount); + } + IFACEMETHODIMP_(ULONG) Release( + void + ) + { + ULONG uCount = InterlockedDecrement(&m_nRefCount); + if (uCount == 0) + { + delete this; + } + return uCount; + } + + IFACEMETHODIMP_(HRESULT) QueryInterface( + _In_ REFIID riid, + _Outptr_result_maybenull_ void **ppvObject + ); + // + // IKsControl Interface functions + // + + IFACEMETHODIMP KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ) + { + if ( m_spIkscontrol!=nullptr ) + { + return m_spIkscontrol->KsProperty(pProperty, + ulPropertyLength, + pPropertyData, + ulDataLength, + pBytesReturned); + } + else + { + return E_NOTIMPL; + } + } + virtual IFACEMETHODIMP FlushQueues( + ) + { + return S_OK; + } + // + // NOOPs for this iteration.. + // + IFACEMETHODIMP KsMethod( + _In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod, + _In_ ULONG ulMethodLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pMethodData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ) + { + UNREFERENCED_PARAMETER(pBytesReturned); + UNREFERENCED_PARAMETER(ulDataLength); + UNREFERENCED_PARAMETER(pMethodData); + UNREFERENCED_PARAMETER(pMethod); + UNREFERENCED_PARAMETER(ulMethodLength); + return S_OK; + } + + IFACEMETHODIMP KsEvent( + _In_reads_bytes_(ulEventLength) PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_updates_bytes_opt_(ulDataLength) LPVOID pEventData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ) + { + UNREFERENCED_PARAMETER(pBytesReturned); + UNREFERENCED_PARAMETER(ulDataLength); + UNREFERENCED_PARAMETER(pEventData); + UNREFERENCED_PARAMETER(pEvent); + UNREFERENCED_PARAMETER(ulEventLength); + return S_OK; + } + + // + //IMFAttributes implementation + // + IFACEMETHODIMP GetItem( + _In_ REFGUID guidKey, + _Inout_opt_ PROPVARIANT* pValue + ) + { + return m_spAttributes->GetItem(guidKey, pValue); + } + + IFACEMETHODIMP GetItemType( + _In_ REFGUID guidKey, + _Out_ MF_ATTRIBUTE_TYPE* pType + ) + { + return m_spAttributes->GetItemType(guidKey, pType); + } + + IFACEMETHODIMP CompareItem( + _In_ REFGUID guidKey, + _In_ REFPROPVARIANT Value, + _Out_ BOOL* pbResult + ) + { + return m_spAttributes->CompareItem(guidKey, Value, pbResult); + } + + IFACEMETHODIMP Compare( + _In_ IMFAttributes* pTheirs, + _In_ MF_ATTRIBUTES_MATCH_TYPE MatchType, + _Out_ BOOL* pbResult + ) + { + return m_spAttributes->Compare(pTheirs, MatchType, pbResult); + } + + IFACEMETHODIMP GetUINT32( + _In_ REFGUID guidKey, + _Out_ UINT32* punValue + ) + { + return m_spAttributes->GetUINT32(guidKey, punValue); + } + + IFACEMETHODIMP GetUINT64( + _In_ REFGUID guidKey, + _Out_ UINT64* punValue + ) + { + return m_spAttributes->GetUINT64(guidKey, punValue); + } + + IFACEMETHODIMP GetDouble( + _In_ REFGUID guidKey, + _Out_ double* pfValue + ) + { + return m_spAttributes->GetDouble(guidKey, pfValue); + } + + IFACEMETHODIMP GetGUID( + _In_ REFGUID guidKey, + _Out_ GUID* pguidValue + ) + { + return m_spAttributes->GetGUID(guidKey, pguidValue); + } + + IFACEMETHODIMP GetStringLength( + _In_ REFGUID guidKey, + _Out_ UINT32* pcchLength + ) + { + return m_spAttributes->GetStringLength(guidKey, pcchLength); + } + + IFACEMETHODIMP GetString( + _In_ REFGUID guidKey, + _Out_writes_(cchBufSize) LPWSTR pwszValue, + _In_ UINT32 cchBufSize, + _Inout_opt_ UINT32* pcchLength + ) + { + return m_spAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength); + } + + IFACEMETHODIMP GetAllocatedString( + _In_ REFGUID guidKey, + _Out_writes_(*pcchLength + 1) LPWSTR* ppwszValue, + _Inout_ UINT32* pcchLength + ) + { + return m_spAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength); + } + + IFACEMETHODIMP GetBlobSize( + _In_ REFGUID guidKey, + _Out_ UINT32* pcbBlobSize + ) + { + return m_spAttributes->GetBlobSize(guidKey, pcbBlobSize); + } + + IFACEMETHODIMP GetBlob( + _In_ REFGUID guidKey, + _Out_writes_(cbBufSize) UINT8* pBuf, + UINT32 cbBufSize, + _Inout_ UINT32* pcbBlobSize + ) + { + return m_spAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize); + } + + IFACEMETHODIMP GetAllocatedBlob( + __RPC__in REFGUID guidKey, + __RPC__deref_out_ecount_full_opt(*pcbSize) UINT8** ppBuf, + __RPC__out UINT32* pcbSize + ) + { + return m_spAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize); + } + + IFACEMETHODIMP GetUnknown( + __RPC__in REFGUID guidKey, + __RPC__in REFIID riid, + __RPC__deref_out_opt LPVOID *ppv + ) + { + return m_spAttributes->GetUnknown(guidKey, riid, ppv); + } + + IFACEMETHODIMP SetItem( + _In_ REFGUID guidKey, + _In_ REFPROPVARIANT Value + ) + { + return m_spAttributes->SetItem(guidKey, Value); + } + + IFACEMETHODIMP DeleteItem( + _In_ REFGUID guidKey + ) + { + return m_spAttributes->DeleteItem(guidKey); + } + + IFACEMETHODIMP DeleteAllItems() + { + return m_spAttributes->DeleteAllItems(); + } + + IFACEMETHODIMP SetUINT32( + _In_ REFGUID guidKey, + _In_ UINT32 unValue + ) + { + return m_spAttributes->SetUINT32(guidKey, unValue); + } + + IFACEMETHODIMP SetUINT64( + _In_ REFGUID guidKey, + _In_ UINT64 unValue + ) + { + return m_spAttributes->SetUINT64(guidKey, unValue); + } + + IFACEMETHODIMP SetDouble( + _In_ REFGUID guidKey, + _In_ double fValue + ) + { + return m_spAttributes->SetDouble(guidKey, fValue); + } + + IFACEMETHODIMP SetGUID( + _In_ REFGUID guidKey, + _In_ REFGUID guidValue + ) + { + return m_spAttributes->SetGUID(guidKey, guidValue); + } + + IFACEMETHODIMP SetString( + _In_ REFGUID guidKey, + _In_ LPCWSTR wszValue + ) + { + return m_spAttributes->SetString(guidKey, wszValue); + } + + IFACEMETHODIMP SetBlob( + _In_ REFGUID guidKey, + _In_reads_(cbBufSize) const UINT8* pBuf, + UINT32 cbBufSize + ) + { + return m_spAttributes->SetBlob(guidKey, pBuf, cbBufSize); + } + + IFACEMETHODIMP SetUnknown( + _In_ REFGUID guidKey, + _In_ IUnknown* pUnknown + ) + { + return m_spAttributes->SetUnknown(guidKey, pUnknown); + } + + IFACEMETHODIMP LockStore() + { + return m_spAttributes->LockStore(); + } + + IFACEMETHODIMP UnlockStore() + { + return m_spAttributes->UnlockStore(); + } + + IFACEMETHODIMP GetCount( + _Out_ UINT32* pcItems + ) + { + return m_spAttributes->GetCount(pcItems); + } + + IFACEMETHODIMP GetItemByIndex( + UINT32 unIndex, + _Out_ GUID* pguidKey, + _Inout_ PROPVARIANT* pValue + ) + { + return m_spAttributes->GetItemByIndex(unIndex, pguidKey, pValue); + } + + IFACEMETHODIMP CopyAllItems( + _In_ IMFAttributes* pDest + ) + { + return m_spAttributes->CopyAllItems(pDest); + } + + // + //Helper Functions + // + __requires_lock_held(m_lock) + __inline HRESULT Active() + { + return (m_state == DeviceStreamState_Run)?S_OK:HRESULT_FROM_WIN32(ERROR_INVALID_STATE); + } + __inline DWORD streamId() + { + return m_StreamId; + } + + __inline VOID setMediaType(_In_opt_ IMFMediaType *pMediaType) + { + m_setMediaType = pMediaType; + } + + __inline HRESULT getMediaType(_Outptr_opt_result_maybenull_ IMFMediaType **ppMediaType) + { + HRESULT hr = S_OK; + if (!ppMediaType) + return E_INVALIDARG; + + if (m_setMediaType != nullptr) + { + hr = m_setMediaType.CopyTo(ppMediaType); + } + else + { + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + } + return hr; + } + + __inline IFACEMETHODIMP getPinAttributes (_In_ IMFAttributes **ppAttributes) + { + return QueryInterface( IID_PPV_ARGS(ppAttributes) ); + } + + IFACEMETHODIMP AddMediaType( + _Inout_ DWORD *pos, + _In_ IMFMediaType *pMediatype); /*Filling the media types data structure*/ + IFACEMETHODIMP GetMediaTypeAt( + _In_ DWORD pos, + _Outptr_result_maybenull_ IMFMediaType **pMediaType); /* getting the data from the data structure*/ + IFACEMETHODIMP_(BOOL) IsMediaTypeSupported( + _In_ IMFMediaType *pMediaType, + _When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_) + IMFMediaType **ppIMFMediaTypeFull); + IFACEMETHODIMP GetOutputAvailableType( + _In_ DWORD dwTypeIndex, + _Out_opt_ IMFMediaType **ppType); + + VOID SetD3DManager(_In_opt_ IUnknown* pManager); + VOID SetWorkQueue(_In_ DWORD dwQueueId) + { + m_dwWorkQueueId = dwQueueId; + } +protected: + // + //Inline helper functions + // + _inline CMultipinMft* Parent() + { + return m_Parent; + } + __inline HRESULT setAttributes(_In_ IMFAttributes* _pAttributes) + { + m_spAttributes = _pAttributes; + return S_OK; + } + __inline CCritSec& lock() + { + return m_lock; + } + IMFMediaTypeArray m_listOfMediaTypes; + ComPtr m_spAttributes; + ComPtr m_spIkscontrol; + DeviceStreamState m_state; + ComPtr m_spDxgiManager; + DWORD m_dwWorkQueueId; +private: + ULONG m_StreamId; /*Device Stream Id*/ + CCritSec m_lock; /*This is only used to change the reference count i.e. active users of this stream*/ + ComPtr m_setMediaType; + CMultipinMft* m_Parent; + ULONG m_nRefCount; +}; + + + +class CInPin: public CBasePin{ +public: + CInPin( _In_opt_ IMFAttributes*, _In_ ULONG ulPinId = 0, _In_ CMultipinMft *pParent=NULL); + ~CInPin(); + + IFACEMETHODIMP Init( + _In_ IMFDeviceTransform * + ); + IFACEMETHODIMP_(VOID) ConnectPin( + _In_ CBasePin * + ); + IFACEMETHODIMP SendSample( + _In_ IMFSample * + ); + HRESULT GenerateMFMediaTypeListFromDevice( + _In_ UINT uiStreamId + ); + IFACEMETHODIMP WaitForSetInputPinMediaChange( + ); + // + //Corresponding IMFDeviceTransform functions for the Pin + // + HRESULT GetInputStreamPreferredState( + _Inout_ DeviceStreamState *value, + _Outptr_opt_result_maybenull_ IMFMediaType** ppMediaType + ); + HRESULT SetInputStreamState( + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags + ); + + virtual IFACEMETHODIMP FlushQueues() + { + return S_OK; + } + // + //Inline functions + // + __inline IMFMediaType* getPreferredMediaType() + { + return m_spPrefferedMediaType.Get(); + } + __inline VOID setPreferredMediaType( _In_ IMFMediaType *pMediaType) + { + m_spPrefferedMediaType = pMediaType; + } + __inline DeviceStreamState setPreferredStreamState(_In_ DeviceStreamState streamState) + { + return (DeviceStreamState)InterlockedCompareExchange((LONG*)&m_preferredStreamState, (LONG)streamState, (LONG)m_preferredStreamState); + } + __inline DeviceStreamState getPreferredStreamState() + { + return m_preferredStreamState; + } + + IFACEMETHODIMP_( VOID) ShutdownPin(); + +protected: + ComPtr m_spSourceTransform; /*Source Transform i.e. DevProxy*/ + GUID m_stStreamType; /*GUID representing the GUID*/ + ComPtr m_outpin; //Only one output pin connected per input pin. There can be multiple pins connected and this could be a list + DeviceStreamState m_preferredStreamState; + ComPtr m_spPrefferedMediaType; + HANDLE m_waitInputMediaTypeWaiter; /*Set when the input media type is changed*/ + +}; + + + +class COutPin: public CBasePin{ +public: + COutPin( + _In_ ULONG id = 0, + _In_opt_ CMultipinMft *pparent = NULL, + _In_ IKsControl* iksControl=NULL + ); + ~COutPin(); + IFACEMETHODIMP FlushQueues(); + IFACEMETHODIMP AddPin( + _In_ DWORD pinId + ); + virtual IFACEMETHODIMP AddSample( + _In_ IMFSample *pSample, + _In_ CBasePin *inPin + ); + IFACEMETHODIMP GetOutputStreamInfo( + _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo + ); + virtual IFACEMETHODIMP ChangeMediaTypeFromInpin( + _In_ IMFMediaType* pOutMediaType, + _In_ DeviceStreamState state ); + IFACEMETHODIMP ProcessOutput ( + _In_ DWORD dwFlags, + _Inout_ MFT_OUTPUT_DATA_BUFFER *pOutputSample, + _Out_ DWORD *pdwStatus + ); + IFACEMETHODIMP KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ); + IFACEMETHODIMP_(VOID) SetFirstSample( + _In_ BOOL + ); + + UINT32 GetMediatypeCount() + { + return (UINT32)m_listOfMediaTypes.size(); + } + +protected: + CPinQueue * m_queue; /* Queue where the sample will be stored*/ + BOOL m_firstSample; +}; + diff --git a/avstream/avscamera/DMFT/common.h b/avstream/avscamera/DMFT/common.h new file mode 100644 index 000000000..b6e636a87 --- /dev/null +++ b/avstream/avscamera/DMFT/common.h @@ -0,0 +1,360 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// + +#pragma once + +#ifndef MF_WPP +#define DMFTRACE(...) +#endif + +// +// The below guid is used to register the GUID as the Device Transform. This should be adeed to the +// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\ and under the +// GLOBAL#\Device Parameters key, add a CameraDeviceMFTCLSID value, and set its value to +// {836E84ED-45E9-4160-A79D-771F1C718CD2} for the Pipeline to pick up the Transform. +// + +DEFINE_GUID(CLSID_AvsCameraDMFT, 0x836e84ed, 0x45e9, 0x4160, 0xa7, 0x9d, 0x77, 0x1f, 0x1c, 0x71, 0x8c, 0xd2); + +#ifdef DBG +#define mf_assert(a) if(!a) DebugBreak() +#else +#define mf_assert(a) +#endif + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID(CtlGUID_DMFTTrace, (CBCCA12E, 9472, 409D, A1B1, 753C98BF03C0), \ + WPP_DEFINE_BIT(DMFT_INIT) \ + WPP_DEFINE_BIT(DMFT_CONTROL) \ + WPP_DEFINE_BIT(DMFT_GENERAL) \ + ) + +#define WPP_LEVEL_FLAG_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) +#define WPP_LEVEL_FLAG_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) +#define WPP_FLAG_LEVEL_LOGGER(flags,lvl) WPP_LEVEL_LOGGER(flags) +#define WPP_FLAG_LEVEL_ENABLED(flags, lvl) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) + +#define WPP_CHECK_LEVEL_ENABLED(flags, level) 1 + +//begin_wpp config +// +// USEPREFIX (DMFTCHECKNULL_GOTO,"%!STDPREFIX!"); +// FUNC DMFTCHECKNULL_GOTO(CHECKNULLGOTO_EXP,LABEL,HR,...); +// USESUFFIX (DMFTCHECKNULL_GOTO," failed %!HRESULT!\n", hr); +// +//end_wpp + +//begin_wpp config +// +// USEPREFIX (DMFTCHECKHR_GOTO,"%!STDPREFIX!"); +// FUNC DMFTCHECKHR_GOTO(CHECKHRGOTO_EXP,LABEL,...); +// USESUFFIX (DMFTCHECKHR_GOTO," failed %!HRESULT!\n", hr); +// + +//end_wpp + +#define WPP_CHECKNULLGOTO_EXP_LABEL_HR_PRE(pointer,label,HR) if( pointer == NULL ) { hr = HR; +#define WPP_CHECKNULLGOTO_EXP_LABEL_HR_POST(pointer,label,HR) ; goto label; } + +#define WPP_CHECKNULLGOTO_EXP_LABEL_HR_LOGGER(pointer,label,HR) WPP_LEVEL_LOGGER( DMFT_INIT ) +#define WPP_CHECKNULLGOTO_EXP_LABEL_HR_ENABLED(pointer,label,HR) WPP_CHECK_LEVEL_ENABLED( DMFT_INIT, TP_ERROR ) + +#define WPP_CHECKHRGOTO_EXP_LABEL_PRE(HR,label) if( FAILED( hr = HR ) ) { +#define WPP_CHECKHRGOTO_EXP_LABEL_POST(HR,label) ; goto label; } + +#define WPP_CHECKHRGOTO_EXP_LABEL_LOGGER(HR, label) WPP_LEVEL_LOGGER( DMFT_INIT ) +#define WPP_CHECKHRGOTO_EXP_LABEL_ENABLED(HR, label) WPP_CHECK_LEVEL_ENABLED( DMFT_INIT, TP_ERROR ) + + +// Give it checkhr and checknull definitions if some future generations of visual studio remove the wpp processor support + +//#if !defined DMFTCHECKHR_GOTO +//#define DMFTCHECKHR_GOTO(a,b) {hr=(a); if(FAILED(hr)){goto b;}} +//#endif +// +//#if !defined DMFTCHECKNULL_GOTO +//#define DMFTCHECKNULL_GOTO(a,b,c) {if(!a) {hr = c; goto b;}} +//#endif + +#define SAFE_ADDREF(p) if( NULL != p ) { ( p )->AddRef(); } +#define SAFE_DELETE(p) delete p; p = NULL; +#define SAFE_SHUTDELETE(p) if( NULL != p ) { ( p )->Shutdown(); delete p; p = NULL; } +#define SAFE_RELEASE(p) if( NULL != p ) { ( p )->Release(); p = NULL; } +#define SAFE_SHUTRELEASE(p) if( NULL != p ) { ( p )->Shutdown(); ( p )->Release(); p = NULL; } +#define SAFE_CLOSERELEASE(p) if( NULL != p ) { ( p )->Close( TRUE ); ( p )->Release(); p = NULL; } +#define SAFE_COTASKMEMFREE(p) CoTaskMemFree( p ); p = NULL; +#define SAFE_SYSFREESTRING(p) SysFreeString( p ); p = NULL; +#define SAFE_ARRAYDELETE(p) delete [] p; p = NULL; +#define SAFE_BYTEARRAYDELETE(p) delete [] (BYTE*) p; p = NULL; +#define SAFE_CLOSEHANDLE(h) { if(INVALID_HANDLE_VALUE != (h)) { ::CloseHandle(h); (h) = INVALID_HANDLE_VALUE; } } + + +#define SAFERELEASE(x) \ +if (x) {\ + x->Release(); \ + x = NULL; \ +} + +#if !defined(_IKsControl_) +#define _IKsControl_ +interface DECLSPEC_UUID("28F54685-06FD-11D2-B27A-00A0C9223196") IKsControl; +#undef INTERFACE +#define INTERFACE IKsControl +DECLARE_INTERFACE_(IKsControl, IUnknown) +{ + STDMETHOD(KsProperty)( + THIS_ + IN PKSPROPERTY Property, + IN ULONG PropertyLength, + IN OUT LPVOID PropertyData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; + STDMETHOD(KsMethod)( + THIS_ + IN PKSMETHOD Method, + IN ULONG MethodLength, + IN OUT LPVOID MethodData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; + STDMETHOD(KsEvent)( + THIS_ + IN PKSEVENT Event OPTIONAL, + IN ULONG EventLength, + IN OUT LPVOID EventData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; +}; +#endif //!defined(_IKsControl_) + +//Forward defintion +class CBasePin; +////////////////////////////////////////////////////////////////////////// +// CCritSec +// Description: Wraps a critical section. +////////////////////////////////////////////////////////////////////////// + +class CCritSec +{ +private: + CRITICAL_SECTION m_criticalSection; +public: + CCritSec(); + ~CCritSec(); + _Requires_lock_not_held_(m_criticalSection) _Acquires_lock_(m_criticalSection) + void Lock(); + _Requires_lock_held_(m_criticalSection) _Releases_lock_(m_criticalSection) + void Unlock(); +}; + + +////////////////////////////////////////////////////////////////////////// +// CAutoLock +// Description: Provides automatic locking and unlocking of a +// of a critical section. +////////////////////////////////////////////////////////////////////////// + +class CAutoLock +{ +protected: + CCritSec *m_pCriticalSection; +public: + _Acquires_lock_(this->m_pCriticalSection->m_criticalSection) + CAutoLock(CCritSec& crit); + _Acquires_lock_(this->m_pCriticalSection->m_criticalSection) + CAutoLock(CCritSec* crit); + _Releases_lock_(this->m_pCriticalSection->m_criticalSection) + ~CAutoLock(); +}; + +class MediaBufferLock +{ +public: + MediaBufferLock(_In_ IMFMediaBuffer* pBuffer) : + m_bLocked(false) + { + m_spBuffer = pBuffer; + } + + HRESULT LockBuffer( + _Outptr_result_bytebuffer_to_(*pcbMaxLength, *pcbCurrentLength) BYTE** ppbBuffer, + _Out_opt_ DWORD* pcbMaxLength, + _Out_opt_ DWORD* pcbCurrentLength) + { + if (!m_spBuffer) + { + return E_INVALIDARG; + } + + HRESULT hr = m_spBuffer->Lock(ppbBuffer, pcbMaxLength, pcbCurrentLength); + if (FAILED(hr)) + { + return hr; + } + m_bLocked = true; + return S_OK; + } + + ~MediaBufferLock() + { + if (m_spBuffer && m_bLocked) + { + //Unlock fails only if we did not lock it first + (void)m_spBuffer->Unlock(); + } + } + +private: + ComPtr m_spBuffer; + bool m_bLocked; +}; + +typedef std::vector> IMFMediaTypeArray; +typedef std::vector> CBasePinArray; +typedef std::vector> IMFSampleList; +typedef std::pair< std::multimap::iterator, std::multimap::iterator > MMFTMMAPITERATOR; + +STDMETHODIMP_(BOOL) IsPinStateInActive( + _In_ DeviceStreamState state + ); + + +template +HRESULT ExceptionBoundary(Lambda&& lambda) +{ + try + { + lambda(); + return S_OK; + } + catch (const _com_error& e) + { + return e.Error(); + } + catch (const std::bad_alloc&) + { + return E_OUTOFMEMORY; + } + catch (const std::out_of_range&) + { + return MF_E_INVALIDINDEX; + } + catch (...) + { + return E_UNEXPECTED; + } +} + +// +// Object LifeTime manager. The Class has a global variable which +// maintains a reference count of the number of objects in the +// system managed by the DLL. +// +class CDMFTModuleLifeTimeManager{ +public: + CDMFTModuleLifeTimeManager() + { + InterlockedIncrement(&s_lObjectCount); + } + ~CDMFTModuleLifeTimeManager() + { + InterlockedDecrement(&s_lObjectCount); + } + static long GetDMFTObjCount() + { + return s_lObjectCount; + } +private: + static volatile long s_lObjectCount; +}; + +class CPinQueue : public IUnknown +{ +public: + CPinQueue(_In_ DWORD _inPinId, _In_ IMFDeviceTransform* pTransform = nullptr); + ~CPinQueue(); + + STDMETHODIMP Insert(_In_ IMFSample* pSample); + STDMETHODIMP Remove(_Outptr_result_maybenull_ IMFSample** pSample); + STDMETHODIMP_(VOID) Clear(); + + // + // Inline functions + // + __inline BOOL Empty() + { + return (!m_sampleList.size()); + } + __inline DWORD pinStreamId() + { + return m_dwInPinId; + } + __inline GUID pinCategory() + { + if (IsEqualCLSID(m_streamCategory, GUID_NULL)) + { + ComPtr spAttributes; + if (SUCCEEDED(m_pTransform->GetOutputStreamAttributes(pinStreamId(), spAttributes.ReleaseAndGetAddressOf()))) + { + (VOID) spAttributes->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &m_streamCategory); + } + } + return m_streamCategory; + } + + STDMETHODIMP QueryInterface(REFIID riid, void** ppv) + { + HRESULT hr = S_OK; + if (ppv != nullptr) + { + *ppv = nullptr; + if (riid == __uuidof(IUnknown)) + { + AddRef(); + *ppv = static_cast(this); + } + else + { + hr = E_NOINTERFACE; + } + } + else + { + hr = E_POINTER; + } + return hr; + } + + STDMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&m_cRef); + } + STDMETHODIMP_(ULONG) Release() + { + long cRef = InterlockedDecrement(&m_cRef); + if (cRef == 0) + { + delete this; + } + return cRef; + } + +private: + DWORD m_dwInPinId; /* This is the input pin */ + IMFSampleList m_sampleList; /* List storing the samples */ + IMFDeviceTransform* m_pTransform; /* Weak reference to the the device MFT */ + GUID m_streamCategory; + ULONG m_cRef; +}; + + +HRESULT ProcessMetadata(_In_ IMFSample* pSample); +// Metadata defintions + diff --git a/avstream/avscamera/DMFT/dllmain.cpp b/avstream/avscamera/DMFT/dllmain.cpp new file mode 100644 index 000000000..5a988320c --- /dev/null +++ b/avstream/avscamera/DMFT/dllmain.cpp @@ -0,0 +1,354 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +////////////////////////////////////////////////////////////////////////// +// +// dllmain.cpp : Implements DLL exports and COM class factory +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Note: This source file implements the class factory for the transform, +// plus the following DLL functions: +// - DllMain +// - DllCanUnloadNow +// - DllRegisterServer +// - DllUnregisterServer +// - DllGetClassObject +// +////////////////////////////////////////////////////////////////////////// +#include "stdafx.h" + +#ifdef MF_WPP +#include "dllmain.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif + +// +// The static variable needed to check the object count of the deviceMFts loaded. +// + +volatile long CDMFTModuleLifeTimeManager::s_lObjectCount = 0; + + + +HRESULT RegisterObject(HMODULE hModule, REFGUID guid, PCWSTR pszDescription, PCWSTR pszThreadingModel); + +HRESULT UnregisterObject(const GUID& guid); + + +// Module Ref count +long g_cRefModule = 0; + +// Handle to the DLL's module +HMODULE g_hModule = NULL; + +void DllAddRef() +{ + InterlockedIncrement(&g_cRefModule); +} + +void DllRelease() +{ + InterlockedDecrement(&g_cRefModule); +} + +// +// IClassFactory implementation +// + +typedef HRESULT (*PFNCREATEINSTANCE)(REFIID riid, void **ppvObject); +struct CLASS_OBJECT_INIT +{ + const CLSID *pClsid; + PFNCREATEINSTANCE pfnCreate; +}; + +// Classes supported by this module: +const CLASS_OBJECT_INIT c_rgClassObjectInit[] = +{ + { &CLSID_AvsCameraDMFT, MFT_CreateInstance }, +}; + +class CClassFactory : public IClassFactory +{ +public: + + static HRESULT CreateInstance( + REFCLSID clsid, // The CLSID of the object to create (from DllGetClassObject) + const CLASS_OBJECT_INIT *pClassObjectInits, // Array of class factory data. + size_t cClassObjectInits, // Number of elements in the array. + REFIID riid, // The IID of the interface to retrieve (from DllGetClassObject) + void **ppv // Receives a pointer to the interface. + ) + { + *ppv = NULL; + + HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; + + for (size_t i = 0; i < cClassObjectInits; i++) + { + if (clsid == *pClassObjectInits[i].pClsid) + { + IClassFactory *pClassFactory = new (std::nothrow) CClassFactory(pClassObjectInits[i].pfnCreate); + + if (pClassFactory) + { + hr = pClassFactory->QueryInterface(riid, ppv); + pClassFactory->Release(); + } + else + { + hr = E_OUTOFMEMORY; + } + break; // match found + } + } + return hr; + } + + // IUnknown methods + IFACEMETHODIMP QueryInterface(REFIID riid, void ** ppv) + { +#if 0 + static const QITAB qit[] = + { + QITABENT(CClassFactory, IClassFactory), + { 0 } + }; + return QISearch(this, qit, riid, ppv); + +#else + if (riid == __uuidof(IClassFactory)) + { + *ppv = static_cast< IClassFactory* >(this); + AddRef(); + } + return S_OK; +#endif + } + + IFACEMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&m_cRef); + } + + IFACEMETHODIMP_(ULONG) Release() + { + long cRef = InterlockedDecrement(&m_cRef); + if (cRef == 0) + { + delete this; + } + return cRef; + } + + // IClassFactory methods + + IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv) + { + return punkOuter ? CLASS_E_NOAGGREGATION : m_pfnCreate(riid, ppv); + } + + IFACEMETHODIMP LockServer(BOOL fLock) + { + if (fLock) + { + DllAddRef(); + } + else + { + DllRelease(); + } + return S_OK; + } + +private: + + CClassFactory(PFNCREATEINSTANCE pfnCreate) : m_cRef(1), m_pfnCreate(pfnCreate) + { + DllAddRef(); + } + + ~CClassFactory() + { + DllRelease(); + } + + long m_cRef; + PFNCREATEINSTANCE m_pfnCreate; +}; + + + +// +// Standard DLL functions +// + +IFACEMETHODIMP_(BOOL) WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void*) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hModule = (HMODULE)hInstance; + DisableThreadLibraryCalls(hInstance); +#ifdef MF_WPP + WPP_INIT_TRACING(L"MultiPinMft"); +#endif + } + else + if (dwReason == DLL_PROCESS_DETACH) + { +#ifdef MF_WPP + WPP_CLEANUP(); +#endif + } + return TRUE; +} + +IFACEMETHODIMP DllCanUnloadNow() +{ + HRESULT hr = ((g_cRefModule == 0) && (CDMFTModuleLifeTimeManager::GetDMFTObjCount() == 0)) ? S_OK : S_FALSE; + // + // Debug object lifetimes + // + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! returning %d %d %!HRESULT!", + g_cRefModule, + CDMFTModuleLifeTimeManager::GetDMFTObjCount(), + hr); + + return hr; + +} + +_Check_return_ +STDAPI DllGetClassObject(_In_ REFCLSID clsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) +{ + return CClassFactory::CreateInstance(clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv); +} + +IFACEMETHODIMP DllRegisterServer() +{ + assert(g_hModule != NULL); + + // Register the CLSID for CoCreateInstance. + HRESULT hr = RegisterObject(g_hModule, CLSID_AvsCameraDMFT, TEXT("Multiple MFTs"), TEXT("Both")); + + return hr; +} + +IFACEMETHODIMP DllUnregisterServer() +{ + // Unregister the CLSID. + UnregisterObject(CLSID_AvsCameraDMFT); + + return S_OK; +} + + +// Converts a CLSID into a string with the form "CLSID\{clsid}" +IFACEMETHODIMP CreateObjectKeyName(REFGUID guid, _Out_writes_(cchMax) PWSTR pszName, DWORD cchMax) +{ + const DWORD chars_in_guid = 39; + + // convert CLSID uuid to string + OLECHAR szCLSID[chars_in_guid]; + HRESULT hr = StringFromGUID2(guid, szCLSID, chars_in_guid); + if (SUCCEEDED(hr)) + { + // Create a string of the form "CLSID\{clsid}" + hr = StringCchPrintf((STRSAFE_LPWSTR)pszName, cchMax, TEXT("Software\\Classes\\CLSID\\%ls"), szCLSID); + } + return hr; +} + +// Creates a registry key (if needed) and sets the default value of the key +IFACEMETHODIMP CreateRegKeyAndValue(HKEY hKey, PCWSTR pszSubKeyName, PCWSTR pszValueName, + PCWSTR pszData, PHKEY phkResult) +{ + *phkResult = NULL; + LONG lRet = RegCreateKeyExW( + hKey, pszSubKeyName, + 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, NULL, phkResult, NULL); + + if (lRet == ERROR_SUCCESS) + { + lRet = RegSetValueExW( + (*phkResult), + pszValueName, 0, REG_SZ, + (LPBYTE) pszData, + ((DWORD) wcslen(pszData) + 1) * sizeof(WCHAR) + ); + + if (lRet != ERROR_SUCCESS) + { + RegCloseKey(*phkResult); + } + } + + return HRESULT_FROM_WIN32(lRet); +} + +// Creates the registry entries for a COM object. + +HRESULT RegisterObject(HMODULE hModule, const GUID& guid, const TCHAR *pszDescription, const TCHAR *pszThreadingModel) +{ + HKEY hKey = NULL; + HKEY hSubkey = NULL; + TCHAR achTemp[MAX_PATH]; + + // Create the name of the key from the object's CLSID + HRESULT hr = CreateObjectKeyName(guid, achTemp, MAX_PATH); + + // Create the new key. + if (SUCCEEDED(hr)) + { + hr = CreateRegKeyAndValue(HKEY_LOCAL_MACHINE, achTemp, NULL, pszDescription,&hKey); + } + + if (SUCCEEDED(hr)) + { + (void)GetModuleFileName(hModule, achTemp, MAX_PATH); + + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + // Create the "InprocServer32" subkey + if (SUCCEEDED(hr)) + { + hr = CreateRegKeyAndValue(hKey, L"InProcServer32", NULL, achTemp, &hSubkey); + RegCloseKey(hSubkey); + } + + // Add a new value to the subkey, for "ThreadingModel" = + if (SUCCEEDED(hr)) + { + hr = CreateRegKeyAndValue(hKey, L"InProcServer32", L"ThreadingModel", pszThreadingModel, &hSubkey); + RegCloseKey(hSubkey); + } + + // close hkeys + RegCloseKey(hKey); + return hr; +} + +// Deletes the registry entries for a COM object. + +HRESULT UnregisterObject(const GUID& guid) +{ + WCHAR achTemp[MAX_PATH]; + + HRESULT hr = CreateObjectKeyName(guid, achTemp, MAX_PATH); + if (SUCCEEDED(hr)) + { + // Delete the key recursively. + LONG lRes = RegDeleteTree(HKEY_LOCAL_MACHINE, achTemp); + hr = HRESULT_FROM_WIN32(lRes); + } + return hr; +} + + diff --git a/avstream/avscamera/DMFT/mftpeventgenerator.cpp b/avstream/avscamera/DMFT/mftpeventgenerator.cpp new file mode 100644 index 000000000..1e510cfa2 --- /dev/null +++ b/avstream/avscamera/DMFT/mftpeventgenerator.cpp @@ -0,0 +1,234 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// + +#include "stdafx.h" +#include "common.h" +#include "mftpeventgenerator.h" + + + +#ifdef MF_WPP +#include "mftpeventgenerator.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif + +CMediaEventGenerator::CMediaEventGenerator () : + m_nRefCount(0), + m_pQueue(NULL), + m_bShutdown(FALSE) +{ + //Call this explicit... + InitMediaEventGenerator(); +} + +STDMETHODIMP CMediaEventGenerator::InitMediaEventGenerator( + void + ) +{ + + return MFCreateEventQueue(&m_pQueue); + +} + +STDMETHODIMP_(ULONG) CMediaEventGenerator::AddRef( + void + ) +{ + return InterlockedIncrement(&m_nRefCount); +} + +STDMETHODIMP_(ULONG) CMediaEventGenerator::Release( + void + ) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + + if (uCount == 0) + { + delete this; + } + return uCount; +} + +STDMETHODIMP CMediaEventGenerator::QueryInterface( + _In_ REFIID iid, + _COM_Outptr_ void** ppv) +{ + HRESULT hr = S_OK; + + *ppv = NULL; + + if (iid == __uuidof(IUnknown) || iid == __uuidof(IMFMediaEventGenerator)) + { + *ppv = static_cast(this); + AddRef(); + } + else + { + hr = E_NOINTERFACE; + } + + return hr; +} + +// +// IMediaEventGenerator methods +// +STDMETHODIMP CMediaEventGenerator::BeginGetEvent( + _In_ IMFAsyncCallback* pCallback, + _In_ IUnknown* pState + ) +{ + HRESULT hr = S_OK; + m_critSec.Lock(); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pQueue->BeginGetEvent(pCallback, pState); + } + + m_critSec.Unlock(); + + return hr; +} + +STDMETHODIMP CMediaEventGenerator::EndGetEvent( + _In_ IMFAsyncResult* pResult, + _Outptr_result_maybenull_ IMFMediaEvent** ppEvent + ) +{ + HRESULT hr = S_OK; + m_critSec.Lock(); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + hr = m_pQueue->EndGetEvent(pResult, ppEvent); + } + + m_critSec.Unlock(); + + return hr; +} + +STDMETHODIMP CMediaEventGenerator::GetEvent( + _In_ DWORD dwFlags, + _Outptr_result_maybenull_ IMFMediaEvent** ppEvent + ) +{ + // + // Because GetEvent can block indefinitely, it requires + // a slightly different locking strategy. + // + HRESULT hr = S_OK; + IMFMediaEventQueue *pQueue = NULL; + + m_critSec.Lock(); + + hr = CheckShutdown(); + // + // Store the pointer in a local variable, so that another thread + // does not release it after we leave the critical section. + // + if (SUCCEEDED(hr)) + { + pQueue = m_pQueue; + } + + m_critSec.Unlock(); + + if (SUCCEEDED(hr)) + { + hr = pQueue->GetEvent(dwFlags, ppEvent); + } + + return hr; +} + +STDMETHODIMP CMediaEventGenerator::QueueEvent( + _In_ MediaEventType met, + _In_ REFGUID extendedType, + _In_ HRESULT hrStatus, + _In_opt_ const PROPVARIANT* pvValue + ) +{ + HRESULT hr = S_OK; + m_critSec.Lock(); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + + hr = m_pQueue->QueueEventParamVar( + met, + extendedType, + hrStatus, + pvValue + ); + } + + m_critSec.Unlock(); + + return hr; +} + +STDMETHODIMP CMediaEventGenerator::ShutdownEventGenerator( + void + ) +{ + HRESULT hr = S_OK; + + + m_critSec.Lock(); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + if (m_pQueue) + { + hr = m_pQueue->Shutdown(); + } + SAFE_RELEASE(m_pQueue); + m_bShutdown = TRUE; + } + m_critSec.Unlock(); + + return hr; +} + +STDMETHODIMP CMediaEventGenerator::QueueEvent( + _In_ IMFMediaEvent* pEvent + ) +{ + HRESULT hr = S_OK; + m_critSec.Lock(); + + hr = CheckShutdown(); + + if (SUCCEEDED(hr)) + { + if (m_pQueue) + { + hr = m_pQueue->QueueEvent(pEvent); + } + } + + m_critSec.Unlock(); + return hr; +} + +CMediaEventGenerator::~CMediaEventGenerator ( + void + ) +{ + ShutdownEventGenerator(); +} diff --git a/avstream/avscamera/DMFT/mftpeventgenerator.h b/avstream/avscamera/DMFT/mftpeventgenerator.h new file mode 100644 index 000000000..2ddae218f --- /dev/null +++ b/avstream/avscamera/DMFT/mftpeventgenerator.h @@ -0,0 +1,94 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// +#pragma once + +class CMediaEventGenerator : + public IMFMediaEventGenerator +{ + +public: + + // + // IUnknown + // + STDMETHOD_(ULONG, AddRef)( + void + ); + + STDMETHOD_(ULONG, Release)( + void + ); + + STDMETHOD(QueryInterface)( + _In_ REFIID iid, + _COM_Outptr_ void** ppv); + + + // + // IMFMediaEventGenerator + // + STDMETHOD(BeginGetEvent)( + _In_ IMFAsyncCallback* pCallback, + _In_ IUnknown* pState + ); + + STDMETHOD(EndGetEvent)( + _In_ IMFAsyncResult* pResult, + _Outptr_result_maybenull_ IMFMediaEvent** ppEvent + ); + + STDMETHOD(GetEvent)( + _In_ DWORD dwFlags, + _Outptr_result_maybenull_ IMFMediaEvent** ppEvent + ); + + STDMETHOD(QueueEvent)( + _In_ MediaEventType met, + _In_ REFGUID extendedType, + _In_ HRESULT hrStatus, + _In_opt_ const PROPVARIANT* pvValue + ); + + STDMETHOD(QueueEvent)( + _In_ IMFMediaEvent* pEvent + ); + +protected: + + CMediaEventGenerator( + void + ); + + virtual ~CMediaEventGenerator ( + void + ); + // + // Utility Methods + // + STDMETHOD(ShutdownEventGenerator)( + void + ); + + STDMETHOD (InitMediaEventGenerator)( + void + ); + + __inline HRESULT (CheckShutdown)( + void + ) const + { + return (m_bShutdown? MF_E_SHUTDOWN : S_OK); + } + +private: + + long m_nRefCount; + CCritSec m_critSec; + IMFMediaEventQueue* m_pQueue; + BOOL m_bShutdown; +}; diff --git a/avstream/avscamera/DMFT/packages.config b/avstream/avscamera/DMFT/packages.config new file mode 100644 index 000000000..26065b144 --- /dev/null +++ b/avstream/avscamera/DMFT/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/avstream/avscamera/DMFT/stdafx.h b/avstream/avscamera/DMFT/stdafx.h new file mode 100644 index 000000000..d21def931 --- /dev/null +++ b/avstream/avscamera/DMFT/stdafx.h @@ -0,0 +1,47 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +#include +#include +using namespace ABI::Windows::Foundation; +using namespace Microsoft::WRL; + +#include "common.h" +#include "AvsCameraDMFT.h" +#include "basepin.h" +#include "metadataInternal.h" diff --git a/avstream/avscamera/DMFT/stdafxsrc.cpp b/avstream/avscamera/DMFT/stdafxsrc.cpp new file mode 100644 index 000000000..a6f44b0e8 --- /dev/null +++ b/avstream/avscamera/DMFT/stdafxsrc.cpp @@ -0,0 +1,4 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#include "stdafx.h" \ No newline at end of file diff --git a/avstream/avscamera/Package/package.VcxProj b/avstream/avscamera/Package/package.VcxProj index 32eb33549..a570a1fbb 100644 --- a/avstream/avscamera/Package/package.VcxProj +++ b/avstream/avscamera/Package/package.VcxProj @@ -19,8 +19,8 @@ - - {2C0B129E-88F3-479A-AE5D-65609A88BE66} + + {e77657cd-a270-49e1-823a-8a14ff8596c8} {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68} diff --git a/avstream/avscamera/README.md b/avstream/avscamera/README.md index da8e8d65b..2cfde98ce 100644 --- a/avstream/avscamera/README.md +++ b/avstream/avscamera/README.md @@ -15,7 +15,7 @@ The AvsCamera sample provides a pin-centric AVStream capture driver for a simula This sample features strong parameter validation and overflow detection. It provides validation and simulation logic for all advanced camera controls in the CCaptureFilter class. A real camera driver would replace the filter automation table and CSensor and CSynthesizer class hierarchies to produce a new camera driver. -The sample comes with its own MFT0 called AvsCameraMft0.dll. This MFT0 is used to parse metadata supplied in the AvsCamera driver samples. The metadata communications from the driver is primarily a private channel to its MFT0. The MFT0 is responsible for reformatting that information for the capture pipeline. +The sample comes with its own DeviceMFT called AvsCameraMft0.dll. This DeviceMFT is used to parse metadata supplied in the AvsCamera driver samples. The metadata communications from the driver is primarily a private channel to its DeviceMFT. The DeviceMFT is responsible for reformatting that information for the capture pipeline. ## Universal Windows Driver Compliant @@ -23,4 +23,4 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a ## Building the sample -The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraMft0.dll, AvsCamera.inf and AvsCamera.cat. +The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraDMFT.dll, AvsCamera.inf and AvsCamera.cat. diff --git a/avstream/avscamera/avscamera.sln b/avstream/avscamera/avscamera.sln index faa04506b..b358cd908 100644 --- a/avstream/avscamera/avscamera.sln +++ b/avstream/avscamera/avscamera.sln @@ -1,59 +1,65 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34009.444 MinimumVisualStudioVersion = 12.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{174AB66C-6250-4DDB-88C5-856B9D499DB7}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mft0", "Mft0", "{8031E506-AE20-4995-9F28-2D177A1FB319}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sys", "Sys", "{72571B45-7827-4380-8821-38A33FBFF4E2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{9397D285-8C29-4661-A741-F6703E2F5FD6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AvsCameraMft0", "mft0\AvsCameraMft0.vcxproj", "{2C0B129E-88F3-479A-AE5D-65609A88BE66}" + ProjectSection(ProjectDependencies) = postProject + {E77657CD-A270-49E1-823A-8A14FF8596C8} = {E77657CD-A270-49E1-823A-8A14FF8596C8} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AvsCamera", "sys\AvsCamera.vcxproj", "{24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AvsCameraDMFT", "DMFT\AvsCameraDMFT.vcxproj", "{E77657CD-A270-49E1-823A-8A14FF8596C8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DMFT", "DMFT", "{08C63CB6-78C2-44EC-AA24-8CBA0CFEE2E6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9397D285-8C29-4661-A741-F6703E2F5FD6}.Debug|Win32.ActiveCfg = Debug|Win32 {9397D285-8C29-4661-A741-F6703E2F5FD6}.Debug|Win32.Build.0 = Debug|Win32 - {9397D285-8C29-4661-A741-F6703E2F5FD6}.Release|Win32.ActiveCfg = Release|Win32 - {9397D285-8C29-4661-A741-F6703E2F5FD6}.Release|Win32.Build.0 = Release|Win32 {9397D285-8C29-4661-A741-F6703E2F5FD6}.Debug|x64.ActiveCfg = Debug|x64 {9397D285-8C29-4661-A741-F6703E2F5FD6}.Debug|x64.Build.0 = Debug|x64 + {9397D285-8C29-4661-A741-F6703E2F5FD6}.Release|Win32.ActiveCfg = Release|Win32 + {9397D285-8C29-4661-A741-F6703E2F5FD6}.Release|Win32.Build.0 = Release|Win32 {9397D285-8C29-4661-A741-F6703E2F5FD6}.Release|x64.ActiveCfg = Release|x64 {9397D285-8C29-4661-A741-F6703E2F5FD6}.Release|x64.Build.0 = Release|x64 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Debug|Win32.ActiveCfg = Debug|Win32 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Debug|Win32.Build.0 = Debug|Win32 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Release|Win32.ActiveCfg = Release|Win32 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Release|Win32.Build.0 = Release|Win32 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Debug|x64.ActiveCfg = Debug|x64 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Debug|x64.Build.0 = Debug|x64 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Release|x64.ActiveCfg = Release|x64 - {2C0B129E-88F3-479A-AE5D-65609A88BE66}.Release|x64.Build.0 = Release|x64 {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Debug|Win32.ActiveCfg = Debug|Win32 {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Debug|Win32.Build.0 = Debug|Win32 - {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Release|Win32.ActiveCfg = Release|Win32 - {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Release|Win32.Build.0 = Release|Win32 {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Debug|x64.ActiveCfg = Debug|x64 {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Debug|x64.Build.0 = Debug|x64 + {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Release|Win32.ActiveCfg = Release|Win32 + {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Release|Win32.Build.0 = Release|Win32 {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Release|x64.ActiveCfg = Release|x64 {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68}.Release|x64.Build.0 = Release|x64 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Debug|Win32.ActiveCfg = Debug|Win32 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Debug|Win32.Build.0 = Debug|Win32 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Debug|x64.ActiveCfg = Debug|x64 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Debug|x64.Build.0 = Debug|x64 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Release|Win32.ActiveCfg = Release|Win32 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Release|Win32.Build.0 = Release|Win32 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Release|x64.ActiveCfg = Release|x64 + {E77657CD-A270-49E1-823A-8A14FF8596C8}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {9397D285-8C29-4661-A741-F6703E2F5FD6} = {174AB66C-6250-4DDB-88C5-856B9D499DB7} - {2C0B129E-88F3-479A-AE5D-65609A88BE66} = {8031E506-AE20-4995-9F28-2D177A1FB319} {24D35D6E-BDB0-4949-8A34-7DD25F0E8F68} = {72571B45-7827-4380-8821-38A33FBFF4E2} + {E77657CD-A270-49E1-823A-8A14FF8596C8} = {08C63CB6-78C2-44EC-AA24-8CBA0CFEE2E6} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2191F306-963C-4507-99DB-A9D54CB8615B} EndGlobalSection EndGlobal diff --git a/avstream/avscamera/mft0/AvsCameraMFT0.rc b/avstream/avscamera/mft0/AvsCameraMFT0.rc deleted file mode 100644 index 86c06ba28..000000000 --- a/avstream/avscamera/mft0/AvsCameraMFT0.rc +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include - - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT2_UNKNOWN -#define VER_FILEDESCRIPTION_STR "A/V Stream Camera MFT0" -#define VER_INTERNALNAME_STR "AvsCameraMft0.dll" -#define VER_ORIGINALFILENAME_STR "AvsCameraMft0.dll" -#define VER_LANGNEUTRAL - -#include "common.ver" - diff --git a/avstream/avscamera/mft0/AvsCameraMft0.vcxproj b/avstream/avscamera/mft0/AvsCameraMft0.vcxproj deleted file mode 100644 index 518a324f4..000000000 --- a/avstream/avscamera/mft0/AvsCameraMft0.vcxproj +++ /dev/null @@ -1,216 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {2C0B129E-88F3-479A-AE5D-65609A88BE66} - $(MSBuildProjectName) - false - true - Debug - Win32 - {1921F93C-296D-4875-BD67-D087F1DBF95B} - - - - Windows10 - False - Universal - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Universal - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - False - Universal - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Universal - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - - $(IntDir) - - - - - - - - - - - - - - - - AvsCameraMft0 - - - AvsCameraMft0 - - - AvsCameraMft0 - - - AvsCameraMft0 - - - - Sync - - - - - Sync - - - - - Sync - - - - - Sync - - - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - %(AdditionalIncludeDirectories);$(SDK_INC_PATH)\ks;..\common - - - - - %(AdditionalDependencies);mfplat.lib;uuid.lib;mfuuid.lib;OneCoreUAP.lib - Mft0.def - - - - - %(AdditionalDependencies);mfplat.lib;uuid.lib;mfuuid.lib;OneCoreUAP.lib - Mft0.def - - - - - %(AdditionalDependencies);mfplat.lib;uuid.lib;mfuuid.lib;OneCoreUAP.lib - Mft0.def - - - - - %(AdditionalDependencies);mfplat.lib;uuid.lib;mfuuid.lib;OneCoreUAP.lib - Mft0.def - - - - - - ;%(AdditionalIncludeDirectories) - stdafx.h - Use - $(IntDir)\stdafx.h.pch - - - ;%(AdditionalIncludeDirectories) - stdafx.h - Use - $(IntDir)\stdafx.h.pch - - - ;%(AdditionalIncludeDirectories) - stdafx.h - Create - $(IntDir)\stdafx.h.pch - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/avstream/avscamera/mft0/MFT0.def b/avstream/avscamera/mft0/MFT0.def deleted file mode 100644 index b4430ceb3..000000000 --- a/avstream/avscamera/mft0/MFT0.def +++ /dev/null @@ -1,13 +0,0 @@ -; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -; ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -; PARTICULAR PURPOSE. -; Copyright (c) Microsoft Corporation. All rights reserved - -; SampleMft0.def : Declares the module parameters. - -LIBRARY - -EXPORTS - DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE \ No newline at end of file diff --git a/avstream/avscamera/mft0/MFT0.idl b/avstream/avscamera/mft0/MFT0.idl deleted file mode 100644 index 40098f71f..000000000 --- a/avstream/avscamera/mft0/MFT0.idl +++ /dev/null @@ -1,46 +0,0 @@ -//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -//// PARTICULAR PURPOSE. -//// -//// Copyright (c) Microsoft Corporation. All rights reserved - -// SampleMft0.idl : IDL source for SampleMft0 -// - -// This file will be processed by the MIDL tool to -// produce the type library (SampleMft0.tlb) and marshalling code. - -import "oaidl.idl"; -import "ocidl.idl"; -import "Inspectable.idl"; -import "mftransform.idl"; -[ - object, - uuid(7B917902-D657-4437-9F93-93B94482F286), - oleautomation, - nonextensible, - pointer_default(unique) -] -interface ISocMft0 : IUnknown{ - [id(1)] HRESULT SetState([in] UINT32 state); - [id(2)] HRESULT GetState([out] UINT* pState); -}; -[ - uuid(8F14E328-2084-442E-A4D9-A80AA30ECBA8), - version(1.0), -] -library SampleSocMft0Lib -{ - importlib("stdole2.tlb"); - [ - uuid(424BF154-D92A-42EB-B041-1395F9E5B4A2) - ] - coclass Mft0 - { - [default] interface ISocMft0; - interface IInspectable; - interface IMFTransform; - }; -}; - diff --git a/avstream/avscamera/mft0/MFT0Impl.cpp b/avstream/avscamera/mft0/MFT0Impl.cpp deleted file mode 100644 index 26d40f997..000000000 --- a/avstream/avscamera/mft0/MFT0Impl.cpp +++ /dev/null @@ -1,2083 +0,0 @@ -/************************************************************************** - - A/V Stream Camera Sample - - Copyright (c) 2014, Microsoft Corporation. - - File: - - Mft0Impl.cpp - - Abstract: - - This is the implementation of CSocMft0. - - CSocMft0 is the MFT0 for the AvsCamera sample driver. This MFT0 - performs the following key tasks: - 1. Filters overscan media types supplied by the driver, and - 2. Parses private metadata and attaches an IMFAttribute to the sample. - - History: - - created 5/15/2014 - -**************************************************************************/ - - -#include "stdafx.h" -#include "Mft0Impl.h" -#include "SampleHelpers.h" -#include "metadataInternal.h" -#include -#include -#include -#include - -#include "CustomProperties.h" -#include "macros.h" - -///////////////////////////////////////////////////////////////////////////////// -// -// These two functions demostrate that OEM application can communicate with MFT0 -// -STDMETHODIMP CSocMft0::SetState(UINT32 state) -{ - // OEM can use similar function to update the status of MFT - // From their own application - m_uiInternalState = state; - return S_OK; -} - -STDMETHODIMP CSocMft0::GetState(UINT32 *pState) -{ - HRESULT hr = S_OK; - - // OEM can use similar function to get the status of MFT - // From their own application - if (!pState) - { - return E_POINTER; - } - *pState = m_uiInternalState; - - return hr; -} - -////////////////////////////////////////////////////////////////////////////////// -// -// This initializes the CSocMFT0 for Com -// -// -HRESULT CSocMft0::CreateInstance( - REFIID iid, - void **ppMFT -) -{ - HRESULT hr = S_OK; - ComPtr spMFT; - UNREFERENCED_PARAMETER(iid); - - auto sObject = Microsoft::WRL::Make(); - - if (!sObject) - { - return E_OUTOFMEMORY; - } - hr = sObject->FinalConstruct(); - - if (SUCCEEDED(hr)) - { - hr = sObject.As(&spMFT); - *ppMFT = spMFT.Detach(); - } - - return hr; -} - -///////////////////////////////////////////////////////////////////////////////// -// -// IInspectable interface enable COM interface to talk with other programming environments -// -// Gets the interfaces that are implemented by the current Windows Runtime class. -// -STDMETHODIMP CSocMft0::GetIids( - _Out_ ULONG *iidCount, - _Outptr_result_buffer_maybenull_(*iidCount) IID **iids -) -{ - HRESULT hr = S_OK; - - if (!iidCount) - { - return E_POINTER; - } - - if (!iids) - { - return E_POINTER; - } - - *iids = NULL; - *iidCount = 0; - - return hr; -} - -///////////////////////////////////////////////////////////////////////////////// -// -// Gets the fully qualified name of the current Windows Runtime object. -// -STDMETHODIMP CSocMft0::GetRuntimeClassName( - _Outptr_result_maybenull_ HSTRING *pClassName -) -{ - - if (!pClassName) - { - return E_POINTER; - } - return WindowsCreateString(NULL, 0, pClassName); -} - -///////////////////////////////////////////////////////////////////////////////// -// -// Gets the trust level of the current Windows Runtime object. -// -STDMETHODIMP CSocMft0::GetTrustLevel( - _Out_ TrustLevel *trustLevel -) -{ - HRESULT hr = S_OK; - - if (trustLevel) - { - return E_POINTER; - } - *trustLevel = TrustLevel::BaseTrust; - - return hr; -} - -//////////////////////////////////////////////////////////////////////// -// -// Final Construct -// -HRESULT CSocMft0::FinalConstruct() -{ - HRESULT hr = S_OK; - hr = MFCreateAttributes(&m_spGlobalAttributes, 3); - if (FAILED(hr)) - { - goto done; - } - - hr = m_spGlobalAttributes->SetUINT32(MF_TRANSFORM_ASYNC, FALSE); - if (FAILED(hr)) - { - goto done; - } - - hr = m_spGlobalAttributes->SetString( - MFT_ENUM_HARDWARE_URL_Attribute, - L"Sample_CameraExtensionMft"); - if (FAILED(hr)) - { - goto done; - } - - hr = m_spGlobalAttributes->SetUINT32( - MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, - TRUE); - -done: - if (FAILED(hr)) - { - m_spGlobalAttributes.Reset(); - } - return hr; -} - -// IMFTransform methods. Refer to the Media Foundation SDK documentation for details. - -//////////////////////////////////////////////////////////////////////// -// -// GetStreamLimits -// Returns the minimum and maximum number of streams. -// -STDMETHODIMP CSocMft0::GetStreamLimits( - _Out_ DWORD *pdwInputMinimum, - _Out_ DWORD *pdwInputMaximum, - _Out_ DWORD *pdwOutputMinimum, - _Out_ DWORD *pdwOutputMaximum -) -{ - if ((!pdwInputMinimum) || - (!pdwInputMaximum) || - (!pdwOutputMinimum) || - (!pdwOutputMaximum)) - { - return E_POINTER; - } - - // This MFT has a fixed number of streams. - *pdwInputMinimum = 1; - *pdwInputMaximum = 1; - *pdwOutputMinimum = 1; - *pdwOutputMaximum = 1; - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetStreamCount -// Returns the actual number of streams. -// -STDMETHODIMP CSocMft0::GetStreamCount( - _Out_ DWORD *pcInputStreams, - _Out_ DWORD *pcOutputStreams -) -{ - if (!pcInputStreams || !pcOutputStreams) - { - return E_POINTER; - } - - // This MFT has a fixed number of streams. - *pcInputStreams = 1; - *pcOutputStreams = 1; - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetStreamIDs -// Returns stream IDs for the input and output streams. -// -STDMETHODIMP CSocMft0::GetStreamIDs( - DWORD dwInputIDArraySize, - _Out_writes_(dwInputIDArraySize) DWORD *pdwInputIDs, - DWORD dwOutputIDArraySize, - _Out_writes_(dwOutputIDArraySize) DWORD *pdwOutputIDs -) -{ - UNREFERENCED_PARAMETER(dwInputIDArraySize); - UNREFERENCED_PARAMETER(dwOutputIDArraySize); - UNREFERENCED_PARAMETER(pdwInputIDs); - UNREFERENCED_PARAMETER(pdwOutputIDs); - - // It is not required to implement this method if the MFT has a fixed number of - // streams AND the stream IDs are numbered sequentially from zero (that is, the - // stream IDs match the stream indexes). - - // In that case, it is OK to return E_NOTIMPL. - return (E_NOTIMPL); -} - -//////////////////////////////////////////////////////////////////////// -// -// GetInputStreamInfo -// Returns information about an input stream. -// -STDMETHODIMP CSocMft0::GetInputStreamInfo( - DWORD dwInputStreamID, - _Out_ MFT_INPUT_STREAM_INFO *pStreamInfo -) -{ - UNREFERENCED_PARAMETER(dwInputStreamID); - CAutoLock lock(&m_critSec); - - if (!pStreamInfo) - { - return E_POINTER; - } - - if (!m_spInputType) - { - return MF_E_TRANSFORM_TYPE_NOT_SET; - } - - pStreamInfo->hnsMaxLatency = 0; - pStreamInfo->cbAlignment = 0; - pStreamInfo->cbSize = 0; - pStreamInfo->dwFlags = - MFT_INPUT_STREAM_WHOLE_SAMPLES | - MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | - MFT_INPUT_STREAM_PROCESSES_IN_PLACE; - pStreamInfo->hnsMaxLatency = 0; - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetOutputStreamInfo -// Returns information about an output stream. -// -STDMETHODIMP CSocMft0::GetOutputStreamInfo( - DWORD dwOutputStreamID, - _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo -) -{ - UNREFERENCED_PARAMETER(dwOutputStreamID); - CAutoLock lock(&m_critSec); - - if (!pStreamInfo) - { - return E_POINTER; - } - - if (!m_spOutputType) - { - return MF_E_TRANSFORM_TYPE_NOT_SET; - } - - pStreamInfo->cbAlignment = 0; - pStreamInfo->cbSize = 0; - pStreamInfo->dwFlags = - MFT_OUTPUT_STREAM_WHOLE_SAMPLES | - MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | - MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | - MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; - - return S_OK; -} - -///////////////////////////////////////////////////////////////////////// -// -// GetAttributes -// Returns the global attributes for the MFT. -// -STDMETHODIMP CSocMft0::GetAttributes( - _Outptr_result_maybenull_ IMFAttributes **ppAttributes -) -{ - if (!ppAttributes) - { - return E_POINTER; - } - - return m_spGlobalAttributes.CopyTo(ppAttributes); -} - -//////////////////////////////////////////////////////////////////////// -// -// GetInputStreamAttributes -// Returns stream-level attributes for an input stream. -// -STDMETHODIMP CSocMft0::GetInputStreamAttributes( - DWORD dwInputStreamID, - _Outptr_result_maybenull_ IMFAttributes **ppAttributes -) -{ - HRESULT hr = S_OK; - - if (dwInputStreamID > 0) - { - return MF_E_INVALIDSTREAMNUMBER; - } - if (!ppAttributes) - { - return E_POINTER; - } - - if (!m_spInputAttributes) - { - hr = MFCreateAttributes(&m_spInputAttributes, 2); - if (FAILED(hr)) - { - goto done; - } - hr = m_spInputAttributes->SetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE); - if (FAILED(hr)) - { - goto done; - } - hr = m_spInputAttributes->SetString(MFT_ENUM_HARDWARE_URL_Attribute, L"Sample_CameraExtensionMft"); - if (FAILED(hr)) - { - goto done; - } - } - hr = m_spInputAttributes.CopyTo(ppAttributes); - -done: - if (FAILED(hr)) - { - m_spInputAttributes.Reset(); - } - return hr; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetOutputStreamAttributes -// Returns stream-level attributes for an output stream. -// -STDMETHODIMP CSocMft0::GetOutputStreamAttributes( - DWORD dwOutputStreamID, - _Outptr_result_maybenull_ IMFAttributes **ppAttributes -) -{ - if (dwOutputStreamID > 0) - { - return MF_E_INVALIDSTREAMNUMBER; - } - - if (!ppAttributes) - { - return E_POINTER; - } - - if (!m_spInputAttributes) - { - return MF_E_TRANSFORM_TYPE_NOT_SET; - } - - return m_spInputAttributes.CopyTo(ppAttributes); -} - -//////////////////////////////////////////////////////////////////////// -// -// DeleteInputStream -// -STDMETHODIMP CSocMft0::DeleteInputStream( - DWORD dwStreamID -) -{ - UNREFERENCED_PARAMETER(dwStreamID); - - // This MFT has a fixed number of input streams, so the method is not supported. - return (E_NOTIMPL); -} - -//////////////////////////////////////////////////////////////////////// -// -// AddInputStreams -// -STDMETHODIMP CSocMft0::AddInputStreams( - DWORD cStreams, - _In_ DWORD *adwStreamIDs -) -{ - UNREFERENCED_PARAMETER(cStreams); - UNREFERENCED_PARAMETER(adwStreamIDs); - - // This MFT has a fixed number of output streams, so the method is not supported. - return (E_NOTIMPL); -} - -//////////////////////////////////////////////////////////////////////// -// -// GetInputAvailableType -// Returns a preferred input type. -// -STDMETHODIMP CSocMft0::GetInputAvailableType( - DWORD dwInputStreamID, - DWORD dwTypeIndex, - _Outptr_result_maybenull_ IMFMediaType **ppType -) -{ - HRESULT hr = S_OK; - ComPtr spUnknown; - ComPtr spSourceAttributes; - - CAutoLock lock(&m_critSec); - - if (!m_spSourceTransform && m_spInputAttributes) - { - hr = m_spInputAttributes->GetUnknown(MFT_CONNECTED_STREAM_ATTRIBUTE, IID_PPV_ARGS(spSourceAttributes.ReleaseAndGetAddressOf())); - if (FAILED(hr)) - { - return hr; - } - - hr = spSourceAttributes->GetUnknown(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT, IID_PPV_ARGS(spUnknown.ReleaseAndGetAddressOf())); - if (FAILED(hr)) - { - return hr; - } - - hr = spUnknown.As(&m_spSourceTransform); - if (FAILED(hr)) - { - return hr; - } - - hr = spSourceAttributes->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &m_stStreamType); - if (FAILED(hr)) - { - return hr; - } - - hr = spSourceAttributes->GetUINT32(MF_DEVICESTREAM_STREAM_ID, &m_uiSourceStreamId); - if (FAILED(hr)) - { - return hr; - } - - hr = GenerateMFMediaTypeListFromDevice(); - if (FAILED(hr)) - { - return hr; - } - } - - hr = GetMediaType(dwInputStreamID, dwTypeIndex, ppType); - - return hr; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetOutputAvailableType -// Returns a preferred output type. -// -STDMETHODIMP CSocMft0::GetOutputAvailableType( - DWORD dwOutputStreamID, - DWORD dwTypeIndex, - _Outptr_result_maybenull_ IMFMediaType **ppType -) -{ - HRESULT hr = S_OK; - ComPtr spUnknown; - ComPtr spSourceAttributes; - - CAutoLock lock(&m_critSec); - - if (!m_spSourceTransform && m_spInputAttributes) - { - hr = m_spInputAttributes->GetUnknown(MFT_CONNECTED_STREAM_ATTRIBUTE, IID_PPV_ARGS(spSourceAttributes.ReleaseAndGetAddressOf())); - if (FAILED(hr)) - { - return hr; - } - - hr = spSourceAttributes->GetUnknown(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT, IID_PPV_ARGS(spUnknown.ReleaseAndGetAddressOf())); - if (FAILED(hr)) - { - return hr; - } - - hr = spUnknown.As(&m_spSourceTransform); - if (FAILED(hr)) - { - return hr; - } - - hr = spSourceAttributes->GetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, &m_stStreamType); - if (FAILED(hr)) - { - return hr; - } - - hr = spSourceAttributes->GetUINT32(MF_DEVICESTREAM_STREAM_ID, &m_uiSourceStreamId); - if (FAILED(hr)) - { - return hr; - } - - // - // This is the first function get called after the MFT0 object get instantiated, - // Here we can generate the supported media type from the connected input pin, - // Also, we can selectively plug in MFT0 only on pins requires processing - // by returning error on the unwanted pin types. Example below if we did not - // want MFT0 for Record - - //if(m_stStreamType != PINNAME_IMAGE && m_stStreamType != PINNAME_VIDEO_PREVIEW) - //{ - // return E_UNEXPECTED; - //} - - hr = GenerateMFMediaTypeListFromDevice(); - if (FAILED(hr)) - { - return hr; - } - } - - return GetMediaType(dwOutputStreamID, dwTypeIndex, ppType); -} - -//////////////////////////////////////////////////////////////////////// -// -// SetInputType -// -STDMETHODIMP CSocMft0::SetInputType( - DWORD dwInputStreamID, - _In_opt_ IMFMediaType *pType, - DWORD dwFlags -) -{ - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - - BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0); - - // Validate flags. - // Only MFT_SET_TYPE_TEST_ONLY is supported, if any other bit flags - // get set, it should return error. - if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY) - { - return E_INVALIDARG; - } - - if (!bReallySet) - { - return IsMediaTypeSupported(dwInputStreamID, pType); - } - - ComPtr spFullType; - hr = IsMediaTypeSupported(dwInputStreamID, pType, spFullType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return hr; - } - - m_spInputType = spFullType; - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// SetOutputType -// This function set the output media type and at the same time, it should -// also choose a compatible input type -// -STDMETHODIMP CSocMft0::SetOutputType( - DWORD dwOutputStreamID, - _In_opt_ IMFMediaType *pType, - DWORD dwFlags -) -{ - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0); - BOOL bUseModifiedInputType = FALSE; - - // Validate flags. - if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY) - { - return E_INVALIDARG; - } - - if (!bReallySet) - { - return IsMediaTypeSupported(dwOutputStreamID, pType); - } - - ComPtr spFullType; - ComPtr spFullInputType; - hr = IsMediaTypeSupported(dwOutputStreamID, pType, spFullType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return hr; - } - - if (m_stStreamType == PINNAME_CAPTURE) - { - hr = GetVideoStabilizationEnabled(); - if (FAILED(hr)) - { - return hr; - } - - // Hardware Video Stabilization is enabled - if (m_bEnableVideoStabilization) - { - UINT32 uiIndex = 0; - //This shouldn't fail, since it is derived from IsMediaTypeSupported - // and that just passed. - hr = FindMediaIndex(dwOutputStreamID, pType, &uiIndex); - if (FAILED(hr)) - { - return hr; - } - //Device Driver contains a static list of mediatypes on the pin - // We have ordered them in such a way so that all odd mediatypes are the - // overscan media of the even mediatype immediatley proceeding it, ie. - // -normalVGA - // -overscanVGA - // -normalQVGA - // -overscanQVGA - // etc - // The following command determines if we are dealing with an overscan or normal mediatype - // if it is overscan, we fail (cannot overscan an overscan mediatype) - // otherwise, we set our input mediatype to the overscan type associated with it. - if (uiIndex % 2 != 0) //odd means overscan - { - return MF_E_INVALIDMEDIATYPE; - } - else //even - { - hr = GetMediaType(dwOutputStreamID, uiIndex + 1, spFullInputType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return hr; - } - - bUseModifiedInputType = TRUE; - } - } - } - m_spOutputType = spFullType; - - // Here, we choose a compatible input type which is the same type - // as output. If OEM choose to encode sample here, it should choose - // an input which is supported by encoder. - if (bUseModifiedInputType) - { - m_spInputType = spFullInputType; - } - else - { - m_spInputType = spFullType; - } - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetInputCurrentType -// Returns the current input type. -// -STDMETHODIMP CSocMft0::GetInputCurrentType( - DWORD dwInputStreamID, - _Outptr_result_maybenull_ IMFMediaType **ppType -) -{ - UNREFERENCED_PARAMETER(dwInputStreamID); - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - - if (!ppType) - { - return E_POINTER; - } - - if (!m_spInputType) - { - return MF_E_TRANSFORM_TYPE_NOT_SET; - } - - ComPtr spMediaType; - hr = MFCreateMediaType(spMediaType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return hr; - } - - hr = m_spInputType->CopyAllItems(spMediaType.Get()); - if (FAILED(hr)) - { - return hr; - } - - return spMediaType.CopyTo(ppType); -} - -//////////////////////////////////////////////////////////////////////// -// -// GetOutputCurrentType -// Returns the current output type. -// -STDMETHODIMP CSocMft0::GetOutputCurrentType( - DWORD dwOutputStreamID, - _Outptr_result_maybenull_ IMFMediaType **ppType -) -{ - UNREFERENCED_PARAMETER(dwOutputStreamID); - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - - if (!ppType) - { - return E_POINTER; - } - - if (!m_spOutputType) - { - return MF_E_TRANSFORM_TYPE_NOT_SET; - } - - ComPtr spMediaType; - hr = MFCreateMediaType(spMediaType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return hr; - } - - hr = m_spOutputType->CopyAllItems(spMediaType.Get()); - if (FAILED(hr)) - { - return hr; - } - - return spMediaType.CopyTo(ppType); -} - -//////////////////////////////////////////////////////////////////////// -// -// GetInputStatus -// Query if the MFT is accepting more input. -// -STDMETHODIMP CSocMft0::GetInputStatus( - DWORD dwInputStreamID, - _Out_ DWORD *pdwFlags -) -{ - UNREFERENCED_PARAMETER(dwInputStreamID); - CAutoLock lock(&m_critSec); - - if (!pdwFlags) - { - return E_POINTER; - } - - // If we already have an input sample, we don't accept - // another one until the client calls ProcessOutput or Flush. - if (m_spSample == NULL) - { - *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA; - } - else - { - *pdwFlags = 0; - } - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// GetOutputStatus -// Query if the MFT can produce output. -// -STDMETHODIMP CSocMft0::GetOutputStatus( - _Out_ DWORD *pdwFlags -) -{ - if (!pdwFlags) - { - return E_POINTER; - } - - CAutoLock lock(&m_critSec); - - // We can produce an output sample if (and only if) - // we have an input sample. - if (m_spSample != NULL) - { - *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY; - } - else - { - *pdwFlags = 0; - } - - return S_OK; -} - -//////////////////////////////////////////////////////////////////////// -// -// SetOutputBounds -// Sets the range of time stamps that the MFT will output. -// -STDMETHODIMP CSocMft0::SetOutputBounds( - LONGLONG hnsLowerBound, - LONGLONG hnsUpperBound -) -{ - UNREFERENCED_PARAMETER(hnsLowerBound); - UNREFERENCED_PARAMETER(hnsUpperBound); - - // Implementation of this method is optional. - return (E_NOTIMPL); -} - -//////////////////////////////////////////////////////////////////////// -// -// ProcessEvent -// Sends an event to an input stream. -// -STDMETHODIMP CSocMft0::ProcessEvent( - DWORD dwInputStreamID, - _In_opt_ IMFMediaEvent *pEvent -) -{ - UNREFERENCED_PARAMETER(dwInputStreamID); - UNREFERENCED_PARAMETER(pEvent); - return E_NOTIMPL; -} - -//////////////////////////////////////////////////////////////////////// -// -// ProcessMessage -// -STDMETHODIMP CSocMft0::ProcessMessage( - MFT_MESSAGE_TYPE eMessage, - ULONG_PTR ulParam -) -{ - UNREFERENCED_PARAMETER(ulParam); - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - - switch (eMessage) - { - case MFT_MESSAGE_COMMAND_FLUSH: - // Flush the MFT. - hr = OnFlush(); - break; - } - - return hr; -} - -///////////////////////////////////////////////////////////////////// -// -// ProcessInput -// Process an input sample. The sample is cached and real work is done -// in ProcessOutput -// -STDMETHODIMP CSocMft0::ProcessInput( - DWORD dwInputStreamID, - IMFSample *pSample, - DWORD dwFlags -) -{ - UNREFERENCED_PARAMETER(dwInputStreamID); - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - - if (!pSample) - { - return E_POINTER; - } - if (dwFlags != 0) - { - return E_INVALIDARG; - } - - if (!m_spInputType || !m_spOutputType) - { - return MF_E_NOTACCEPTING; // Client must set input and output types. - } - - if (m_spSample != NULL) - { - return MF_E_NOTACCEPTING; // We already have an input sample. - } - - // Validate the number of buffers. There should only be a single buffer to hold the video frame. - DWORD dwBufferCount = 0; - hr = pSample->GetBufferCount(&dwBufferCount); - if (FAILED(hr)) - { - return hr; - } - - if (dwBufferCount == 0) - { - return E_FAIL; - } - - if (dwBufferCount > 1) - { - return MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS; - } - - // Cache the sample. We do the actual work in ProcessOutput. - m_spSample = pSample; - - return S_OK; -} - -///////////////////////////////////////////////////////////////////// -// -// ProcessOutput -// Process an output sample. -// -STDMETHODIMP CSocMft0::ProcessOutput( - DWORD dwFlags, - DWORD cOutputBufferCount, - MFT_OUTPUT_DATA_BUFFER *pOutputSamples, - DWORD *pdwStatus -) -{ - HRESULT hr = S_OK; - - CAutoLock lock(&m_critSec); - - if (dwFlags != 0) - { - return E_INVALIDARG; - } - - if (!pOutputSamples || !pdwStatus) - { - return E_POINTER; - } - - if (pOutputSamples[0].pSample) - { - pOutputSamples[0].pSample->Release(); - pOutputSamples[0].pSample = nullptr; - } - - // Must be exactly one output buffer. - if (cOutputBufferCount != 1) - { - return E_INVALIDARG; - } - - // If we don't have an input sample, we need some input before - // we can generate any output. - if (m_spSample == nullptr) - { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } -#if (NTDDI_VERSION >= NTDDI_WINBLUE) - hr = ProcessMetadata(); - if (FAILED(hr)) - { - //Log the failure - hr = S_OK; - } -#endif // (NTDDI_VERSION >= NTDDI_WINBLUE) - hr = CreateOutputSample(&pOutputSamples[0].pSample); - if (FAILED(hr)) - { - return hr; - } - pOutputSamples[0].dwStatus = 0; - *pdwStatus = 0; - - // if createOutputSample actually make a copy of the sample, - // (for example, JPEG encoding case), we need to copy the - // attribute from m_spSample to spOutputIMFSample - m_spSample.Reset(); - return hr; -} - -///////////////////////////////////////////////////////////////////// -// -// The actual processing is here, required operation is demux -// Other operation is optional -// -HRESULT -CSocMft0:: -CreateOutputSample( - _Outptr_result_maybenull_ - IMFSample **ppSample -) -{ - HRESULT hr = S_OK; - - //Do nothing for now - if (!ppSample) - { - return E_POINTER; - } - - m_spSample.CopyTo(ppSample); - - return hr; -} -///////////////////////////////////////////////////////////////////// -// -// Flush the MFT. -// -STDMETHODIMP CSocMft0::OnFlush() -{ - // For this MFT, flushing just means releasing the input sample. - CAutoLock lock(&m_critSec); - m_spSample.Reset(); - return S_OK; -} - -///////////////////////////////////////////////////////////////////// -// -// Get the mediaType of selected stream. -// -STDMETHODIMP CSocMft0::GetMediaType( - _In_ DWORD dwStreamId, - _In_ DWORD dwTypeIndex, - _Outptr_result_maybenull_ IMFMediaType **ppType -) -{ - HRESULT hr = S_OK; - ComPtr spMediaType; - - if (!ppType) - { - return E_POINTER; - } - - if (dwStreamId != 0) - { - return MF_E_INVALIDSTREAMNUMBER; - } - - if (dwTypeIndex >= m_listOfMediaTypes.size()) - { - return MF_E_NO_MORE_TYPES; - } - - hr = MFCreateMediaType(spMediaType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return hr; - } - - hr = m_listOfMediaTypes[dwTypeIndex]->CopyAllItems(spMediaType.Get()); - if (FAILED(hr)) - { - return hr; - } - - return spMediaType.CopyTo(ppType); -} - -///////////////////////////////////////////////////////////////////// -// -// Check if the media type is supported by MFT0. -// -STDMETHODIMP CSocMft0::IsMediaTypeSupported( - _In_ UINT uiStreamId, - _In_opt_ IMFMediaType *pIMFMediaType, - _Outptr_opt_result_maybenull_ IMFMediaType **ppIMFMediaTypeFull -) -{ - HRESULT hr = S_OK; - - if (!pIMFMediaType) - { - return E_POINTER; - } - - if (uiStreamId != 0) - { - return MF_E_INVALIDINDEX; - } - - BOOL bFound = FALSE; - - - for (UINT i = 0; i < m_listOfMediaTypes.size(); i++) - { - DWORD dwResult = 0; - hr = m_listOfMediaTypes[i]->IsEqual(pIMFMediaType, &dwResult); - if (hr == S_FALSE) - { - if ((dwResult & MF_MEDIATYPE_EQUAL_MAJOR_TYPES) && - (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_TYPES) && - (dwResult& MF_MEDIATYPE_EQUAL_FORMAT_DATA)) - { - hr = S_OK; - } - } - if (hr == S_OK) - { - bFound = TRUE; - if (ppIMFMediaTypeFull) - { - m_listOfMediaTypes[i].CopyTo(ppIMFMediaTypeFull); - } - break; - } - else if (FAILED(hr)) - { - return hr; - } - } - - if (bFound == FALSE) - { - return MF_E_INVALIDMEDIATYPE; - } - - return S_OK; -} - -///////////////////////////////////////////////////////////////////// -// -// Check if the media type is supported by MFT0. -// -_Success_(return == 0) -STDMETHODIMP CSocMft0::FindMediaIndex( - _In_ UINT uiStreamId, - _In_ IMFMediaType *pIMFMediaType, - _Out_ UINT *puiMediaIndex -) -{ - HRESULT hr = S_OK; - - if (!pIMFMediaType || !puiMediaIndex) - { - return E_INVALIDARG; - } - - if (uiStreamId != 0) - { - return MF_E_INVALIDINDEX; - } - - BOOL bFound = FALSE; - - for (UINT i = 0; i < m_listOfMediaTypes.size(); i++) - { - DWORD dwResult = 0; - hr = m_listOfMediaTypes[i]->IsEqual(pIMFMediaType, &dwResult); - if (hr == S_FALSE) - { - if ((dwResult & MF_MEDIATYPE_EQUAL_MAJOR_TYPES) && - (dwResult & MF_MEDIATYPE_EQUAL_FORMAT_TYPES) && - (dwResult & MF_MEDIATYPE_EQUAL_FORMAT_DATA)) - { - hr = S_OK; - } - } - if (hr == S_OK) - { - bFound = TRUE; - *puiMediaIndex = i; - break; - } - else if (FAILED(hr)) - { - return hr; - } - } - - if (bFound == FALSE) - { - return MF_E_INVALIDMEDIATYPE; - } - - return S_OK; -} - -///////////////////////////////////////////////////////////////////// -// -// Generate the supported input media type from device source media type -// -STDMETHODIMP CSocMft0::GenerateMFMediaTypeListFromDevice() -{ - HRESULT hr = S_OK; - - if (!m_spSourceTransform) - { - return MF_E_NOT_FOUND; - } - - m_listOfMediaTypes.clear(); - UINT iMediaType = 0; - while (SUCCEEDED(hr)) - { - ComPtr spMediaType; - hr = m_spSourceTransform->GetOutputAvailableType(m_uiSourceStreamId, iMediaType, spMediaType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - if (hr == MF_E_NO_MORE_TYPES) - { - hr = S_OK; - } - break; - } - - if (m_stStreamType == PINNAME_IMAGE || m_stStreamType == PINNAME_VIDEO_STILL) - { - GUID guidPhotoSubType = {}; - spMediaType->GetGUID(MF_MT_SUBTYPE, &guidPhotoSubType); - if (IsEqualGUID(guidPhotoSubType, MFVideoFormat_NV12)) - { - // Need to set MF_MT_VIDEO_NOMINAL_RANGE on NV12 or the pipeline ends up with a copy due to mismatched nominal range - hr = spMediaType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255); - if (FAILED(hr)) - { - return hr; - } - } - - - m_listOfMediaTypes.push_back(spMediaType); - } - - else if (m_stStreamType == PINNAME_CAPTURE) - { - UINT32 width = 0; - UINT32 height = 0; - hr = MFGetAttributeSize(spMediaType.Get(), MF_MT_FRAME_SIZE, &width, &height); - if (FAILED(hr)) - { - return hr; - } - - MFVideoArea validVideo; - validVideo.OffsetX.value = 0; - validVideo.OffsetX.fract = 0; - validVideo.OffsetY.value = 0; - validVideo.OffsetY.fract = 0; - validVideo.Area.cx = width; - validVideo.Area.cy = height; - hr = spMediaType->SetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (BYTE *)&validVideo, sizeof(validVideo)); - if (FAILED(hr)) - { - return hr; - } - - m_listOfMediaTypes.push_back(spMediaType); - } - - else - { - m_listOfMediaTypes.push_back(spMediaType); - } - - iMediaType++; - } - - return hr; -} - -///////////////////////////////////////////////////////////////////// -// -// Get the current media type in order to generate photo confirmation -// -HRESULT CSocMft0::GetPreviewMediaType( - _Outptr_result_maybenull_ IMFMediaType **ppType -) -{ - CAutoLock lock(&m_critSec); - if (!m_spSourceTransform) - { - return MF_E_NOT_FOUND; - } - - DWORD dwInStreamCount = 0, dwOutStreamCount = 0; - HRESULT hr = m_spSourceTransform->GetStreamCount( - &dwInStreamCount, - &dwOutStreamCount); - if (FAILED(hr)) - { - return hr; - } - - for (UINT32 i = 0; i < dwOutStreamCount; i++) - { - ComPtr spAttributes; - hr = m_spSourceTransform->GetOutputStreamAttributes(i, spAttributes.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - continue; - } - - GUID guidPinCategory = GUID_NULL; - hr = spAttributes->GetGUID( - MF_DEVICESTREAM_STREAM_CATEGORY, - &guidPinCategory); - if (FAILED(hr)) - { - continue; - } - if (IsEqualGUID(guidPinCategory, PINNAME_VIDEO_PREVIEW)) - { - ComPtr spMediaType; - hr = m_spSourceTransform->GetOutputCurrentType(i, spMediaType.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - return MF_E_NOT_FOUND; - } - return spMediaType.CopyTo(ppType); - } - } - - return MF_E_NOT_FOUND; -} - -#if (NTDDI_VERSION >= NTDDI_WINBLUE) -///////////////////////////////////////////////////////////////////// -// -// Handle the Metadata with the buffer -// -HRESULT CSocMft0::ProcessMetadata() -{ - ComPtr spMetadata; - HRESULT hr = m_spSample->GetUnknown(MFSampleExtension_CaptureMetadata, IID_PPV_ARGS(spMetadata.ReleaseAndGetAddressOf())); - if (FAILED(hr)) - { - return hr; - } - - ComPtr spBuffer; - hr = spMetadata->GetUnknown(MF_CAPTURE_METADATA_FRAME_RAWSTREAM, IID_PPV_ARGS(spBuffer.ReleaseAndGetAddressOf())); - if (FAILED(hr)) - { - return hr; - } - - MediaBufferLock bufferLock(spBuffer.Get()); - BYTE *pData = NULL; - DWORD dwLength = 0; - hr = bufferLock.LockBuffer(&pData, NULL, &dwLength); - if (FAILED(hr)) - { - return hr; - } - - // OEM put meta data passing logic here, - if (FAILED(hr)) - { - return hr; - } - - LONG lBufferLeft = static_cast(dwLength); - if (lBufferLeft < sizeof(KSCAMERA_METADATA_ITEMHEADER)) - { - return E_UNEXPECTED; - } - - PKSCAMERA_METADATA_ITEMHEADER pItem = (PKSCAMERA_METADATA_ITEMHEADER)pData; - - while (lBufferLeft > 0) - { - switch (pItem->MetadataId) - { - case MetadataId_Custom_PreviewAggregation: - hr = ParseMetadata_PreviewAggregation(pItem, spMetadata.Get()); - if (FAILED(hr)) - { - return hr; - } - break; - case MetadataId_Custom_ImageAggregation: - hr = ParseMetadata_ImageAggregation(pItem, spMetadata.Get()); - if (FAILED(hr)) - { - return hr; - } - break; - case MetadataId_Custom_Histogram: - hr = ParseMetadata_Histogram(pItem, spMetadata.Get()); - if (FAILED(hr)) - { - return hr; - } - break; - case MetadataId_Custom_FaceDetection: - hr = ParseMetadata_FaceDetection(pItem, spMetadata.Get()); - if (FAILED(hr)) - { - return hr; - } - } - - if (!pItem->Size) - { - // 0 size item will cause the loop to break and - // we will report buffer malformated - break; - } - lBufferLeft -= (LONG)pItem->Size; - if (lBufferLeft < sizeof(KSCAMERA_METADATA_ITEMHEADER)) - { - break; - } - pItem = reinterpret_cast - (reinterpret_cast(pItem) + pItem->Size); - } - - if (lBufferLeft != 0) - { - //Check and log for malformated data - return E_UNEXPECTED; - } - - return S_OK; -} - -HRESULT CSocMft0::ParseMetadata_PreviewAggregation( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes -) -{ - HRESULT hr = S_OK; - if (pItem->Size < sizeof(CAMERA_METADATA_PREVIEWAGGREGATION)) - { - return E_UNEXPECTED; - } - - PCAMERA_METADATA_PREVIEWAGGREGATION pFixedStruct = - (PCAMERA_METADATA_PREVIEWAGGREGATION)pItem; - - if (pFixedStruct->Data.FocusState.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_FOCUSSTATE, - pFixedStruct->Data.FocusState.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.ExposureTime.Set) - { - hr = pMetaDataAttributes->SetUINT64( - MF_CAPTURE_METADATA_EXPOSURE_TIME, - pFixedStruct->Data.ExposureTime.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.ISOSpeed.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_ISO_SPEED, - pFixedStruct->Data.ISOSpeed.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.LensPosition.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_LENS_POSITION, - pFixedStruct->Data.LensPosition.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.FlashOn.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_FLASH, - pFixedStruct->Data.FlashOn.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.WhiteBalanceMode.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_WHITEBALANCE, - pFixedStruct->Data.WhiteBalanceMode.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.EVCompensation.Set) - { - CapturedMetadataExposureCompensation EVCompensation; - - EVCompensation.Flags = pFixedStruct->Data.EVCompensation.Flags; - EVCompensation.Value = pFixedStruct->Data.EVCompensation.Value; - - hr = pMetaDataAttributes->SetBlob( - MF_CAPTURE_METADATA_EXPOSURE_COMPENSATION, - (const UINT8 *)&EVCompensation, - sizeof(EVCompensation)); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.SensorFrameRate.Set) - { - hr = pMetaDataAttributes->SetUINT64( - MF_CAPTURE_METADATA_SENSORFRAMERATE, - pFixedStruct->Data.SensorFrameRate.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.IsoAnalogGain.Set || - pFixedStruct->Data.IsoDigitalGain.Set) - { - CapturedMetadataISOGains IsoGains; - - if (pFixedStruct->Data.IsoAnalogGain.Set) - { - IsoGains.AnalogGain = - FLOAT(pFixedStruct->Data.IsoAnalogGain.Numerator) / - FLOAT(pFixedStruct->Data.IsoAnalogGain.Denominator); - } - if (pFixedStruct->Data.IsoDigitalGain.Set) - { - IsoGains.DigitalGain = - FLOAT(pFixedStruct->Data.IsoDigitalGain.Numerator) / - FLOAT(pFixedStruct->Data.IsoDigitalGain.Denominator); - } - - hr = pMetaDataAttributes->SetBlob( - MF_CAPTURE_METADATA_ISO_GAINS, - (const UINT8 *)&IsoGains, - sizeof(IsoGains)); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.WhiteBalanceGain_R.Set || - pFixedStruct->Data.WhiteBalanceGain_G.Set || - pFixedStruct->Data.WhiteBalanceGain_B.Set) - { - CapturedMetadataWhiteBalanceGains WhiteBalanceGains; - - if (pFixedStruct->Data.WhiteBalanceGain_R.Set) - { - WhiteBalanceGains.R = - FLOAT(pFixedStruct->Data.WhiteBalanceGain_R.Numerator) / - FLOAT(pFixedStruct->Data.WhiteBalanceGain_R.Denominator); - } - if (pFixedStruct->Data.WhiteBalanceGain_G.Set) - { - WhiteBalanceGains.G = - FLOAT(pFixedStruct->Data.WhiteBalanceGain_G.Numerator) / - FLOAT(pFixedStruct->Data.WhiteBalanceGain_G.Denominator); - } - if (pFixedStruct->Data.WhiteBalanceGain_B.Set) - { - WhiteBalanceGains.B = - FLOAT(pFixedStruct->Data.WhiteBalanceGain_B.Numerator) / - FLOAT(pFixedStruct->Data.WhiteBalanceGain_B.Denominator); - } - - hr = pMetaDataAttributes->SetBlob( - MF_CAPTURE_METADATA_WHITEBALANCE_GAINS, - (const UINT8 *)&WhiteBalanceGains, - sizeof(WhiteBalanceGains)); - if (FAILED(hr)) - { - return hr; - } - } - - return S_OK; -} - -HRESULT CSocMft0::ParseMetadata_ImageAggregation( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes -) -{ - HRESULT hr = S_OK; - if (pItem->Size < sizeof(CAMERA_METADATA_IMAGEAGGREGATION)) - { - return E_UNEXPECTED; - } - - PCAMERA_METADATA_IMAGEAGGREGATION pFixedStruct = - (PCAMERA_METADATA_IMAGEAGGREGATION)pItem; - - if (pFixedStruct->Data.FrameId.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_REQUESTED_FRAME_SETTING_ID, - pFixedStruct->Data.FrameId.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.ExposureTime.Set) - { - hr = pMetaDataAttributes->SetUINT64( - MF_CAPTURE_METADATA_EXPOSURE_TIME, - pFixedStruct->Data.ExposureTime.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.ISOSpeed.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_ISO_SPEED, - pFixedStruct->Data.ISOSpeed.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.LensPosition.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_LENS_POSITION, - pFixedStruct->Data.LensPosition.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.SceneMode.Set) - { - hr = pMetaDataAttributes->SetUINT64( - MF_CAPTURE_METADATA_SCENE_MODE, - pFixedStruct->Data.SceneMode.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.FlashOn.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_FLASH, - pFixedStruct->Data.FlashOn.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.FlashPower.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_FLASH_POWER, - pFixedStruct->Data.FlashPower.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.WhiteBalanceMode.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_WHITEBALANCE, - pFixedStruct->Data.WhiteBalanceMode.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.ZoomFactor.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_ZOOMFACTOR, - pFixedStruct->Data.ZoomFactor.Value); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.EVCompensation.Set) - { - CapturedMetadataExposureCompensation EVCompensation; - - EVCompensation.Flags = pFixedStruct->Data.EVCompensation.Flags; - EVCompensation.Value = pFixedStruct->Data.EVCompensation.Value; - - hr = pMetaDataAttributes->SetBlob( - MF_CAPTURE_METADATA_EXPOSURE_COMPENSATION, - (const UINT8 *)&EVCompensation, - sizeof(EVCompensation)); - if (FAILED(hr)) - { - return hr; - } - } - - if (pFixedStruct->Data.FocusState.Set) - { - hr = pMetaDataAttributes->SetUINT32( - MF_CAPTURE_METADATA_FOCUSSTATE, - pFixedStruct->Data.FocusState.Value); - if (FAILED(hr)) - { - return hr; - } - } - return S_OK; -} -#endif // (NTDDI_VERSION >= NTDDI_WINBLUE) -struct HistogramData -{ - HistogramDataHeader Header; - ULONG Color[256]; - - HistogramData() - { - Header.Size = sizeof(*this); - Header.ChannelMask = 0; - Header.Linear = 1; - RtlZeroMemory(Color, sizeof(Color)); - } -}; - -// This is the blob we pass back every time. -template -struct Histogram -{ - HistogramBlobHeader Blob; - // RGB or YUV Histograms. - HistogramHeader Header; - HistogramData Data[I]; - - Histogram( - _In_ ULONG Width = 0, - _In_ ULONG Height = 0 - ) - { - Blob.Histograms = 1; - Blob.Size = sizeof(*this); - - Header.Size = sizeof(Header) + sizeof(Data); - Header.Bins = 256; - Header.Grid.Height = Height; - Header.Grid.Width = Width; - Header.Grid.Region.top = 0; - Header.Grid.Region.left = 0; - Header.Grid.Region.bottom = Height - 1; - Header.Grid.Region.right = Width - 1; - } -}; - -#if (NTDDI_VERSION >= NTDDI_WINBLUE) -#define MF_HISTOGRAM_RGB (MF_HISTOGRAM_CHANNEL_R | MF_HISTOGRAM_CHANNEL_G | MF_HISTOGRAM_CHANNEL_B ) -#define MF_HISTOGRAM_YCrCb (MF_HISTOGRAM_CHANNEL_Y | MF_HISTOGRAM_CHANNEL_Cr | MF_HISTOGRAM_CHANNEL_Cb) - -HRESULT CSocMft0::ParseMetadata_Histogram( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes -) -{ - if (pItem->Size < sizeof(CAMERA_METADATA_HISTOGRAM)) - { - return E_UNEXPECTED; - } - - PCAMERA_METADATA_HISTOGRAM pHistogram = (PCAMERA_METADATA_HISTOGRAM)pItem; - - if ((pHistogram->Data.ChannelMask & MF_HISTOGRAM_RGB) == MF_HISTOGRAM_RGB) - { - Histogram<4> Blob(pHistogram->Data.Width, pHistogram->Data.Height); - - Blob.Header.FourCC = pHistogram->Data.FourCC; - Blob.Header.ChannelMasks = pHistogram->Data.ChannelMask; - - // For a RGB Histogram, we fake the Y channel by copying the G channel. - Blob.Data[0].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Y; - RtlCopyMemory(Blob.Data[0].Color, pHistogram->Data.P1Data, sizeof(Blob.Data[0].Color)); - - // Now just copy the RGB channels normally. - Blob.Data[1].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_R; - RtlCopyMemory(Blob.Data[1].Color, pHistogram->Data.P0Data, sizeof(Blob.Data[1].Color)); - Blob.Data[2].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_G; - RtlCopyMemory(Blob.Data[2].Color, pHistogram->Data.P1Data, sizeof(Blob.Data[2].Color)); - Blob.Data[3].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_B; - RtlCopyMemory(Blob.Data[3].Color, pHistogram->Data.P2Data, sizeof(Blob.Data[3].Color)); - - return pMetaDataAttributes->SetBlob( - MF_CAPTURE_METADATA_HISTOGRAM, - (PBYTE)&Blob, - sizeof(Blob) - ); - } - else if ((pHistogram->Data.ChannelMask & MF_HISTOGRAM_YCrCb) == MF_HISTOGRAM_YCrCb) - { - Histogram<3> Blob(pHistogram->Data.Width, pHistogram->Data.Height); - - Blob.Header.FourCC = pHistogram->Data.FourCC; - Blob.Header.ChannelMasks = pHistogram->Data.ChannelMask; - - Blob.Data[0].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Y; - RtlCopyMemory(Blob.Data[0].Color, pHistogram->Data.P0Data, sizeof(Blob.Data[0].Color)); - Blob.Data[1].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Cr; - RtlCopyMemory(Blob.Data[1].Color, pHistogram->Data.P1Data, sizeof(Blob.Data[1].Color)); - Blob.Data[2].Header.ChannelMask = MF_HISTOGRAM_CHANNEL_Cb; - RtlCopyMemory(Blob.Data[2].Color, pHistogram->Data.P2Data, sizeof(Blob.Data[2].Color)); - - //TODO: - return pMetaDataAttributes->SetBlob( - MF_CAPTURE_METADATA_HISTOGRAM, - (PBYTE)&Blob, - sizeof(Blob) - ); - } - return E_UNEXPECTED; -} - -HRESULT CSocMft0::ParseMetadata_FaceDetection( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes -) -{ - HRESULT hr = S_OK; - - if (pItem->Size < sizeof(CAMERA_METADATA_FACEHEADER)) - { - return E_UNEXPECTED; - } - - PCAMERA_METADATA_FACEHEADER pFaceHeader = (PCAMERA_METADATA_FACEHEADER)pItem; - - if (pItem->Size < (sizeof(CAMERA_METADATA_FACEHEADER) + (sizeof(METADATA_FACEDATA) * pFaceHeader->Count))) - { - return E_UNEXPECTED; - } - PMETADATA_FACEDATA pFaceData = (PMETADATA_FACEDATA)(pFaceHeader + 1); - UINT32 cbRectSize = sizeof(FaceRectInfoBlobHeader) + (sizeof(FaceRectInfo) * (pFaceHeader->Count)); - BYTE *pRectBuf = new (std::nothrow) BYTE[cbRectSize]; - if (pRectBuf == NULL) - { - return E_OUTOFMEMORY; - } - - UINT32 cbCharSize = sizeof(FaceCharacterizationBlobHeader) + (sizeof(FaceCharacterization) * (pFaceHeader->Count)); - BYTE *pCharBuf = new (std::nothrow) BYTE[cbCharSize]; - if (pCharBuf == NULL) - { - delete[] pRectBuf; - return E_OUTOFMEMORY; - } - - FaceRectInfoBlobHeader *pFaceRectHeader = (FaceRectInfoBlobHeader *)pRectBuf; - pFaceRectHeader->Size = cbRectSize; - pFaceRectHeader->Count = pFaceHeader->Count; - - FaceCharacterizationBlobHeader *pFaceCharHeader = (FaceCharacterizationBlobHeader *)pCharBuf; - pFaceCharHeader->Size = cbCharSize; - pFaceCharHeader->Count = pFaceHeader->Count; - - FaceRectInfo *FaceRegions = (FaceRectInfo *)(pFaceRectHeader + 1); - FaceCharacterization *FaceChars = (FaceCharacterization *)(pFaceCharHeader + 1); - - for (UINT i = 0; i < pFaceHeader->Count; i++) - { - FaceRegions[i].Region = pFaceData[i].Region; - FaceRegions[i].confidenceLevel = pFaceData[i].confidenceLevel; - - FaceChars[i].BlinkScoreLeft = pFaceData[i].BlinkScoreLeft; - FaceChars[i].BlinkScoreRight = pFaceData[i].BlinkScoreRight; - FaceChars[i].FacialExpression = (pFaceData[i].FacialExpression == EXPRESSION_SMILE) ? MF_METADATAFACIALEXPRESSION_SMILE : 0; - FaceChars[i].FacialExpressionScore = pFaceData[i].FacialExpressionScore; - } - - hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROIS, pRectBuf, cbRectSize); - if (FAILED(hr)) - { - goto done; - } - - MetadataTimeStamps timestamp; - timestamp.Flags = MF_METADATATIMESTAMPS_DEVICE; - timestamp.Device = pFaceHeader->Timestamp; - - hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROITIMESTAMPS, (const UINT8 *)×tamp, sizeof(MetadataTimeStamps)); - if (FAILED(hr)) - { - goto done; - } - -#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) - // Include characterization data if any of the associated bits were set. - if (pFaceHeader->Flags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_ADVANCED_MASK) - { - hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROICHARACTERIZATIONS, pCharBuf, cbCharSize); - } -#endif // (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) - -done: - delete[] pRectBuf; - delete[] pCharBuf; - - return hr; -} -#endif // (NTDDI_VERSION >= NTDDI_WINBLUE) -HRESULT CSocMft0::FillBufferLengthFromMediaType( - _In_ IMFMediaType *pPreviewType, - _Inout_ IMFMediaBuffer *pBuffer -) -{ - if (!pPreviewType || !pBuffer) - { - return E_INVALIDARG; - } - - UINT32 uiWidth = 0, uiHeight = 0, uiImageSize = 0; - GUID guidSubType = {}; - - HRESULT hr = MFGetAttributeSize(pPreviewType, MF_MT_FRAME_SIZE, &uiWidth, &uiHeight); - if (FAILED(hr)) - { - return hr; - } - - hr = pPreviewType->GetGUID(MF_MT_SUBTYPE, &guidSubType); - if (FAILED(hr)) - { - return hr; - } - - hr = MFCalculateImageSize(guidSubType, uiWidth, uiHeight, &uiImageSize); - if (FAILED(hr)) - { - return hr; - } - - return pBuffer->SetCurrentLength(uiImageSize); -} - -HRESULT CSocMft0::GetVideoStabilizationEnabled() -{ - HRESULT hr = S_OK; - ComPtr spKsControl; - KSPROPERTY ksProperty = { 0 }; - KSPROPERTY_CUSTOM_CAMERACONTROL_MFT0_VIDEOSTABILIZATION_S ksData = { 0 }; - ULONG bytesReturned = 0; - - if (m_spSourceTransform != NULL) - { - hr = m_spSourceTransform.As(&spKsControl); - if (SUCCEEDED(hr)) - { - ksProperty.Set = PROPSETID_VIDCAP_CUSTOM_CAMERACONTROL_MFT0; - ksProperty.Id = KSPROPERTY_CUSTOM_CAMERACONTROL_MFT0_VIDEOSTABILIZATION; - ksProperty.Flags = KSPROPERTY_TYPE_GET; - - hr = spKsControl->KsProperty(&ksProperty, sizeof(ksProperty), &ksData, sizeof(ksData), &bytesReturned); - if (SUCCEEDED(hr)) - { - m_bEnableVideoStabilization = ksData.VideoStabilizationEnabled; - } - } - } - else - { - hr = E_INVALIDARG; - } - return hr; -} diff --git a/avstream/avscamera/mft0/MFT0Impl.h b/avstream/avscamera/mft0/MFT0Impl.h deleted file mode 100644 index 9427dd7d4..000000000 --- a/avstream/avscamera/mft0/MFT0Impl.h +++ /dev/null @@ -1,316 +0,0 @@ -/************************************************************************** - - A/V Stream Camera Sample - - Copyright (c) 2013, Microsoft Corporation. - - File: - - Mft0Impl.h - - Abstract: - - The CSocMft0 class definition - an implementation of the iSocMft0 - interface found in Mft0.idl. - - History: - - created 4/26/2013 - -**************************************************************************/ - - -#pragma once -#include "Mft0.h" -#include "SampleHelpers.h" -#include "Mft0clsid.h" - -#include - -// CSocMft0 -#define FaceDetectionDelayMax 2 //frames between emitting facedetection data - -ULONG DllAddRef(); -ULONG DllRelease(); - -using namespace Microsoft::WRL; - -class CSocMft0: - public Microsoft::WRL::RuntimeClass, - ISocMft0, - IMFTransform, - IInspectable> -{ - -public: - - static HRESULT CreateInstance(REFIID iid, void **ppMFT); - - CSocMft0(): - m_bEnableEffects(TRUE), - m_bEnableVideoStabilization(FALSE), - m_uiSourceStreamId(0), - m_uiInternalState(0), - m_uThumbnailScaleFactor(4) - { - InitializeCriticalSection(&m_critSec); - m_stThumbnailFormat = MFVideoFormat_ARGB32; - DllAddRef(); - - } - - HRESULT FinalConstruct(); - -public: - - /*ISocMft0*/ - STDMETHOD(SetState)(UINT32 state); - STDMETHOD(GetState)(UINT32 *pState); - - /*IInspectable*/ - STDMETHOD(GetIids)( - _Out_ ULONG *iidCount, - _Outptr_result_buffer_maybenull_(*iidCount) - IID **iids - ); - - STDMETHOD(GetRuntimeClassName)( - _Outptr_result_maybenull_ HSTRING *pClassName - ); - - STDMETHOD(GetTrustLevel)( - _Out_ TrustLevel *trustLevel - ); - - /*IMFTransform*/ - STDMETHOD(GetStreamLimits)( - _Out_ DWORD *pdwInputMinimum, - _Out_ DWORD *pdwInputMaximum, - _Out_ DWORD *pdwOutputMinimum, - _Out_ DWORD *pdwOutputMaximum - ); - - STDMETHOD(GetStreamCount)( - _Out_ DWORD *pcInputStreams, - _Out_ DWORD *pcOutputStreams - ); - - STDMETHOD(GetStreamIDs)( - DWORD dwInputIDArraySize, - _Out_writes_(dwInputIDArraySize) DWORD *pdwInputIDs, - DWORD dwOutputIDArraySize, - _Out_writes_(dwOutputIDArraySize) DWORD *pdwOutputIDs - ); - - STDMETHOD(GetInputStreamInfo)( - DWORD dwInputStreamID, - _Out_ MFT_INPUT_STREAM_INFO *pStreamInfo - ); - - STDMETHOD(GetOutputStreamInfo)( - DWORD dwOutputStreamID, - _Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo - ); - - STDMETHOD(GetAttributes)( - _Outptr_result_maybenull_ IMFAttributes **pAttributes - ); - - STDMETHOD(GetInputStreamAttributes)( - DWORD dwInputStreamID, - _Outptr_result_maybenull_ IMFAttributes **pAttributes - ); - - STDMETHOD(GetOutputStreamAttributes)( - DWORD dwOutputStreamID, - _Outptr_result_maybenull_ - IMFAttributes **pAttributes - ); - - STDMETHOD(DeleteInputStream)( - DWORD dwStreamID - ); - - STDMETHOD(AddInputStreams)( - DWORD cStreams, - _In_ DWORD *adwStreamIDs - ); - - STDMETHOD(GetInputAvailableType)( - DWORD dwInputStreamID, - DWORD dwTypeIndex, - _Outptr_result_maybenull_ IMFMediaType **ppType - ); - - STDMETHOD(GetOutputAvailableType)( - DWORD dwOutputStreamID, - DWORD dwTypeIndex, - _Outptr_result_maybenull_ IMFMediaType **ppType - ); - - STDMETHOD(SetInputType)( - DWORD dwInputStreamID, - _In_opt_ IMFMediaType *pType, - DWORD dwFlags); - - STDMETHOD(SetOutputType)( - DWORD dwOutputStreamID, - _In_opt_ IMFMediaType *pType, - DWORD dwFlags); - - STDMETHOD(GetInputCurrentType)( - DWORD dwInputStreamID, - _Outptr_result_maybenull_ IMFMediaType **ppType - ); - - STDMETHOD(GetOutputCurrentType)( - DWORD dwOutputStreamID, - _Outptr_result_maybenull_ IMFMediaType **ppType - ); - - STDMETHOD(GetInputStatus)( - DWORD dwInputStreamID, - _Out_ DWORD *pdwFlags - ); - - STDMETHOD(GetOutputStatus)( - _Out_ DWORD *pdwFlags - ); - - STDMETHOD(SetOutputBounds)( - LONGLONG hnsLowerBound, - LONGLONG hnsUpperBound - ); - - STDMETHOD(ProcessEvent)( - DWORD dwInputStreamID, - _In_opt_ IMFMediaEvent *pEvent - ); - - STDMETHOD(ProcessMessage)( - MFT_MESSAGE_TYPE eMessage, - ULONG_PTR ulParam - ); - - STDMETHOD(ProcessInput)( - DWORD dwInputStreamID, - IMFSample *pSample, - DWORD dwFlags - ); - - STDMETHOD(ProcessOutput)( - DWORD dwFlags, - DWORD cOutputBufferCount, - MFT_OUTPUT_DATA_BUFFER *pOutputSamples, - DWORD *pdwStatus - ); - -protected: - virtual ~CSocMft0() - { - DeleteCriticalSection(&m_critSec); - DllRelease(); - } - - STDMETHOD(GetMediaType)( - _In_ DWORD dwStreamID, - _In_ DWORD dwTypeIndex, - _Outptr_result_maybenull_ IMFMediaType **ppType - ); - - STDMETHOD(IsMediaTypeSupported)( - _In_ UINT uiStreamId, - _In_opt_ IMFMediaType *pIMFMediaType, - _Outptr_opt_result_maybenull_ IMFMediaType **ppIMFMediaTypeFull = NULL - ); - - STDMETHOD(GenerateMFMediaTypeListFromDevice)(); - - _Success_(return == 0) - STDMETHOD(FindMediaIndex)( - _In_ UINT uiStreamId, - _In_ IMFMediaType *pIMFMediaType, - _Out_ UINT *puiMediaIndex - ); - - // HasPendingOutput: Returns TRUE if the MFT is holding an input sample. - BOOL HasPendingOutput() const - { - return m_spSample != NULL; - } - - HRESULT CreateOutputSample( - _Outptr_result_maybenull_ IMFSample **ppSample - ); - - HRESULT GetPreviewMediaType( - _Outptr_result_maybenull_ IMFMediaType **ppType - ); -#if (NTDDI_VERSION >= NTDDI_WINBLUE) - HRESULT ProcessMetadata(); - - HRESULT ParseMetadata_PreviewAggregation( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes - ); - - HRESULT ParseMetadata_ImageAggregation( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes - ); - - HRESULT ParseMetadata_Histogram( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes - ); - - HRESULT ParseMetadata_FaceDetection( - _In_ PKSCAMERA_METADATA_ITEMHEADER pItem, - _In_ IMFAttributes *pMetaDataAttributes - ); -#endif // (NTDDI_VERSION >= NTDDI_WINBLUE) - HRESULT FillBufferLengthFromMediaType( - _In_ IMFMediaType *pPreviewType, - _Inout_ IMFMediaBuffer *pBuffer - ); - - STDMETHOD(OnFlush)(); - - HRESULT GetVideoStabilizationEnabled(); - - HRESULT GetThumbnailResolution(); - - HRESULT OnProcessImage( - _Outptr_result_maybenull_ - IMFSample **ppIMFOutputSample - ); - - CRITICAL_SECTION m_critSec; - - ComPtr m_spSample; // Input sample. - ComPtr m_spInputType; // Input media type. - ComPtr m_spOutputType; // Output media type. - - // Image transform function. (Changes based on the media type.) - ComPtr m_spInputAttributes; - ComPtr m_spGlobalAttributes; - GUID m_stStreamType; - ComPtr m_spSourceTransform; - volatile BOOL m_bEnableEffects; - BOOL m_bEnableVideoStabilization; - UINT m_uiSourceStreamId; - UINT m_uiInternalState; - BYTE m_uThumbnailScaleFactor; - GUID m_stThumbnailFormat; - - std::vector> - m_listOfMediaTypes; - -}; - -inline HRESULT MFT0CreateInstance(REFIID riid, void **ppv) -{ - return CSocMft0::CreateInstance(riid, ppv); -} - -//CoCreateableClass(CSocMft0); \ No newline at end of file diff --git a/avstream/avscamera/mft0/MFT0clsid.h b/avstream/avscamera/mft0/MFT0clsid.h deleted file mode 100644 index d8aad5f5c..000000000 --- a/avstream/avscamera/mft0/MFT0clsid.h +++ /dev/null @@ -1,26 +0,0 @@ -/************************************************************************** - - A/V Stream Camera Sample - - Copyright (c) 2015, Microsoft Corporation. - - File: - - Mft0clsid.h - - Abstract: - - Define the Class GUID of the MFT. - - History: - - created 2/19/2015 - -**************************************************************************/ - -#pragma once - -// CLSID of the MFT. -// {1C2CE17A-FAAD-4E73-85E7-167068093F25} -DEFINE_GUID(CLSID_AvsCamMft0, - 0x1c2ce17a, 0xfaad, 0x4e73, 0x85, 0xe7, 0x16, 0x70, 0x68, 0x9, 0x3f, 0x25); diff --git a/avstream/avscamera/mft0/SampleHelpers.h b/avstream/avscamera/mft0/SampleHelpers.h deleted file mode 100644 index 11908f829..000000000 --- a/avstream/avscamera/mft0/SampleHelpers.h +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************************** - - A/V Stream Camera Sample - - Copyright (c) 2013, Microsoft Corporation. - - File: - - SampleHelpers.h - - Abstract: - - Helper classes for the MFT0. - - History: - - created 4/26/2013 - -**************************************************************************/ - -#pragma once - -/***************************************************************************\ -***************************************************************************** -* -* class CAutoLock -* -* Locks a critical section at construction time and unlocks it automatically -* when the object goes out of scope -* -***************************************************************************** -\***************************************************************************/ - -class CAutoLock -{ -private: - // Make copy constructor and assignment operator inaccessible - CAutoLock(const CAutoLock &refAutoLock); - CAutoLock &operator=(const CAutoLock &refAutoLock); - - // CAutoLock should not be created on the heap, so declare - // (but do not implement) private operator new/delete. - static void *operator new(size_t); - static void operator delete(void *); - static void *operator new[](size_t); - static void operator delete[](void *); - -protected: - CRITICAL_SECTION *m_pLock; - -public: - _Acquires_lock_(m_pLock) - explicit CAutoLock(CRITICAL_SECTION *pLock): - m_pLock(pLock) - { - EnterCriticalSection(m_pLock); - } - - _Releases_lock_(m_pLock) - ~CAutoLock() - { - LeaveCriticalSection(m_pLock); - } -}; - -class MediaBufferLock -{ -public: - MediaBufferLock(_In_ IMFMediaBuffer *pBuffer): - m_bLocked(false) - { - m_spBuffer = pBuffer; - } - - HRESULT LockBuffer( - _Outptr_result_bytebuffer_to_(*pcbMaxLength, *pcbCurrentLength) BYTE **ppbBuffer, - _Out_opt_ DWORD *pcbMaxLength, - _Out_opt_ DWORD *pcbCurrentLength) - { - if(!m_spBuffer) - { - return E_INVALIDARG; - } - - HRESULT hr = m_spBuffer->Lock(ppbBuffer, pcbMaxLength, pcbCurrentLength); - if(FAILED(hr)) - { - return hr; - } - m_bLocked = true; - return S_OK; - } - - ~MediaBufferLock() - { - if(m_spBuffer && m_bLocked) - { - //Unlock fails only if we did not lock it first - (void) m_spBuffer->Unlock(); - } - } - -private: - ComPtr m_spBuffer; - bool m_bLocked; -}; diff --git a/avstream/avscamera/mft0/dllmain.cpp b/avstream/avscamera/mft0/dllmain.cpp deleted file mode 100644 index b57464177..000000000 --- a/avstream/avscamera/mft0/dllmain.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/************************************************************************** - - A/V Stream Camera Sample - - Copyright (c) 2014, Microsoft Corporation. - - File: - - dllmain.cpp - - Abstract: - - DLL and COM initialization. - - History: - - created 5/15/2014 - -**************************************************************************/ -//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -//// PARTICULAR PURPOSE. -//// -//// Copyright (c) Microsoft Corporation. All rights reserved - - -#include "stdafx.h" -#include "Mft0.h" -#include "Mft0clsid.h" -#include "Mft0Impl.h" -#include - -using namespace Microsoft::WRL; - -// Module Ref count -volatile ULONG g_cRefModule = 0; - -// Handle to the DLL's module -HMODULE g_hModule = NULL; - -ULONG DllAddRef() -{ - return InterlockedIncrement(&g_cRefModule); -} - -ULONG DllRelease() -{ - return InterlockedDecrement(&g_cRefModule); -} - -class CClassFactory : public IClassFactory -{ -public: - static HRESULT CreateInstance( - REFCLSID clsid, - REFIID riid, - _COM_Outptr_ void **ppv - ) - { - *ppv = NULL; - - HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; - - if(IsEqualGUID(clsid, CLSID_AvsCamMft0)) - { - IClassFactory *pClassFactory = new (std::nothrow) CClassFactory(); - if(!pClassFactory) - { - return E_OUTOFMEMORY; - } - hr = pClassFactory->QueryInterface(riid, ppv); - pClassFactory->Release(); - } - return hr; - } - - //IUnknown methods - IFACEMETHODIMP QueryInterface(REFIID riid, void **ppvObject) - { - HRESULT hr = S_OK; - - if(ppvObject == NULL) - { - return E_POINTER; - } - - if(riid == IID_IUnknown) - { - *ppvObject = (IUnknown*)this; - } - else if(riid == IID_IClassFactory) - { - *ppvObject = (IClassFactory*)this; - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - AddRef(); - - return hr; - } - - IFACEMETHODIMP_(ULONG) AddRef() - { - return InterlockedIncrement(&m_cRef); - } - - IFACEMETHODIMP_(ULONG) Release() - { - long cRef = InterlockedDecrement(&m_cRef); - if(cRef == 0) - { - delete this; - } - return cRef; - } - - //IClassFactory Methods - IFACEMETHODIMP CreateInstance(_In_ IUnknown *punkOuter, _In_ REFIID riid, _Outptr_ void **ppv) - { - return punkOuter ? CLASS_E_NOAGGREGATION : MFT0CreateInstance(riid, ppv); - } - - IFACEMETHODIMP LockServer(BOOL fLock) - { - if(fLock) - { - DllAddRef(); - } - else - { - DllRelease(); - } - return S_OK; - } - -private: - CClassFactory() : - m_cRef(1) - { - DllAddRef(); - } - - ~CClassFactory() - { - DllRelease(); - } - - long m_cRef; -}; - - - - -STDAPI_(BOOL) DllMain(_In_ HINSTANCE hinst, DWORD reason, _In_opt_ void *) -{ - if (reason == DLL_PROCESS_ATTACH) - { - g_hModule = (HMODULE)hinst; - DisableThreadLibraryCalls(hinst); - } - return TRUE; -} - -// -// DllCanUnloadNow -// -///////////////////////////////////////////////////////////////////////// -__control_entrypoint(DllExport) -STDAPI DllCanUnloadNow() -{ - return (g_cRefModule == 0) ? S_OK : S_FALSE; -} - -///////////////////////////////////////////////////////////////////////// -// -// DllGetClassObject -// -///////////////////////////////////////////////////////////////////////// -_Check_return_ -STDAPI DllGetClassObject( - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Outptr_ LPVOID FAR *ppv -) -{ - return CClassFactory::CreateInstance(rclsid, riid, ppv); -} diff --git a/avstream/avscamera/mft0/stdafx.h b/avstream/avscamera/mft0/stdafx.h deleted file mode 100644 index 6d784805c..000000000 --- a/avstream/avscamera/mft0/stdafx.h +++ /dev/null @@ -1,39 +0,0 @@ -//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -//// PARTICULAR PURPOSE. -//// -//// Copyright (c) Microsoft Corporation. All rights reserved - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#ifndef STRICT -#define STRICT -#endif - -#include "targetver.h" -#if (NTDDI_VERSION >= NTDDI_WIN10_VB) -#pragma message("MFT0 is deprecated for this target Windows version and beyond- Change project settings to target an older version of Windows") -#endif - -#if (NTDDI_VERSION <= NTDDI_WIN7) -// TODO: disable the MFT0 conditional to the target system version -#pragma message("MFT0 is in not supported in this target Windows version - Change project settings to target a newer version of Windows") -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace Microsoft::WRL; \ No newline at end of file diff --git a/avstream/avscamera/mft0/stdafxsrc.cpp b/avstream/avscamera/mft0/stdafxsrc.cpp deleted file mode 100644 index 1577c4e3b..000000000 --- a/avstream/avscamera/mft0/stdafxsrc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" \ No newline at end of file diff --git a/avstream/avscamera/mft0/targetver.h b/avstream/avscamera/mft0/targetver.h deleted file mode 100644 index fc349fa5f..000000000 --- a/avstream/avscamera/mft0/targetver.h +++ /dev/null @@ -1,15 +0,0 @@ -//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -//// PARTICULAR PURPOSE. -//// -//// Copyright (c) Microsoft Corporation. All rights reserved - -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include diff --git a/avstream/avscamera/sys/AvsCamera.vcxproj b/avstream/avscamera/sys/AvsCamera.vcxproj index 5456ee7ac..74cada21f 100644 --- a/avstream/avscamera/sys/AvsCamera.vcxproj +++ b/avstream/avscamera/sys/AvsCamera.vcxproj @@ -31,7 +31,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -39,7 +39,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -47,7 +47,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -55,7 +55,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -256,4 +256,4 @@ - + \ No newline at end of file diff --git a/avstream/avscamera/sys/AvsCamera.vcxproj.Filters b/avstream/avscamera/sys/AvsCamera.vcxproj.Filters index 8d9ec4698..1c346b6c2 100644 --- a/avstream/avscamera/sys/AvsCamera.vcxproj.Filters +++ b/avstream/avscamera/sys/AvsCamera.vcxproj.Filters @@ -1,4 +1,4 @@ - + @@ -97,10 +97,23 @@ Source Files + + Source Files + Resource Files + + + Header Files + + + + + Driver Files + + \ No newline at end of file diff --git a/avstream/avscamera/sys/Capture.cpp b/avstream/avscamera/sys/Capture.cpp index 25e6a5f88..730370e60 100644 --- a/avstream/avscamera/sys/Capture.cpp +++ b/avstream/avscamera/sys/Capture.cpp @@ -2294,6 +2294,7 @@ SetFramingSizes( PKSALLOCATOR_FRAMING_EX Framing ) { + PAGED_CODE(); Framing->FramingItem[0].PhysicalRange.MinFrameSize = m_VideoInfoHeader->bmiHeader.biSizeImage; Framing->FramingItem[0].PhysicalRange.MaxFrameSize = m_VideoInfoHeader->bmiHeader.biSizeImage; Framing->FramingItem[0].FramingRange.Range.MinFrameSize = m_VideoInfoHeader->bmiHeader.biSizeImage; diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp index 2741da08e..38d4f555f 100644 --- a/avstream/avscamera/sys/Device.cpp +++ b/avstream/avscamera/sys/Device.cpp @@ -110,6 +110,7 @@ IrpSynchronousCompletion( IN PVOID pKevent ) { + PAGED_CODE(); if (Irp->PendingReturned) { NT_ASSERT(pKevent); diff --git a/avstream/avscamera/sys/avscamera.inx b/avstream/avscamera/sys/avscamera.inx index f6f1e8469..f75da695e 100644 Binary files a/avstream/avscamera/sys/avscamera.inx and b/avstream/avscamera/sys/avscamera.inx differ diff --git a/avstream/avscamera/sys/hwsim.cpp b/avstream/avscamera/sys/hwsim.cpp index fdf7b3673..80a4adcfc 100644 --- a/avstream/avscamera/sys/hwsim.cpp +++ b/avstream/avscamera/sys/hwsim.cpp @@ -796,6 +796,7 @@ bool CHardwareSimulation:: CheckForAvailableBuffer() { + PAGED_CODE(); return true; } @@ -803,6 +804,7 @@ NTSTATUS CHardwareSimulation:: CommitImageData(PSCATTER_GATHER_ENTRY sGEntry, ULONG stride) { + PAGED_CODE(); // Have the synthesizer output a frame to the buffer. ULONG CommitBufferSize = sGEntry->ByteCount; PUCHAR CommitBufferAddress = sGEntry->Virtual; @@ -818,6 +820,7 @@ NTSTATUS CHardwareSimulation:: ValidateBuffer(PSCATTER_GATHER_ENTRY sGEntry) { + PAGED_CODE(); return STATUS_SUCCESS; } diff --git a/avstream/avshws/avshws.inx b/avstream/avshws/avshws.inx index 238ce1878..9409635d3 100644 Binary files a/avstream/avshws/avshws.inx and b/avstream/avshws/avshws.inx differ diff --git a/avstream/avshws/avshws.vcxproj b/avstream/avshws/avshws.vcxproj index 407048b73..11fb4c396 100644 --- a/avstream/avshws/avshws.vcxproj +++ b/avstream/avshws/avshws.vcxproj @@ -45,7 +45,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -53,7 +53,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -61,7 +61,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -69,7 +69,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -77,7 +77,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -85,7 +85,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -93,7 +93,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -101,7 +101,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver diff --git a/avstream/avshws/avshws.vcxproj.Filters b/avstream/avshws/avshws.vcxproj.Filters index 4e32a73fd..bc11045f2 100644 --- a/avstream/avshws/avshws.vcxproj.Filters +++ b/avstream/avshws/avshws.vcxproj.Filters @@ -1,4 +1,4 @@ - + @@ -43,4 +43,14 @@ Resource Files + + + Header Files + + + + + Driver Files + + \ No newline at end of file diff --git a/avstream/avssamp/avssamp.inx b/avstream/avssamp/avssamp.inx index 61d66fa37..c06925ea3 100644 Binary files a/avstream/avssamp/avssamp.inx and b/avstream/avssamp/avssamp.inx differ diff --git a/avstream/avssamp/avssamp.vcxproj b/avstream/avssamp/avssamp.vcxproj index 58d7992df..dfe36af75 100644 --- a/avstream/avssamp/avssamp.vcxproj +++ b/avstream/avssamp/avssamp.vcxproj @@ -29,7 +29,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -37,7 +37,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -45,7 +45,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -53,7 +53,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver diff --git a/avstream/avssamp/avssamp.vcxproj.Filters b/avstream/avssamp/avssamp.vcxproj.Filters index 8d3458319..5a9d5e00b 100644 --- a/avstream/avssamp/avssamp.vcxproj.Filters +++ b/avstream/avssamp/avssamp.vcxproj.Filters @@ -1,4 +1,4 @@ - + @@ -53,24 +53,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - diff --git a/avstream/sampledevicemft/SampleSocDeviceMFT.cpp b/avstream/sampledevicemft/SampleSocDeviceMFT.cpp new file mode 100644 index 000000000..2a91906f8 --- /dev/null +++ b/avstream/sampledevicemft/SampleSocDeviceMFT.cpp @@ -0,0 +1,1533 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// + +#include "stdafx.h" +#include "multipinmft.h" +#ifdef MF_WPP +#include "multipinmft.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif +// +// Note since MFT_UNIQUE_METHOD_NAMES is defined all the functions of IMFTransform have the Mft suffix.. +// +extern const CLSID CLSID_HwMFTActivate; + +CMultipinMft::CMultipinMft() +: m_nRefCount( 0 ), + m_InputPinCount( 0 ), + m_OutputPinCount( 0 ), + m_dwWorkQueueId ( MFASYNC_CALLBACK_QUEUE_MULTITHREADED ), + m_lWorkQueuePriority ( 0 ), + m_spAttributes( nullptr ), + m_spSourceTransform( nullptr ), + m_SymbolicLink(nullptr) +{ + HRESULT hr = S_OK; + ComPtr pAttributes = nullptr; + MFCreateAttributes( &pAttributes, 0 ); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32( MF_TRANSFORM_ASYNC, TRUE ),done); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32( MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, TRUE ),done); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32( MF_SA_D3D_AWARE, TRUE ), done); + DMFTCHECKHR_GOTO(pAttributes->SetString( MFT_ENUM_HARDWARE_URL_Attribute, L"SampleMultiPinMft" ),done); + m_spAttributes = pAttributes; +done: + if (FAILED(hr)) + { + + } +} + +CMultipinMft::~CMultipinMft( ) +{ + + + for ( ULONG ulIndex = 0, ulSize = (ULONG) m_InPins.size(); ulIndex < ulSize; ulIndex++ ) + { + SAFERELEASE(m_InPins[ ulIndex ]); + } + m_InPins.clear(); + for (ULONG ulIndex = 0, ulSize = (ULONG) m_OutPins.size(); ulIndex < ulSize; ulIndex++) + { + SAFERELEASE(m_OutPins[ ulIndex ]); + } + m_OutPins.clear(); + SAFE_ARRAYDELETE(m_SymbolicLink); + m_spSourceTransform = nullptr; + +} + +STDMETHODIMP_(ULONG) CMultipinMft::AddRef( + void + ) +{ + return InterlockedIncrement(&m_nRefCount); +} + +STDMETHODIMP_(ULONG) CMultipinMft::Release( + void + ) +{ + ULONG uCount = InterlockedDecrement(&m_nRefCount); + + if ( uCount == 0 ) + { + delete this; + } + return uCount; +} + +STDMETHODIMP CMultipinMft::QueryInterface( + _In_ REFIID iid, + _COM_Outptr_ void** ppv + ) +{ + + HRESULT hr = S_OK; + *ppv = NULL; + + if ((iid == __uuidof(IMFDeviceTransform)) || (iid == __uuidof(IUnknown))) + { + *ppv = static_cast< IMFDeviceTransform* >(this); + } + else if ( iid == __uuidof( IMFMediaEventGenerator ) ) + { + *ppv = static_cast< IMFMediaEventGenerator* >(this); + } + else if ( iid == __uuidof( IMFShutdown ) ) + { + *ppv = static_cast< IMFShutdown* >( this ); + } +#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES) + else if (iid == __uuidof(IMFTransform)) + { + *ppv = static_cast< IMFTransform* >(this); + } +#endif + else if ( iid == __uuidof( IKsControl ) ) + { + *ppv = static_cast< IKsControl* >( this ); + } + else if ( iid == __uuidof( IMFRealTimeClientEx ) ) + { + *ppv = static_cast< IMFRealTimeClientEx* >( this ); + } + +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + else if (iid == __uuidof(IMFSampleAllocatorControl)) + { + *ppv = static_cast(this); + } +#endif + else + { + hr = E_NOINTERFACE; + goto done; + } + AddRef(); +done: + return hr; +} + +/*++ + Description: + This function is the entry point of the transform + The following things may be initialized here + 1) Query for MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL on the attributes supplied + 2) From the IUnknown acquired get the IMFTransform interface. + 3) Get the stream count.. The output streams are of consequence to the tranform. + The input streams should correspond to the output streams exposed by the source transform + acquired from the Attributes supplied. + 4) Get the IKSControl which is used to send KSPROPERTIES, KSEVENTS and KSMETHODS to the driver for the filer level. Store it in your filter class + 5) Get the OutPutStreamAttributes for the output pins of the source transform. This can further be used to QI and acquire + the IKSControl related to the specific pin. This can be used to send PIN level KSPROPERTIES, EVENTS and METHODS to the pins + 6) Create the output pins + +--*/ + +// This sample will create a grayscale for known media types. Please remove MF_DEVICEMFT_ADD_GRAYSCALER_ to remove the grayscaler +// This sample also has photo confirmation enabled remove DMF_DEVICEMFT_PHTOTOCONFIRMATION to remove photo confirmation +// Please search for the @@@@ README tag for critical sections in code and it's documentation +// +STDMETHODIMP CMultipinMft::InitializeTransform ( + _In_ IMFAttributes *pAttributes + ) +{ + HRESULT hr = S_OK; + ComPtr spFilterUnk = nullptr; + DWORD *pcInputStreams = NULL, *pcOutputStreams = NULL; + DWORD inputStreams = 0; + DWORD outputStreams = 0; + GUID* outGuids = NULL; + GUID streamCategory = GUID_NULL; + ULONG ulOutPinIndex = 0; + UINT32 uiSymLinkLen = 0; + CPinCreationFactory* pPinFactory = new (std::nothrow) CPinCreationFactory(this); + DMFTCHECKNULL_GOTO( pAttributes, done, E_INVALIDARG ); + // + // The attribute passed with MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL is the source transform. This generally represents a filter + // This needs to be stored so that we know the device properties. We cache it. We query for the IKSControl which is used to send + // controls to the driver. + // + DMFTCHECKHR_GOTO( pAttributes->GetUnknown( MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL,IID_PPV_ARGS( &spFilterUnk ) ),done ); + + if (SUCCEEDED(pAttributes->GetStringLength(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &uiSymLinkLen))) // Not available prior to RS5 + { + m_SymbolicLink = new (std::nothrow) WCHAR[++uiSymLinkLen]; + DMFTCHECKNULL_GOTO(m_SymbolicLink, done, E_OUTOFMEMORY); + DMFTCHECKHR_GOTO(pAttributes->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, m_SymbolicLink, uiSymLinkLen, &uiSymLinkLen), done); + } + + DMFTCHECKHR_GOTO( spFilterUnk.As( &m_spSourceTransform ), done ); + + DMFTCHECKHR_GOTO( m_spSourceTransform.As( &m_spIkscontrol ), done ); + + DMFTCHECKHR_GOTO( m_spSourceTransform->MFTGetStreamCount( &inputStreams, &outputStreams ), done ); + + spFilterUnk = nullptr; + + // + //The number of input pins created by the device transform should match the pins exposed by + //the source transform i.e. outputStreams from SourceTransform or DevProxy = Input pins of the Device MFT + // + + if ( inputStreams > 0 || outputStreams > 0 ) + { + pcInputStreams = new (std::nothrow) DWORD[ inputStreams ]; + DMFTCHECKNULL_GOTO( pcInputStreams, done, E_OUTOFMEMORY); + + pcOutputStreams = new (std::nothrow) DWORD[ outputStreams ]; + DMFTCHECKNULL_GOTO( pcOutputStreams, done, E_OUTOFMEMORY ); + + DMFTCHECKHR_GOTO( m_spSourceTransform->MFTGetStreamIDs( inputStreams, pcInputStreams, + outputStreams, + pcOutputStreams ),done ); + + // + // Output pins from DevProxy = Input pins of device MFT.. We are the first transform in the pipeline before MFT0 + // + + for ( ULONG ulIndex = 0; ulIndex < outputStreams; ulIndex++ ) + { + ComPtr pInAttributes = nullptr; + BOOL bCustom = FALSE; + ComPtr spInPin; + + DMFTCHECKHR_GOTO(pPinFactory->CreatePin( + pcOutputStreams[ulIndex], /*Input Pin ID as advertised by the pipeline*/ + 0, /*This is not needed for Input Pin*/ + CPinCreationFactory::DMFT_PIN_INPUT, /*Input Pin*/ + (CBasePin**)spInPin.GetAddressOf(), + bCustom), done); + if (bCustom) + { + m_CustomPinCount++; + } + hr = ExceptionBoundary([&]() + { + m_InPins.push_back(spInPin.Get()); + }); + DMFTCHECKHR_GOTO(hr, done); + DMFTCHECKHR_GOTO( spInPin->Init(m_spSourceTransform.Get() ), done); + spInPin.Detach(); + } + + // + // Create one on one mapping + // + for (ULONG ulIndex = 0; ulIndex < m_InPins.size(); ulIndex++) + { + + ComPtr spoPin; + BOOL bCustom = FALSE; + ComPtr spiPin = ( CInPin * )m_InPins[ ulIndex ]; + + if (spiPin.Get()) + { + BOOL isCustom = false; + if (SUCCEEDED(CheckCustomPin(spiPin.Get(), &isCustom)) && (isCustom)) + { + // + // In this sample we are not connecting the custom pin to the output + // This is because we really have no way of testing the custom pin with the + // pipeline. + // This however can be changed if the custom media type is converted here in + // the device MFT and later exposed to the pipeline.. + // + continue; + } + + DMFTCHECKHR_GOTO(pPinFactory->CreatePin(spiPin->streamId(), /*Input Pin connected to the Output Pin*/ + ulOutPinIndex, /*Output pin Id*/ + CPinCreationFactory::DMFT_PIN_OUTPUT, /*Output pin */ + (CBasePin**)spoPin.ReleaseAndGetAddressOf(), + bCustom), done); + hr = BridgeInputPinOutputPin(spiPin.Get(), spoPin.Get()); + if (SUCCEEDED(hr)) + { + DMFTCHECKHR_GOTO(ExceptionBoundary([&]() + { + m_OutPins.push_back(spoPin.Get()); + }), done); + spoPin.Detach(); + ulOutPinIndex++; + hr = S_OK; + } + if (hr == MF_E_INVALID_STREAM_DATA) + { + // Skip the pin which doesn't have any mediatypes exposed + hr = S_OK; + } + DMFTCHECKHR_GOTO(hr, done); + } + } + + } + + m_InputPinCount = ULONG ( m_InPins.size() ); + m_OutputPinCount = ULONG ( m_OutPins.size() ); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!",hr,hr); + + if ( pcInputStreams ) + { + delete[ ] ( pcInputStreams ); + } + if ( pcOutputStreams ) + { + delete[ ] ( pcOutputStreams ); + } + if ( outGuids ) + { + delete [] ( outGuids ); + } + SAFE_DELETE(pPinFactory); + if ( FAILED( hr ) ) + { + //Release the pins and the resources acquired + for (ULONG ulIndex = 0, ulSize = (ULONG)m_InPins.size(); ulIndex < ulSize; ulIndex++) + { + SAFERELEASE(m_InPins[ulIndex]); + } + m_InPins.clear(); + for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++) + { + SAFERELEASE(m_OutPins[ulIndex]); + } + m_OutPins.clear(); + // + // Simply clear the custom pins since the input pins must have deleted the pin + // + m_spSourceTransform = nullptr; + m_spIkscontrol = nullptr; + } + return hr; +} + + +STDMETHODIMP CMultipinMft::SetWorkQueueEx( + _In_ DWORD dwWorkQueueId, + _In_ LONG lWorkItemBasePriority + ) +/*++ + Description: + + Implements IMFRealTimeClientEx::SetWorkQueueEx function + +--*/ +{ + CAutoLock lock( m_critSec ); + // + // Cache the WorkQueuId and WorkItemBasePriority. This is called once soon after the device MFT is initialized + // + m_dwWorkQueueId = dwWorkQueueId; + m_lWorkQueuePriority = lWorkItemBasePriority; + // Set it on the pins + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_InPins.size(); dwIndex++) + { + m_InPins[dwIndex]->SetWorkQueue(dwWorkQueueId); + } + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_OutPins.size(); dwIndex++) + { + m_OutPins[dwIndex]->SetWorkQueue(dwWorkQueueId); + } + return S_OK; + +} + +// +// IMFDeviceTransform functions +// +STDMETHODIMP CMultipinMft::GetStreamCount( + _Inout_ DWORD *pdwInputStreams, + _Inout_ DWORD *pdwOutputStreams + ) +/*++ + Description: Implements IMFTransform::GetStreamCount function +--*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + DMFTCHECKNULL_GOTO(pdwInputStreams, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(pdwOutputStreams, done, E_INVALIDARG); + *pdwInputStreams = m_InputPinCount; + *pdwOutputStreams = m_OutputPinCount; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); +done: + return hr; +} + +// +//Doesn't strictly conform to the GetStreamIDs on IMFTransform Interface! +// +STDMETHODIMP CMultipinMft::GetStreamIDs( + _In_ DWORD dwInputIDArraySize, + _When_(dwInputIDArraySize >= m_InputPinCount, _Out_writes_(dwInputIDArraySize)) DWORD* pdwInputIDs, + _In_ DWORD dwOutputIDArraySize, + _When_(dwOutputIDArraySize >= m_OutputPinCount && (pdwInputIDs && (dwInputIDArraySize > 0)), + _Out_writes_(dwOutputIDArraySize)) _On_failure_(_Valid_) DWORD* pdwOutputIDs + ) +/*++ + Description: + Implements IMFTransform::GetStreamIDs function +--*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + if ( ( dwInputIDArraySize < m_InputPinCount ) && ( dwOutputIDArraySize < m_OutputPinCount ) ) + { + hr = MF_E_BUFFERTOOSMALL; + goto done; + } + + if ( dwInputIDArraySize ) + { + DMFTCHECKNULL_GOTO( pdwInputIDs, done, E_POINTER ); + for ( DWORD dwIndex = 0; dwIndex < ((dwInputIDArraySize > m_InputPinCount) ? m_InputPinCount: + dwInputIDArraySize); dwIndex++ ) + { + pdwInputIDs[ dwIndex ] = ( m_InPins[dwIndex] )->streamId(); + } + } + + if ( dwOutputIDArraySize ) + { + DMFTCHECKNULL_GOTO( pdwOutputIDs, done, E_POINTER ); + for ( DWORD dwIndex = 0; dwIndex < ((dwOutputIDArraySize > m_OutputPinCount)? m_OutputPinCount: + dwOutputIDArraySize); dwIndex++ ) + { + pdwOutputIDs[ dwIndex ] = (m_OutPins[ dwIndex ])->streamId(); + } + } +done: + return hr; +} + +/*++ +Name: CMultipinMft::GetInputAvailableType +Description: +Implements IMFTransform::GetInputAvailableType function. This function +gets the media type supported by the specified stream based on the +index dwTypeIndex. +--*/ +STDMETHODIMP CMultipinMft::GetInputAvailableType( + _In_ DWORD dwInputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppMediaType + ) +{ + HRESULT hr = S_OK; + + ComPtr spiPin = GetInPin( dwInputStreamID ); + DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO( spiPin, done, MF_E_INVALIDSTREAMNUMBER ); + + *ppMediaType = nullptr; + + hr = spiPin->GetOutputAvailableType( dwTypeIndex,ppMediaType ); + + if (FAILED(hr)) + { + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin: %d Index: %d exiting %!HRESULT!", + dwInputStreamID, + dwTypeIndex, + hr); + } + +done: + return hr; +} + +STDMETHODIMP CMultipinMft::GetOutputAvailableType( + _In_ DWORD dwOutputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppMediaType + ) +/*++ + Description: + + Implements IMFTransform::GetOutputAvailableType function. This function + gets the media type supported by the specified stream based on the + index dwTypeIndex. + +--*/ +{ + HRESULT hr = S_OK; + CAutoLock Lock(m_critSec); + + ComPtr spoPin = GetOutPin( dwOutputStreamID ); + + DMFTCHECKNULL_GOTO( spoPin.Get(), done, MF_E_INVALIDSTREAMNUMBER ); + DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); + + *ppMediaType = nullptr; + + hr = spoPin->GetOutputAvailableType( dwTypeIndex, ppMediaType ); + + if ( FAILED( hr ) ) + { + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin: %d Index: %d exiting %!HRESULT!", + dwOutputStreamID, + dwTypeIndex, + hr ); + } + +done: + return hr; +} + +STDMETHODIMP CMultipinMft::GetInputCurrentType( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFMediaType** ppMediaType + ) +/*++ + Description: + Implements IMFTransform::GetInputCurrentType function. This function + returns the current media type set on the specified stream. +--*/ +{ + // + // The input current types will not come to this transform. + // The outputs of this transform matter. The DTM manages the + // output of this transform and the inptuts of the source transform + // + UNREFERENCED_PARAMETER(dwInputStreamID); + UNREFERENCED_PARAMETER(ppMediaType); + return S_OK; +} + +STDMETHODIMP CMultipinMft::GetOutputCurrentType( + _In_ DWORD dwOutputStreamID, + _Out_ IMFMediaType** ppMediaType + ) +/*++ + Description: + + Implements IMFTransform::GetOutputCurrentType function. This function + returns the current media type set on the specified stream. + +--*/ +{ + HRESULT hr = S_OK; + ComPtr spoPin; + CAutoLock lock( m_critSec ); + + DMFTCHECKNULL_GOTO( ppMediaType, done, E_INVALIDARG ); + + *ppMediaType = nullptr; + + spoPin = GetOutPin( dwOutputStreamID ); + + DMFTCHECKNULL_GOTO(spoPin, done, MF_E_INVALIDSTREAMNUMBER ); + + DMFTCHECKHR_GOTO(spoPin->getMediaType( ppMediaType ),done ); + + DMFTCHECKNULL_GOTO( *ppMediaType, done, MF_E_TRANSFORM_TYPE_NOT_SET ); + +done: + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); + return hr; +} + + +STDMETHODIMP CMultipinMft::ProcessEvent( + _In_ DWORD dwInputStreamID, + _In_ IMFMediaEvent* pEvent + ) + /*++ + Description: + + Implements IMFTransform::ProcessEvent function. This function + processes events that come to the MFT. + + --*/ +{ + UNREFERENCED_PARAMETER(dwInputStreamID); + UNREFERENCED_PARAMETER(pEvent); + return S_OK; +} + + + +STDMETHODIMP CMultipinMft::ProcessMessage( + _In_ MFT_MESSAGE_TYPE eMessage, + _In_ ULONG_PTR ulParam + ) +/*++ + Description: + + Implements IMFTransform::ProcessMessage function. This function + processes messages coming to the MFT. + +--*/ +{ + HRESULT hr = S_OK; + + UNREFERENCED_PARAMETER(ulParam); + + CAutoLock _lock( m_critSec ); + + printMessageEvent( eMessage ); + + switch ( eMessage ) + { + case MFT_MESSAGE_COMMAND_FLUSH: + // + // This is MFT wide flush.. Flush all output pins + // + (VOID)FlushAllStreams(); + break; + case MFT_MESSAGE_COMMAND_DRAIN: + // + // There is no draining for Device MFT. Just kept here for reference + // + break; + case MFT_MESSAGE_NOTIFY_START_OF_STREAM: + // + // No op for device MFTs + // + break; + case MFT_MESSAGE_SET_D3D_MANAGER: + { + if ( ulParam ) + { + ComPtr< IDirect3DDeviceManager9 > spD3D9Manager; + ComPtr< IMFDXGIDeviceManager > spDXGIManager; + + hr = ( ( IUnknown* ) ulParam )->QueryInterface( IID_PPV_ARGS( &spD3D9Manager ) ); + if ( SUCCEEDED( hr ) ) + { + m_spDeviceManagerUnk = ( IUnknown* )ulParam; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! IDirect3DDeviceManager9 %p, is passed", spD3D9Manager.Get() ); + } + else + { + hr = ( ( IUnknown* ) ulParam )->QueryInterface( IID_PPV_ARGS( &spDXGIManager ) ); + if ( SUCCEEDED(hr) ) + { + m_spDeviceManagerUnk = (IUnknown*)ulParam; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! IMFDXGIDeviceManager %p, is passed", spDXGIManager.Get()); + } + } + } + else + { + m_spDeviceManagerUnk = nullptr; + hr = S_OK; + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC!IDirect3DDeviceManager9 was not passed in"); + } + // + // set it on the pins. Can happen anytime + // + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_InPins.size(); dwIndex++) + { + m_InPins[dwIndex]->SetD3DManager(m_spDeviceManagerUnk.Get()); + } + for (DWORD dwIndex = 0; dwIndex < (DWORD)m_OutPins.size(); dwIndex++) + { + m_OutPins[dwIndex]->SetD3DManager(m_spDeviceManagerUnk.Get()); + } + } + break; + case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING: + { + SetStreamingState( DeviceStreamState_Run ); + } + break; + case MFT_MESSAGE_NOTIFY_END_STREAMING: + { + SetStreamingState(DeviceStreamState_Stop); + } + break; + case MFT_MESSAGE_NOTIFY_END_OF_STREAM: + { + SetStreamingState(DeviceStreamState_Stop); + } + break; + default: + ; + } + + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); + return hr; +} + +STDMETHODIMP CMultipinMft::ProcessInput( + _In_ DWORD dwInputStreamID, + _In_ IMFSample* pSample, + _In_ DWORD dwFlags + ) +/*++ + Description: + + Implements IMFTransform::ProcessInput function.This function is called + when the sourcetransform has input to feed. the pins will try to deliver the + samples to the active output pins conencted. if none are connected then just + returns the sample back to the source transform + +--*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER( dwFlags ); + + ComPtr spInPin = GetInPin( dwInputStreamID ); + DMFTCHECKNULL_GOTO(spInPin, done, MF_E_INVALIDSTREAMNUMBER); + + if ( !IsStreaming() ) + { + goto done; + } + + DMFTCHECKHR_GOTO(spInPin->SendSample( pSample ), done ); +done: + DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr ); + // + //@@@@ README : There is a bug in the sample that the device transform manager which manages the + // device MFT does not release the sample after passing it to Device MFT in processInput like it should. The + // Device MFT therefore unfortunately has to make sure that the sample that leaves processoutput has a reference count of 1 + // + SAFE_RELEASE(pSample); + return hr; + +} + +STDMETHODIMP CMultipinMft::ProcessOutput( + _In_ DWORD dwFlags, + _In_ DWORD cOutputBufferCount, + _Inout_updates_(cOutputBufferCount) MFT_OUTPUT_DATA_BUFFER *pOutputSamples, + _Out_ DWORD *pdwStatus +) +/*++ +Description: + +Implements IMFTransform::ProcessOutput function. This is called by the DTM when +the DT indicates it has samples to give. The DTM will send enough MFT_OUTPUT_DATA_BUFFER +pointers to be filled up as is the number of output pins available. The DT should traverse its +output pins and populate the corresponding MFT_OUTPUT_DATA_BUFFER with the samples available + +--*/ +{ + HRESULT hr = S_OK; + BOOL gotOne = false; + ComPtr spOpin; + UNREFERENCED_PARAMETER( dwFlags ); + + if (cOutputBufferCount > m_OutputPinCount ) + { + DMFTCHECKHR_GOTO( E_INVALIDARG, done ); + } + *pdwStatus = 0; + + for ( DWORD i = 0; i < cOutputBufferCount; i++ ) + { + DWORD dwStreamID = pOutputSamples[i].dwStreamID; + { + CAutoLock _lock(m_critSec); + spOpin = nullptr; + spOpin = GetOutPin(dwStreamID); + GUID pinGuid = GUID_NULL; + DMFTCHECKNULL_GOTO(spOpin.Get(), done, E_INVALIDARG); + } + if ( SUCCEEDED(spOpin->ProcessOutput( dwFlags, &pOutputSamples[i], + pdwStatus ) ) ) + { + gotOne = true; + } + } + if (gotOne) + { + hr = S_OK; + } + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::GetInputStreamAttributes( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFAttributes** ppAttributes + ) +/*++ + Description: + + Implements IMFTransform::GetInputStreamAttributes function. This function + gets the specified input stream's attributes. + +--*/ +{ + HRESULT hr = S_OK; + ComPtr spIPin; + + DMFTCHECKNULL_GOTO( ppAttributes, done, E_INVALIDARG ); + *ppAttributes = nullptr; + + spIPin = GetInPin( dwInputStreamID ); + + DMFTCHECKNULL_GOTO(spIPin, done, E_INVALIDARG ); + + hr = spIPin->getPinAttributes(ppAttributes); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::GetOutputStreamAttributes( + _In_ DWORD dwOutputStreamID, + _Out_ IMFAttributes** ppAttributes + ) +/*++ + Description: + + Implements IMFTransform::GetOutputStreamAttributes function. This function + gets the specified output stream's attributes. + +--*/ +{ + HRESULT hr = S_OK; + ComPtr spoPin; + + DMFTCHECKNULL_GOTO(ppAttributes, done, E_INVALIDARG); + + *ppAttributes = nullptr; + + spoPin = GetOutPin(dwOutputStreamID); + + DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG ); + + DMFTCHECKHR_GOTO(spoPin->getPinAttributes(ppAttributes), done ); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +_Requires_no_locks_held_ +STDMETHODIMP CMultipinMft::SetInputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::SetInputStreamState function. + Sets the input stream state. + + The control lock is not taken here. The lock is taken for operations on + output pins. This operation is a result of the DT notifying the DTM that + output pin change has resulted in the need for the input to be changed. In + this case the DTM sends a getpreferredinputstate and then this call + + --*/ +{ + HRESULT hr = S_OK; + CAutoLock Lock(m_critSec); + ComPtr spiPin = GetInPin(dwStreamID); + DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER); + + DMFTCHECKHR_GOTO(spiPin->SetInputStreamState(pMediaType, value, dwFlags),done); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::GetInputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *value + ) +{ + HRESULT hr = S_OK; + ComPtr piPin = GetInPin(dwStreamID); + + DMFTCHECKNULL_GOTO(piPin, done, MF_E_INVALIDSTREAMNUMBER); + + *value = piPin->GetState(); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + + +STDMETHODIMP CMultipinMft::SetOutputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState state, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::SetOutputStreamState function. + Sets the output stream state. This is called whenever the stream + is selected or deslected i.e. started or stopped. + + The control lock taken here and this operation should be atomic. + This function should check the input pins connected to the output pin + switch off the state of the input pin. Check if any other Pin connected + to the input pin is in a conflicting state with the state requested on this + output pin. Accordinly it calculates the media type to be set on the input pin + and the state to transition into. It then might recreate the other output pins + connected to it + --*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwFlags); + CAutoLock Lock(m_critSec); + + DMFTCHECKHR_GOTO(ChangeMediaTypeEx(dwStreamID, pMediaType, state),done); + +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::GetOutputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *pState + ) + /*++ + Description: + + Implements IMFdeviceTransform::GetOutputStreamState function. + Gets the output stream state. + Called by the DTM to checks states. Atomic operation. needs a lock + --*/ +{ + HRESULT hr = S_OK; + CAutoLock lock(m_critSec); + + ComPtr spoPin = GetOutPin(dwStreamID); + DMFTCHECKNULL_GOTO(pState, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(spoPin, done, MF_E_INVALIDSTREAMNUMBER); + *pState = spoPin->GetState(); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::GetInputStreamPreferredState( + _In_ DWORD dwStreamID, + _Inout_ DeviceStreamState *value, + _Outptr_opt_result_maybenull_ IMFMediaType **ppMediaType + ) + /*++ + Description: + + Implements IMFdeviceTransform::GetInputStreamPreferredState function. + Gets the preferred state and the media type to be set on the input pin. + The lock is not held as this will always be called only when we notify + DTM to call us. We notify DTM only from the context on operations + happening on the output pin + --*/ +{ + HRESULT hr = S_OK; + ComPtr spiPin = GetInPin(dwStreamID); + DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(spiPin, done, MF_E_INVALIDSTREAMNUMBER); + hr = spiPin->GetInputStreamPreferredState(value, ppMediaType); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::FlushInputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::FlushInputStream function. + --*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwStreamIndex); + UNREFERENCED_PARAMETER(dwFlags); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + +STDMETHODIMP CMultipinMft::FlushOutputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags + ) + /*++ + Description: + + Implements IMFdeviceTransform::FlushOutputStream function. + Called by the DTM to flush streams + --*/ +{ + + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(dwFlags); + CAutoLock Lock(m_critSec); + + ComPtr spoPin = GetOutPin(dwStreamIndex); + DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG); + DeviceStreamState oldState = spoPin->SetState(DeviceStreamState_Disabled); + DMFTCHECKHR_GOTO(spoPin->FlushQueues(),done); + spoPin->SetState(oldState); +done: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + + +/*++ + Description: + + Called when the Device Transform gets a MFT_MESSAGE_COMMAND_FLUSH. We drain all the queues. + This is called in device source when the source gets end of streaming. + --*/ +STDMETHODIMP_(VOID) CMultipinMft::FlushAllStreams( + VOID + ) +{ + DeviceStreamState oldState; + CAutoLock Lock(m_critSec); + for ( DWORD dwIndex = 0, dwSize = (DWORD)m_OutPins.size(); dwIndex < dwSize; dwIndex++ ) + { + ComPtr spoPin = (COutPin *)m_OutPins[dwIndex]; + oldState = spoPin->SetState(DeviceStreamState_Disabled); + spoPin->FlushQueues(); + // + //Restore state + // + spoPin->SetState(oldState); + } +} + + +// +// IKsControl interface functions +// +STDMETHODIMP CMultipinMft::KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pvPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pulBytesReturned + ) + /*++ + Description: + + Implements IKSProperty::KsProperty function. + used to pass control commands to the driver (generally) + This can be used to intercepted the control to figure out + if it needs to be propogated to the driver or not + --*/ +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(pulBytesReturned); + DMFTCHECKNULL_GOTO(pProperty, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(pulBytesReturned, done, E_INVALIDARG); + + if (IsEqualCLSID(pProperty->Set, KSPROPERTYSETID_ExtendedCameraControl)) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Extended Control %d Passed ",pProperty->Id); + } + else if ((IsEqualCLSID(pProperty->Set, PROPSETID_VIDCAP_VIDEOCONTROL)) && (pProperty->Id == KSPROPERTY_VIDEOCONTROL_MODE)) + { + // A function illustrating how we can capture and service photos from the device MFT. This block shows how we can + // intercept Photo triggers going down to the pipeline + + if (sizeof(KSPROPERTY_VIDEOCONTROL_MODE_S) == ulDataLength) + { + PKSPROPERTY_VIDEOCONTROL_MODE_S VideoControl = (PKSPROPERTY_VIDEOCONTROL_MODE_S)pvPropertyData; + m_PhotoModeIsPhotoSequence = false; + if (VideoControl->Mode == KS_VideoControlFlag_StartPhotoSequenceCapture) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Starting PhotoSequence Trigger"); + m_PhotoModeIsPhotoSequence = true; + } + else if (VideoControl->Mode == KS_VideoControlFlag_StopPhotoSequenceCapture) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Stopping PhotoSequence Trigger"); + m_PhotoModeIsPhotoSequence = false; + } + else + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Take Single Photo Trigger"); + } + } + } + DMFTCHECKHR_GOTO(m_spIkscontrol->KsProperty(pProperty, + ulPropertyLength, + pvPropertyData, + ulDataLength, + pulBytesReturned),done); +done: + LPSTR guidStr = DumpGUIDA(pProperty->Set); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! g:%s p:%d exiting %x = %!HRESULT!", guidStr, pProperty->Id, hr, hr); + delete(guidStr); + return hr; +} + +STDMETHODIMP CMultipinMft::KsMethod( + _In_reads_bytes_(ulPropertyLength) PKSMETHOD pMethod, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pvPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pulBytesReturned + ) + /*++ + Description: + + Implements IKSProperty::KsMethod function. We can trap ksmethod calls here. + --*/ +{ + return m_spIkscontrol->KsMethod( + pMethod, + ulPropertyLength, + pvPropertyData, + ulDataLength, + pulBytesReturned + ); +} + +STDMETHODIMP CMultipinMft::KsEvent( + _In_reads_bytes_(ulEventLength) PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_updates_bytes_opt_(ulDataLength) LPVOID pEventData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ) + /*++ + Description: + + Implements IKSProperty::KsEvent function. + --*/ +{ + + HRESULT hr = S_OK; + { + + // + // All the Events we don't handle should be sent to the driver! + // + hr = m_spIkscontrol->KsEvent(pEvent, + ulEventLength, + pEventData, + ulDataLength, + pBytesReturned); + } + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} + + +#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES) + +// +// IMFTransform function(s). +// + +// +// Note: This is the only IMFTransform function which is not a redirector to the +// DeviceTransform functions. The rest of IMFTransform functions are in the file common.h +// This function returns the IMFAttribute created for Device MFT. If DMFT is +// not loaded (usually )MFT0's call to GetAttributes will get the Attribute store of DevProxy. +// A device MFT loaded will not pass through the devproxy attribute store, but it will pass +// the device MFT attributes. This should be similar to the singular DevProxy attribute +// which the MFT0 providers can use to synchronize across various MFT0's +// + +STDMETHODIMP CMultipinMft::GetAttributes( + _COM_Outptr_opt_result_maybenull_ IMFAttributes** ppAttributes + ) +{ + HRESULT hr = S_OK; + CAutoLock Lock(m_critSec); + DMFTCHECKNULL_GOTO(ppAttributes, done, E_INVALIDARG); + + *ppAttributes = nullptr; + + if (m_spAttributes != nullptr) + { + m_spAttributes.CopyTo(ppAttributes); + } + else + { + hr = E_OUTOFMEMORY; + } + +done: + return hr; +} +#endif + +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) +// +// IMFSampleAllocatorControl Inferface function declarations +// + +STDMETHODIMP CMultipinMft::SetDefaultAllocator( + _In_ DWORD dwOutputStreamID, + _In_ IUnknown *pAllocator +) +{ + CAutoLock Lock(m_critSec); + + // SetAllocator will be called on the streamId that returns MFSampleAllocatorMode_Default + wil::com_ptr_nothrow outPin = GetOutPin(dwOutputStreamID); + RETURN_HR_IF_NULL(E_INVALIDARG, outPin); + RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator); + + wil::com_ptr_nothrow defaultAllocator; + RETURN_IF_FAILED(pAllocator->QueryInterface(&defaultAllocator)); + outPin->SetAllocator(defaultAllocator.get()); + + return S_OK; +} + +STDMETHODIMP CMultipinMft::GetAllocatorUsage( + _In_ DWORD dwOutputStreamID, + _Out_ DWORD* pdwInputStreamID, + _Out_ MFSampleAllocatorUsage* peUsage +) +{ + CAutoLock Lock(m_critSec); + + RETURN_HR_IF_NULL(E_INVALIDARG, peUsage); + + wil::com_ptr_nothrow outPin = GetOutPin(dwOutputStreamID); + RETURN_HR_IF_NULL(MF_E_INVALIDSTREAMNUMBER, outPin); + *peUsage = outPin->GetSampleAllocatorUsage(); + + if (*peUsage == MFSampleAllocatorUsage_DoesNotAllocate) + { + RETURN_HR_IF_NULL(E_INVALIDARG, pdwInputStreamID); + RETURN_IF_FAILED(GetConnectedInpin((ULONG)dwOutputStreamID, *(ULONG*)pdwInputStreamID)); + } + + return S_OK; +} +#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + +// +// HELPER FUNCTIONS +// + +// +// A lock here could mean a deadlock because this will be called when the lock is already held +// in another thread. +// +CInPin* CMultipinMft::GetInPin( + _In_ DWORD dwStreamId +) +{ + CInPin *inPin = NULL; + for (DWORD dwIndex = 0, dwSize = (DWORD)m_InPins.size(); dwIndex < dwSize; dwIndex++) + { + inPin = (CInPin *)m_InPins[dwIndex]; + if (dwStreamId == inPin->streamId()) + { + break; + } + inPin = NULL; + } + return inPin; +} + +COutPin* CMultipinMft::GetOutPin( + _In_ DWORD dwStreamId + ) +{ + COutPin *outPin = NULL; + for ( DWORD dwIndex = 0, dwSize = (DWORD) m_OutPins.size(); dwIndex < dwSize; dwIndex++ ) + { + outPin = ( COutPin * )m_OutPins[ dwIndex ]; + + if ( dwStreamId == outPin->streamId() ) + { + break; + } + + outPin = NULL; + } + + return outPin; +} +_Requires_lock_held_(m_Critsec) +HRESULT CMultipinMft::GetConnectedInpin(_In_ ULONG ulOutpin, _Out_ ULONG &ulInPin) +{ + HRESULT hr = S_OK; + map::iterator it = m_outputPinMap.find(ulOutpin); + if (it != m_outputPinMap.end()) + { + ulInPin = it->second; + } + else + { + hr = MF_E_INVALIDSTREAMNUMBER; + } + return hr; +} + +// +// The Below function changes media type on the pins exposed by device MFT +// +__requires_lock_held(m_critSec) +HRESULT CMultipinMft::ChangeMediaTypeEx( + _In_ ULONG pinId, + _In_opt_ IMFMediaType *pMediaType, + _In_ DeviceStreamState reqState +) +{ + HRESULT hr = S_OK; + ComPtr spoPin = GetOutPin(pinId); + ComPtr spinPin; + DeviceStreamState oldOutPinState, oldInputStreamState, newOutStreamState, newRequestedInPinState; + ComPtr pFullType, pInputMediaType; + ULONG ulInPinId = 0; + DWORD dwFlags = 0; + + + DMFTCHECKNULL_GOTO(spoPin, done, E_INVALIDARG); + { + // + // dump the media types to the logs + // + ComPtr spOldMediaType; + (VOID)spoPin->getMediaType(spOldMediaType.GetAddressOf()); + CMediaTypePrinter newType(pMediaType); + CMediaTypePrinter oldType(spOldMediaType.Get()); + if (WPP_LEVEL_ENABLED(DMFT_GENERAL)) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, " Pin:%d old MT:[%s] St:%d", pinId, oldType.ToString(), reqState); + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, " Pin:%d new MT:[%s] St:%d", pinId, newType.ToString(), reqState); + } + } + + if (pMediaType) + { + if (!spoPin->IsMediaTypeSupported(pMediaType, &pFullType)) + { + DMFTCHECKHR_GOTO(MF_E_INVALIDMEDIATYPE, done); + } + } + + DMFTCHECKHR_GOTO(GetConnectedInpin(pinId, ulInPinId), done); + spinPin = GetInPin(ulInPinId); // Get the input pin + + (VOID)spinPin->getMediaType(&pInputMediaType); + oldInputStreamState = spinPin->SetState(DeviceStreamState_Disabled); // Disable input pin + oldOutPinState = spoPin->SetState(DeviceStreamState_Disabled); // Disable output pin + (void)spoPin->FlushQueues(); // Flush the output queues + (void)spinPin->FlushQueues(); // Flush the input queues + newOutStreamState = pinStateTransition[oldOutPinState][reqState]; // New state needed + + // The Old input and the output pin states should be the same + newRequestedInPinState = newOutStreamState; + + if ((newOutStreamState != oldOutPinState) /*State change*/ + ||((pFullType.Get() != nullptr) && (pInputMediaType.Get()!=nullptr) && (S_OK != (pFullType->IsEqual(pInputMediaType.Get(), &dwFlags)))) /*Media Types dont match*/ + ||((pFullType == nullptr)||(pInputMediaType == nullptr))/*Either one of the mediatypes is null*/ + ) + { + // + // State has change or media type has changed so we need to change the media type on the + // underlying kernel pin + // + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "Changing Mediatype on the input "); + spinPin->setPreferredMediaType(pFullType.Get()); + spinPin->setPreferredStreamState(newRequestedInPinState); + // Let the pipline know that the input needs to be changed. + SendEventToManager(METransformInputStreamStateChanged, GUID_NULL, spinPin->streamId()); + // + // The media type will be set on the input pin by the time we return from the wait + // + m_critSec.Unlock(); + hr = spinPin->WaitForSetInputPinMediaChange(); + m_critSec.Lock(); + // Change the media type on the output.. + DMFTCHECKHR_GOTO(spoPin->ChangeMediaTypeFromInpin(pFullType.Get(), pMediaType , reqState), done); + // + // Notify the pipeline that the output stream media type has changed + // + DMFTCHECKHR_GOTO(SendEventToManager(MEUnknown, MEDeviceStreamCreated, spoPin->streamId()), done); + spoPin->SetFirstSample(TRUE); + } + else + { + // Restore back old states as we have nothing to do + spinPin->SetState(oldInputStreamState); + spoPin->SetState(oldOutPinState); + } + + +done: + return hr; +} + +// +// The below function sends events to the pipeline. +// + +HRESULT CMultipinMft::SendEventToManager( + _In_ MediaEventType eventType, + _In_ REFGUID pGuid, + _In_ UINT32 context + ) + /*++ + Description: + Used to send the event to DTM. + --*/ + { + HRESULT hr = S_OK; + ComPtr pEvent = nullptr; + + DMFTCHECKHR_GOTO(MFCreateMediaEvent(eventType, pGuid, S_OK, NULL, &pEvent ),done); + DMFTCHECKHR_GOTO(pEvent->SetUINT32(MF_EVENT_MFT_INPUT_STREAM_ID, (ULONG)context),done); + DMFTCHECKHR_GOTO(QueueEvent(pEvent.Get()),done); + done: + + return hr; + } +/*++ +Description: +This function connects the input and output pins. +Any media type filtering can happen here +--*/ +HRESULT CMultipinMft::BridgeInputPinOutputPin( + _In_ CInPin* piPin, + _In_ COutPin* poPin + ) +{ + HRESULT hr = S_OK; + ULONG ulIndex = 0; + ULONG ulAddedMediaTypeCount = 0; + ComPtr spMediaType; + + DMFTCHECKNULL_GOTO( piPin, done, E_INVALIDARG ); + DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG ); + // + // Copy over the media types from input pin to output pin. Since there is no + // decoder support, only the uncompressed media types are inserted. Please make + // sure any pin advertised supports at least one media type. The pipeline doesn't + // like pins with no media types + // + while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, spMediaType.ReleaseAndGetAddressOf() ))) + { + GUID subType = GUID_NULL; + DMFTCHECKHR_GOTO( spMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done ); + { + DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, spMediaType.Get() ), done ); + if (hr == S_OK) + { + ulAddedMediaTypeCount++; + } + } + } + if (ulAddedMediaTypeCount == 0) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Make Sure Pin %d has one media type exposed ", piPin->streamId()); + DMFTCHECKHR_GOTO( MF_E_INVALID_STREAM_DATA, done ); + } + // + //Add the Input Pin to the output Pin + // + DMFTCHECKHR_GOTO(poPin->AddPin(piPin->streamId()), done); + hr = ExceptionBoundary([&](){ + // + // Add the output pin to the input pin. + // Create the pin map. So that we know which pin input pin is connected to which output pin + // + piPin->ConnectPin(poPin); + m_outputPinMap.insert(std::pair< int, int >(poPin->streamId(), piPin->streamId())); + }); + + + +done: + // + //Failed adding media types + // + if (FAILED(hr)) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + } + return hr; +} + +// +// IMFShutdown interface functions +// + +/*++ +Description: +Implements the Shutdown from IMFShutdown +--*/ +STDMETHODIMP CMultipinMft::Shutdown( + void + ) +{ + CAutoLock Lock(m_critSec); + (VOID) m_eventHandler.Clear(); + + for (ULONG ulIndex = 0, ulSize = (ULONG)m_InPins.size(); ulIndex < ulSize; ulIndex++ ) + { + CInPin *pInPin = static_cast(m_InPins[ulIndex]); + + // Deref on the connected outpins to break reference loop + (VOID)pInPin->ShutdownPin(); + } +#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES) + for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++) + { + (VOID) m_OutPins[ulIndex]->DeleteItem(MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT); + } +#endif + return ShutdownEventGenerator(); +} + +// +// Static method to create an instance of the MFT. +// +HRESULT CMultipinMft::CreateInstance(REFIID iid, void **ppMFT) +{ + HRESULT hr = S_OK; + CMultipinMft *pMFT = NULL; + DMFTCHECKNULL_GOTO(ppMFT, done, E_POINTER); + pMFT = new (std::nothrow) CMultipinMft(); + DMFTCHECKNULL_GOTO(pMFT, done, E_OUTOFMEMORY); + + DMFTCHECKHR_GOTO(pMFT->QueryInterface(iid, ppMFT), done); + +done: + if (FAILED(hr)) + { + SAFERELEASE(pMFT); + } + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr); + return hr; +} diff --git a/avstream/sampledevicemft/SampleSocDeviceMFT.h b/avstream/sampledevicemft/SampleSocDeviceMFT.h new file mode 100644 index 000000000..91635fb18 --- /dev/null +++ b/avstream/sampledevicemft/SampleSocDeviceMFT.h @@ -0,0 +1,374 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// + +#pragma once +#include "common.h" +#include "mftpeventgenerator.h" +#include "basepin.h" +#include "custompin.h" +#include "multipinmfthelpers.h" + +// +// The Below GUID is needed to transfer photoconfirmation sample successfully in the pipeline +// It is used to propagate the mediatype of the sample to the pipeline which will consume the sample +// This attribute is known to the OS, but not publicly defined. +// + +DEFINE_GUID(MFSourceReader_SampleAttribute_MediaType_priv, + 0x0ea5c1e8, 0x9845, 0x41e0, 0xa2, 0x43, 0x72, 0x32, 0x07, 0xfc, 0x78, 0x1f); + + +interface IDirect3DDeviceManager9; + +// +// Forward declarations +// +class CMFAttributes; +class CPinCreationFactory; +// +// CMultipinMft class: +// Implements a device proxy MFT. +// +class CMultipinMft : + public IMFDeviceTransform +#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES) + , public IMFTransform +#endif + , public IMFShutdown + , public CMediaEventGenerator + , public IMFRealTimeClientEx + , public IKsControl + , public CDMFTModuleLifeTimeManager +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + , public IMFSampleAllocatorControl +#endif +{ + friend class CPinCreationFactory; +public: + CMultipinMft( + void ); + + virtual ~CMultipinMft(); + + // + // IUnknown + // + STDMETHOD_(ULONG, AddRef)( + void ); + + STDMETHOD_(ULONG, Release)( + void ); + + STDMETHOD(QueryInterface)( + _In_ REFIID iid, + _COM_Outptr_ void** ppv); + + + // + // IMFDeviceTransform functions + // + STDMETHOD(GetStreamCount)( + _Inout_ DWORD *pdwInputStreams, + _Inout_ DWORD *pdwOutputStreams); + + + STDMETHOD(GetStreamIDs)( + _In_ DWORD dwInputIDArraySize, + _When_(dwInputIDArraySize >= m_InputPinCount, _Out_writes_(dwInputIDArraySize)) DWORD* pdwInputIDs, + _In_ DWORD dwOutputIDArraySize, + _When_(dwOutputIDArraySize >= m_OutputPinCount && (pdwInputIDs && (dwInputIDArraySize > 0)), + _Out_writes_(dwOutputIDArraySize)) _On_failure_(_Valid_) DWORD* pdwOutputIDs + ); + + STDMETHOD(GetInputStreamAttributes)( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFAttributes** ppAttributes); + + STDMETHOD(GetOutputStreamAttributes)( + _In_ DWORD dwOutputStreamID, + _Out_ IMFAttributes** ppAttributes); + + STDMETHOD(GetInputAvailableType)( + _In_ DWORD dwInputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppType); + + STDMETHOD(GetOutputAvailableType)( + _In_ DWORD dwOutputStreamID, + _In_ DWORD dwTypeIndex, + _Out_ IMFMediaType** ppMediaType); + + STDMETHOD(GetInputCurrentType)( + _In_ DWORD dwInputStreamID, + _COM_Outptr_result_maybenull_ IMFMediaType** ppMediaType); + + STDMETHOD(GetOutputCurrentType)( + _In_ DWORD dwOutputStreamID, + _Out_ IMFMediaType** ppMediaType); + + STDMETHOD(ProcessMessage)( + _In_ MFT_MESSAGE_TYPE eMessage, + _In_ ULONG_PTR ulParam ); + + STDMETHOD(ProcessEvent)( + _In_ DWORD dwInputStreamID, + _In_ IMFMediaEvent *pEvent); + + + STDMETHOD(ProcessInput)( + _In_ DWORD dwInputStreamID, + _In_ IMFSample* pSample, + _In_ DWORD dwFlags ); + + STDMETHOD(ProcessOutput)( + _In_ DWORD dwFlags, + _In_ DWORD cOutputBufferCount, + _Inout_updates_(cOutputBufferCount) MFT_OUTPUT_DATA_BUFFER *pOutputSamples, + _Out_ DWORD *pdwStatus ); + + // + // IMFRealTimeClientEx + // + STDMETHOD(RegisterThreadsEx)( + _Inout_ DWORD* pdwTaskIndex, + _In_ LPCWSTR wszClassName, + _In_ LONG lBasePriority ) + { + UNREFERENCED_PARAMETER(pdwTaskIndex); + UNREFERENCED_PARAMETER(wszClassName); + UNREFERENCED_PARAMETER(lBasePriority); + return S_OK; + } + + STDMETHOD(UnregisterThreads)() + { + return S_OK; + } + + STDMETHOD(SetWorkQueueEx)( + _In_ DWORD dwWorkQueueId, + _In_ LONG lWorkItemBasePriority ); + + // + // IMFShutdown + // + STDMETHOD(Shutdown)( + void ); + + STDMETHOD(GetShutdownStatus)( + MFSHUTDOWN_STATUS *pStatus) + { + UNREFERENCED_PARAMETER(pStatus); + return(m_eShutdownStatus); + }; + + // + // IMFDeviceTransform function declarations + // + STDMETHODIMP InitializeTransform( + _In_ IMFAttributes *pAttributes ); + + _Requires_no_locks_held_ + STDMETHODIMP SetInputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags ); + + STDMETHODIMP GetInputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *value ); + + STDMETHODIMP SetOutputStreamState( + _In_ DWORD dwStreamID, + _In_ IMFMediaType *pMediaType, + _In_ DeviceStreamState value, + _In_ DWORD dwFlags ); + + STDMETHODIMP GetOutputStreamState( + _In_ DWORD dwStreamID, + _Out_ DeviceStreamState *value ); + + STDMETHODIMP GetInputStreamPreferredState( + _In_ DWORD dwStreamID, + _Inout_ DeviceStreamState *value, + _Outptr_opt_result_maybenull_ IMFMediaType **ppMediaType ); + + STDMETHODIMP FlushInputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags ); + + STDMETHODIMP FlushOutputStream( + _In_ DWORD dwStreamIndex, + _In_ DWORD dwFlags ); + + STDMETHODIMP_(VOID) FlushAllStreams( + VOID + ); + + // + //IKSControl Inferface function declarations + // + STDMETHOD(KsEvent)( + _In_reads_bytes_(ulEventLength) PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_updates_bytes_opt_(ulDataLength) LPVOID pEventData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ); + STDMETHOD(KsProperty)( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ); + STDMETHOD(KsMethod)( + _In_reads_bytes_(ulPropertyLength) PKSMETHOD pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_bytes_(ulDataLength) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Inout_ ULONG* pBytesReturned + ); + +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + // + // IMFSampleAllocatorControl Inferface function declarations + // + + STDMETHOD(SetDefaultAllocator)( + _In_ DWORD dwOutputStreamID, + _In_ IUnknown *pAllocator + ); + + STDMETHOD(GetAllocatorUsage)( + _In_ DWORD dwOutputStreamID, + _Out_ DWORD* pdwInputStreamID, + _Out_ MFSampleAllocatorUsage* peUsage + ); +#endif + static STDMETHODIMP CreateInstance( + REFIID iid, void **ppMFT); + + __inline BOOL isPhotoModePhotoSequence() + { + return m_PhotoModeIsPhotoSequence; + } + + _inline DWORD GetQueueId() + { + return m_dwWorkQueueId; + } + + // + //Will be used from Pins to get the D3D manager once set!!! + // + __inline STDMETHODIMP_(VOID) GetD3DDeviceManager( + IUnknown** ppDeviceManagerUnk + ) + { + m_spDeviceManagerUnk.CopyTo( ppDeviceManagerUnk ); + } + + HRESULT SendEventToManager( + _In_ MediaEventType, + _In_ REFGUID, + _In_ UINT32 + ); + +protected: + + // + //Helper functions + // + + CInPin* GetInPin( + _In_ DWORD dwStreamID + ); + + COutPin* GetOutPin( + _In_ DWORD dwStreamID + ); + + HRESULT GetConnectedInpin(_In_ ULONG ulOutpin, _Out_ ULONG &ulInPin); + + __requires_lock_held(m_critSec) + HRESULT ChangeMediaTypeEx( + _In_ ULONG pinId, + _In_opt_ IMFMediaType *pMediaType, + _In_ DeviceStreamState newState + ); + HRESULT BridgeInputPinOutputPin( + _In_ CInPin* pInPin, + _In_ COutPin* pOutPin); +#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES) + STDMETHODIMP CMultipinMft::GetAttributes( + _COM_Outptr_opt_result_maybenull_ IMFAttributes** ppAttributes + ); +#endif + +#if (defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)) + _DEFINE_DEVICEMFT_MFT0HELPER_IMPL__ +#endif + + + + // + //Inline functions + // + + __inline IMFTransform* Parent() + { + return m_spSourceTransform.Get(); + } + + __inline VOID SetStreamingState(DeviceStreamState state) + { + InterlockedExchange((LONG*)&m_StreamingState, state); + } + __inline DeviceStreamState GetStreamingState() + { + return (DeviceStreamState)InterlockedCompareExchange((LONG*)&m_StreamingState, 0L, 0L); + } + __inline BOOL IsStreaming() + { + return (InterlockedCompareExchange((LONG*)&m_StreamingState, DeviceStreamState_Run, DeviceStreamState_Run) == DeviceStreamState_Run); + } + +private: + ULONG m_InputPinCount; + ULONG m_OutputPinCount; + ULONG m_CustomPinCount; + DeviceStreamState m_StreamingState; + CBasePinArray m_OutPins; + CBasePinArray m_InPins; + BOOL m_PhotoModeIsPhotoSequence; // used to store if the filter is in photo sequence or not + long m_nRefCount; // Reference count + CCritSec m_critSec; // Control lock.. taken only durign state change operations + ComPtr m_spDeviceManagerUnk; // D3D Manager set, when MFT_MESSAGE_SET_D3D_MANAGER is called through ProcessMessage + ComPtr m_spSourceTransform; // The sources transform. This is the pipeline DevProxy + MFSHUTDOWN_STATUS m_eShutdownStatus; + DWORD m_dwWorkQueueId; + LONG m_lWorkQueuePriority; + UINT32 m_punValue; + ComPtr m_spIkscontrol; + ComPtr m_spAttributes; + map m_outputPinMap; // How output pins are connected to input pins i-><0..outpins> + CDMFTEventHandler m_eventHandler; + PWCHAR m_SymbolicLink; + +}; + + + +inline HRESULT MFT_CreateInstance(REFIID riid, void **ppv) +{ + return CMultipinMft::CreateInstance(riid, ppv); +} + + diff --git a/avstream/sampledevicemft/SampleSocDeviceMFTutils.cpp b/avstream/sampledevicemft/SampleSocDeviceMFTutils.cpp new file mode 100644 index 000000000..1b41496b2 --- /dev/null +++ b/avstream/sampledevicemft/SampleSocDeviceMFTutils.cpp @@ -0,0 +1,1320 @@ +//*@@@+++@@@@****************************************************************** +// +// Microsoft Windows Media Foundation +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//*@@@---@@@@****************************************************************** +// + +#include "stdafx.h" +#include "common.h" +#include "multipinmft.h" +#include "basepin.h" + +#pragma comment(lib, "d2d1") +#ifdef MF_WPP +#include "multipinmftutils.tmh" //--REF_ANALYZER_DONT_REMOVE-- +#endif + +// Critical sections + +CCritSec::CCritSec() +{ + InitializeCriticalSection(&m_criticalSection); +} + +CCritSec::~CCritSec() +{ + DeleteCriticalSection(&m_criticalSection); +} + +_Requires_lock_not_held_(m_criticalSection) _Acquires_lock_(m_criticalSection) +void CCritSec::Lock() +{ + EnterCriticalSection(&m_criticalSection); +} + +_Requires_lock_held_(m_criticalSection) _Releases_lock_(m_criticalSection) +void CCritSec::Unlock() +{ + LeaveCriticalSection(&m_criticalSection); +} + + +_Acquires_lock_(this->m_pCriticalSection->m_criticalSection) +CAutoLock::CAutoLock(CCritSec& crit) +{ + m_pCriticalSection = &crit; + m_pCriticalSection->Lock(); +} +_Acquires_lock_(this->m_pCriticalSection->m_criticalSection) +CAutoLock::CAutoLock(CCritSec* crit) +{ + m_pCriticalSection = crit; + m_pCriticalSection->Lock(); +} +_Releases_lock_(this->m_pCriticalSection->m_criticalSection) +CAutoLock::~CAutoLock() +{ + m_pCriticalSection->Unlock(); +} + +// +//Some utility functions.. +// + +/*++ + Description: + Used to check if the input and the output Image types are optinmized or not +--*/ + +STDMETHODIMP IsOptimizedPlanarVideoInputImageOutputPair( + _In_ IMFMediaType *inMediaType, + _In_ IMFMediaType *outMediaType, + _Out_ bool *optimized, + _Out_ bool *optimizedxvpneeded ) +{ + HRESULT hr = S_OK; + GUID guidInputSubType = GUID_NULL; + GUID guidOutputSubType = GUID_NULL; + UINT32 uWidthIn = 0, uHeightIn = 0, uWidthOut = 0, uHeightOut = 0; + + + DMFTCHECKHR_GOTO(inMediaType->GetGUID(MF_MT_SUBTYPE, &guidInputSubType), done); + + DMFTCHECKHR_GOTO(outMediaType->GetGUID(MF_MT_SUBTYPE, &guidOutputSubType), done); + + *optimized = false; //Assume we aren't optimized . Optimized = (ip = YU12|NV12 and op = JPEG) + *optimizedxvpneeded = true; //Assume we need xvps + + if (IsEqualGUID(guidInputSubType, MFVideoFormat_YV12) || IsEqualGUID(guidInputSubType, MFVideoFormat_NV12)) + { + if (IsEqualGUID(guidOutputSubType, GUID_ContainerFormatJpeg)) + { + *optimized = true; + } + } + + if (!*optimized) + { + goto done; + } + + DMFTCHECKHR_GOTO(MFGetAttributeSize(inMediaType, MF_MT_FRAME_SIZE, &uWidthIn, &uHeightIn), done); + DMFTCHECKHR_GOTO(MFGetAttributeSize(outMediaType, MF_MT_FRAME_SIZE, &uWidthOut, &uHeightOut), done); + + if ((uWidthIn == uWidthOut) && (uHeightIn == uHeightOut)) + { + *optimizedxvpneeded = false; + } + if (!*optimizedxvpneeded) + { + UINT32 nominalRange; + hr = inMediaType->GetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, &nominalRange); + + if (FAILED(hr) || nominalRange != MFNominalRange_0_255) + { + //XVP needed since nominal range is not 0-255 for YV12 or NV12 fed into WIC + *optimizedxvpneeded = true; + } + hr = S_OK; + } + +done: + return hr; +} + + +/* +Description: + + This is used whenever there is a media type change on an output pin and the + Output queue is being reconfigured. + The possible return values for the function are as follows + + DeviceMftTransformXVPIllegal -> If either of the mediatypes or both are NULL + DeviceMftTransformXVPDisruptiveIn -> If the mediatype at the output pin is greater than the input pin. This will result in change of the media type on the input + DeviceMftTransformXVPDisruptiveOut -> This is a reconfiguration or addition of the XVP in the Output pin queue + DeviceMftTransformXVPCurrent -> No XVP needed at all +*/ +STDMETHODIMP CompareMediaTypesForConverter( + _In_opt_ IMFMediaType *inMediaType, + _In_ IMFMediaType *newMediaType, + _Inout_ PDMFT_conversion_type operation + ) +{ + HRESULT hr = S_OK; + GUID guidTypeA = GUID_NULL; + GUID guidTypeB = GUID_NULL; + + *operation = DeviceMftTransformTypeIllegal; + if ((!inMediaType) || (!newMediaType)) + { + goto done; + } + + if ( SUCCEEDED( inMediaType->GetGUID( MF_MT_MAJOR_TYPE, &guidTypeA ) ) && + SUCCEEDED( newMediaType->GetGUID( MF_MT_MAJOR_TYPE, &guidTypeB ) ) && + IsEqualGUID( guidTypeA, guidTypeB ) ) + { + if ( SUCCEEDED( inMediaType->GetGUID ( MF_MT_SUBTYPE, &guidTypeA ) ) && + SUCCEEDED( newMediaType->GetGUID( MF_MT_SUBTYPE, &guidTypeB ) ) && + IsEqualGUID( guidTypeA, guidTypeB ) ) + { + BOOL passThrough = TRUE; + DMFTCHECKHR_GOTO(CheckPassthroughMediaType(inMediaType, newMediaType, passThrough), done); + *operation = passThrough?DeviceMftTransformTypeEqual: DeviceMftTransformTypeXVP; + } + else + { + //This is a disruptive operation. Actually a decoder operation! + *operation = DeviceMftTransformTypeDecoder; + } + } + done: + return hr; +} + +/*++ +Description: Used to test if the sample passed is a DX sample or not? +--*/ +HRESULT IsInputDxSample( + _In_ IMFSample* pSample, + _Inout_ BOOL *isDxSample + ) +{ + HRESULT hr = S_OK; + ComPtr spBuffer = nullptr; + DMFTCHECKNULL_GOTO( pSample, done, E_INVALIDARG ); + + *isDxSample = false; + if ( SUCCEEDED( pSample->GetBufferByIndex( 0, &spBuffer ) ) ) + { + ComPtr spDXGIBuffer; + ComPtr spResourceTexture; + if ( SUCCEEDED( spBuffer.As(&spDXGIBuffer ) ) && + SUCCEEDED( spDXGIBuffer-> GetResource( IID_PPV_ARGS( &spResourceTexture ) ) ) ) + { + *isDxSample = true; + } + } +done: + return hr; +} + + +/*++ + Description: + Helper function to return back if the Pin is in stopped stateo or not +--*/ +STDMETHODIMP_(BOOL) IsPinStateInActive( _In_ DeviceStreamState state) +{ + if ((state == DeviceStreamState_Disabled) || + (state == DeviceStreamState_Stop)) + { + return TRUE; + } + return FALSE; +} + +/* +Description: + A Helper function to return if the Mediatype is a compressed video type or not! +*/ +STDMETHODIMP_(BOOL) IsKnownUncompressedVideoType(_In_ GUID guidSubType) +{ + if (guidSubType == MFVideoFormat_ARGB32 || + guidSubType == MFVideoFormat_RGB24 || + guidSubType == MFVideoFormat_RGB555 || + guidSubType == MFVideoFormat_RGB565 || + guidSubType == MFVideoFormat_RGB32 || + guidSubType == MFVideoFormat_RGB8 || + guidSubType == MFVideoFormat_AI44 || + guidSubType == MFVideoFormat_AYUV || + guidSubType == MFVideoFormat_YUY2 || + guidSubType == MFVideoFormat_YVYU || + guidSubType == MFVideoFormat_YVU9 || + guidSubType == MFVideoFormat_UYVY || + guidSubType == MFVideoFormat_NV11 || + guidSubType == MFVideoFormat_NV12 || + guidSubType == MFVideoFormat_YV12 || + guidSubType == MFVideoFormat_I420 || + guidSubType == MFVideoFormat_IYUV || + guidSubType == MFVideoFormat_Y210 || + guidSubType == MFVideoFormat_Y216 || + guidSubType == MFVideoFormat_Y410 || + guidSubType == MFVideoFormat_Y416 || + guidSubType == MFVideoFormat_Y41P || + guidSubType == MFVideoFormat_Y41T || + guidSubType == MFVideoFormat_Y42T || + guidSubType == MFVideoFormat_P210 || + guidSubType == MFVideoFormat_P216 || + guidSubType == MFVideoFormat_P010 || + guidSubType == MFVideoFormat_P016 || + guidSubType == MFVideoFormat_v210 || + guidSubType == MFVideoFormat_v216 || + guidSubType == MFVideoFormat_v410 || + guidSubType == MFVideoFormat_L8 || + guidSubType == MFVideoFormat_L16 || + guidSubType == MFVideoFormat_D16) + { + return( TRUE ); + } + + return( FALSE ); +} + +#ifndef IF_EQUAL_RETURN +#define IF_EQUAL_RETURN(param, val) if(val == param) return #val +#endif + +#define checkAdjustBufferCap(a,len){\ + char* tStore = NULL; \ +if (a && strlen(a) > ((len * 7) / 10)){\ + tStore = a; \ + len *= 2; \ + a = new (std::nothrow) char[len]; \ +if (!a){\ +goto done;}\ + a[0] = 0; \ + strcat_s(a, len, tStore); \ + delete(tStore); }\ +} + + +/*++ +Description: + returns an ascii buffer for the GUID passed. The Caller should release the memory allocated +--*/ +LPSTR DumpGUIDA(_In_ REFGUID guid) +{ + LPOLESTR lpszGuidString = NULL; + char *ansiguidStr = NULL; + if (SUCCEEDED(StringFromCLSID(guid, &lpszGuidString))) + { + int mbGuidLen = 0; + mbGuidLen = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, lpszGuidString, -1, NULL, 0, NULL, NULL); + if (mbGuidLen > 0) + { + mf_assert(mbGuidLen == (int)wcslen(lpszGuidString)); + ansiguidStr = new (std::nothrow) char[mbGuidLen]; + if (ansiguidStr) + { + WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpszGuidString, -1, ansiguidStr, mbGuidLen, NULL, NULL); + CoTaskMemFree(lpszGuidString); + ansiguidStr[mbGuidLen - 1] = 0; + } + } + } + return ansiguidStr; +} + +// +//Borrrowed from MDSN sample +// +LPCSTR GetGUIDNameConst(const GUID& guid) +{ + IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE); + IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE); + IF_EQUAL_RETURN(guid, MF_MT_SUBTYPE); + IF_EQUAL_RETURN(guid, MF_MT_ALL_SAMPLES_INDEPENDENT); + IF_EQUAL_RETURN(guid, MF_MT_FIXED_SIZE_SAMPLES); + IF_EQUAL_RETURN(guid, MF_MT_COMPRESSED); + IF_EQUAL_RETURN(guid, MF_MT_SAMPLE_SIZE); + IF_EQUAL_RETURN(guid, MF_MT_WRAPPED_TYPE); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_NUM_CHANNELS); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_SECOND); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BLOCK_ALIGNMENT); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BITS_PER_SAMPLE); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_CHANNEL_MASK); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FOLDDOWN_MATRIX); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKREF); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKTARGET); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGREF); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGTARGET); + IF_EQUAL_RETURN(guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX); + IF_EQUAL_RETURN(guid, MF_MT_AAC_PAYLOAD_TYPE); + IF_EQUAL_RETURN(guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION); + IF_EQUAL_RETURN(guid, MF_MT_FRAME_SIZE); + IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE); + IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MAX); + IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MIN); + IF_EQUAL_RETURN(guid, MF_MT_PIXEL_ASPECT_RATIO); + IF_EQUAL_RETURN(guid, MF_MT_DRM_FLAGS); + IF_EQUAL_RETURN(guid, MF_MT_PAD_CONTROL_FLAGS); + IF_EQUAL_RETURN(guid, MF_MT_SOURCE_CONTENT_HINT); + IF_EQUAL_RETURN(guid, MF_MT_VIDEO_CHROMA_SITING); + IF_EQUAL_RETURN(guid, MF_MT_INTERLACE_MODE); + IF_EQUAL_RETURN(guid, MF_MT_TRANSFER_FUNCTION); + IF_EQUAL_RETURN(guid, MF_MT_VIDEO_PRIMARIES); + IF_EQUAL_RETURN(guid, MF_MT_CUSTOM_VIDEO_PRIMARIES); + IF_EQUAL_RETURN(guid, MF_MT_YUV_MATRIX); + IF_EQUAL_RETURN(guid, MF_MT_VIDEO_LIGHTING); + IF_EQUAL_RETURN(guid, MF_MT_VIDEO_NOMINAL_RANGE); + IF_EQUAL_RETURN(guid, MF_MT_GEOMETRIC_APERTURE); + IF_EQUAL_RETURN(guid, MF_MT_MINIMUM_DISPLAY_APERTURE); + IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_APERTURE); + IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_ENABLED); + IF_EQUAL_RETURN(guid, MF_MT_AVG_BITRATE); + IF_EQUAL_RETURN(guid, MF_MT_AVG_BIT_ERROR_RATE); + IF_EQUAL_RETURN(guid, MF_MT_MAX_KEYFRAME_SPACING); + IF_EQUAL_RETURN(guid, MF_MT_DEFAULT_STRIDE); + IF_EQUAL_RETURN(guid, MF_MT_PALETTE); + IF_EQUAL_RETURN(guid, MF_MT_USER_DATA); + IF_EQUAL_RETURN(guid, MF_MT_AM_FORMAT_TYPE); + IF_EQUAL_RETURN(guid, MF_MT_MPEG_START_TIME_CODE); + IF_EQUAL_RETURN(guid, MF_MT_MPEG2_PROFILE); + IF_EQUAL_RETURN(guid, MF_MT_MPEG2_LEVEL); + IF_EQUAL_RETURN(guid, MF_MT_MPEG2_FLAGS); + IF_EQUAL_RETURN(guid, MF_MT_MPEG_SEQUENCE_HEADER); + IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_0); + IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_0); + IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_1); + IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_1); + IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_SRC_PACK); + IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_CTRL_PACK); + IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_HEADER); + IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_FORMAT); + IF_EQUAL_RETURN(guid, MF_MT_IMAGE_LOSS_TOLERANT); + IF_EQUAL_RETURN(guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION); + IF_EQUAL_RETURN(guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY); + IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_4CC); + IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG); + + // Media types + + IF_EQUAL_RETURN(guid, MFMediaType_Audio); + IF_EQUAL_RETURN(guid, MFMediaType_Video); + IF_EQUAL_RETURN(guid, MFMediaType_Protected); + IF_EQUAL_RETURN(guid, MFMediaType_SAMI); + IF_EQUAL_RETURN(guid, MFMediaType_Script); + IF_EQUAL_RETURN(guid, MFMediaType_Image); + IF_EQUAL_RETURN(guid, MFMediaType_HTML); + IF_EQUAL_RETURN(guid, MFMediaType_Binary); + IF_EQUAL_RETURN(guid, MFMediaType_FileTransfer); + + IF_EQUAL_RETURN(guid, MFVideoFormat_AI44); // FCC('AI44') + IF_EQUAL_RETURN(guid, MFVideoFormat_ARGB32); // D3DFMT_A8R8G8B8 + IF_EQUAL_RETURN(guid, MFVideoFormat_AYUV); // FCC('AYUV') + IF_EQUAL_RETURN(guid, MFVideoFormat_DV25); // FCC('dv25') + IF_EQUAL_RETURN(guid, MFVideoFormat_DV50); // FCC('dv50') + IF_EQUAL_RETURN(guid, MFVideoFormat_DVH1); // FCC('dvh1') + IF_EQUAL_RETURN(guid, MFVideoFormat_DVSD); // FCC('dvsd') + IF_EQUAL_RETURN(guid, MFVideoFormat_DVSL); // FCC('dvsl') + IF_EQUAL_RETURN(guid, MFVideoFormat_H264); // FCC('H264') + IF_EQUAL_RETURN(guid, MFVideoFormat_I420); // FCC('I420') + IF_EQUAL_RETURN(guid, MFVideoFormat_IYUV); // FCC('IYUV') + IF_EQUAL_RETURN(guid, MFVideoFormat_M4S2); // FCC('M4S2') + IF_EQUAL_RETURN(guid, MFVideoFormat_MJPG); + IF_EQUAL_RETURN(guid, MFVideoFormat_MP43); // FCC('MP43') + IF_EQUAL_RETURN(guid, MFVideoFormat_MP4S); // FCC('MP4S') + IF_EQUAL_RETURN(guid, MFVideoFormat_MP4V); // FCC('MP4V') + IF_EQUAL_RETURN(guid, MFVideoFormat_MPG1); // FCC('MPG1') + IF_EQUAL_RETURN(guid, MFVideoFormat_MSS1); // FCC('MSS1') + IF_EQUAL_RETURN(guid, MFVideoFormat_MSS2); // FCC('MSS2') + IF_EQUAL_RETURN(guid, MFVideoFormat_NV11); // FCC('NV11') + IF_EQUAL_RETURN(guid, MFVideoFormat_NV12); // FCC('NV12') + IF_EQUAL_RETURN(guid, MFVideoFormat_P010); // FCC('P010') + IF_EQUAL_RETURN(guid, MFVideoFormat_P016); // FCC('P016') + IF_EQUAL_RETURN(guid, MFVideoFormat_P210); // FCC('P210') + IF_EQUAL_RETURN(guid, MFVideoFormat_P216); // FCC('P216') + IF_EQUAL_RETURN(guid, MFVideoFormat_RGB24); // D3DFMT_R8G8B8 + IF_EQUAL_RETURN(guid, MFVideoFormat_RGB32); // D3DFMT_X8R8G8B8 + IF_EQUAL_RETURN(guid, MFVideoFormat_RGB555); // D3DFMT_X1R5G5B5 + IF_EQUAL_RETURN(guid, MFVideoFormat_RGB565); // D3DFMT_R5G6B5 + IF_EQUAL_RETURN(guid, MFVideoFormat_RGB8); + IF_EQUAL_RETURN(guid, MFVideoFormat_UYVY); // FCC('UYVY') + IF_EQUAL_RETURN(guid, MFVideoFormat_v210); // FCC('v210') + IF_EQUAL_RETURN(guid, MFVideoFormat_v410); // FCC('v410') + IF_EQUAL_RETURN(guid, MFVideoFormat_WMV1); // FCC('WMV1') + IF_EQUAL_RETURN(guid, MFVideoFormat_WMV2); // FCC('WMV2') + IF_EQUAL_RETURN(guid, MFVideoFormat_WMV3); // FCC('WMV3') + IF_EQUAL_RETURN(guid, MFVideoFormat_WVC1); // FCC('WVC1') + IF_EQUAL_RETURN(guid, MFVideoFormat_Y210); // FCC('Y210') + IF_EQUAL_RETURN(guid, MFVideoFormat_Y216); // FCC('Y216') + IF_EQUAL_RETURN(guid, MFVideoFormat_Y410); // FCC('Y410') + IF_EQUAL_RETURN(guid, MFVideoFormat_Y416); // FCC('Y416') + IF_EQUAL_RETURN(guid, MFVideoFormat_Y41P); + IF_EQUAL_RETURN(guid, MFVideoFormat_Y41T); + IF_EQUAL_RETURN(guid, MFVideoFormat_YUY2); // FCC('YUY2') + IF_EQUAL_RETURN(guid, MFVideoFormat_YV12); // FCC('YV12') + IF_EQUAL_RETURN(guid, MFVideoFormat_YVYU); + + IF_EQUAL_RETURN(guid, MFAudioFormat_PCM); // WAVE_FORMAT_PCM + IF_EQUAL_RETURN(guid, MFAudioFormat_Float); // WAVE_FORMAT_IEEE_FLOAT + IF_EQUAL_RETURN(guid, MFAudioFormat_DTS); // WAVE_FORMAT_DTS + IF_EQUAL_RETURN(guid, MFAudioFormat_Dolby_AC3_SPDIF); // WAVE_FORMAT_DOLBY_AC3_SPDIF + IF_EQUAL_RETURN(guid, MFAudioFormat_DRM); // WAVE_FORMAT_DRM + IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV8); // WAVE_FORMAT_WMAUDIO2 + IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV9); // WAVE_FORMAT_WMAUDIO3 + IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS + IF_EQUAL_RETURN(guid, MFAudioFormat_WMASPDIF); // WAVE_FORMAT_WMASPDIF + IF_EQUAL_RETURN(guid, MFAudioFormat_MSP1); // WAVE_FORMAT_WMAVOICE9 + IF_EQUAL_RETURN(guid, MFAudioFormat_MP3); // WAVE_FORMAT_MPEGLAYER3 + IF_EQUAL_RETURN(guid, MFAudioFormat_MPEG); // WAVE_FORMAT_MPEG + IF_EQUAL_RETURN(guid, MFAudioFormat_AAC); // WAVE_FORMAT_MPEG_HEAAC + IF_EQUAL_RETURN(guid, MFAudioFormat_ADTS); // WAVE_FORMAT_MPEG_ADTS_AAC + + return NULL; +} + + +LPSTR DumpAttribute( _In_ const MF_ATTRIBUTE_TYPE& type, + _In_ REFPROPVARIANT var) +{ + CHAR *tempStr = NULL; + tempStr = new (std::nothrow) CHAR[256]; + switch (type) + { + case MF_ATTRIBUTE_UINT32: + if (var.vt == VT_UI4) + { + sprintf_s(tempStr, 256, "%u", var.ulVal); + } + break; + case MF_ATTRIBUTE_UINT64: + if (var.vt == VT_UI8) + { + sprintf_s(tempStr, 256, "%I64d (high: %d low: %d)", var.uhVal.QuadPart, var.uhVal.HighPart, var.uhVal.LowPart); + } + break; + case MF_ATTRIBUTE_DOUBLE: + if (var.vt == VT_R8) + { + sprintf_s(tempStr, 256, "%.4f", var.dblVal); + } + break; + case MF_ATTRIBUTE_GUID: + if (var.vt == VT_CLSID) + { + return DumpGUIDA(*var.puuid); + } + break; + case MF_ATTRIBUTE_STRING: + if (var.vt == VT_LPWSTR) + { + sprintf_s(tempStr, 256, "%S", var.pwszVal); + } + break; + case MF_ATTRIBUTE_IUNKNOWN: + break; + default: + printf("(Unknown Attribute Type = %d) ", type); + break; + } + return tempStr; +} + +CMediaTypePrinter::CMediaTypePrinter( + _In_ IMFMediaType *_pMediaType ) + : pMediaType(_pMediaType), + m_pBuffer(NULL) +{ +} + +CMediaTypePrinter::~CMediaTypePrinter() +{ + if (m_pBuffer) + { + delete(m_pBuffer); + } +} + +/*++ +Description: +Rudimentary function to print the complete Media type +--*/ +PCHAR CMediaTypePrinter::ToCompleteString( ) +{ + HRESULT hr = S_OK; + UINT32 attrCount = 0; + GUID attrGuid = { 0 }; + char *tempStore = nullptr; + PROPVARIANT var; + LPSTR pTempBaseStr; + MF_ATTRIBUTE_TYPE pType; + + if ( pMediaType && !m_pBuffer ) + { + DMFTCHECKHR_GOTO(pMediaType->GetCount(&attrCount), done); + buffLen = MEDIAPRINTER_STARTLEN; + m_pBuffer = new char[buffLen]; + DMFTCHECKNULL_GOTO(m_pBuffer, done, E_OUTOFMEMORY); + m_pBuffer[0] = 0; + for ( UINT32 ulIndex = 0; ulIndex < attrCount; ulIndex++ ) + { + PropVariantInit( &var ); + checkAdjustBufferCap( m_pBuffer, buffLen ); + DMFTCHECKHR_GOTO( pMediaType->GetItemByIndex( ulIndex, &attrGuid, &var ), done ); + DMFTCHECKHR_GOTO( pMediaType->GetItemType( attrGuid, &pType ), done ); + if ( ulIndex > 0 ) + strcat_s(m_pBuffer, MEDIAPRINTER_STARTLEN, " : "); + strcat_s( m_pBuffer, buffLen, GetGUIDNameConst( attrGuid ) ); + strcat_s( m_pBuffer, buffLen, "=" ); + pTempBaseStr = DumpAttribute( pType, var ); + strcat_s( m_pBuffer, buffLen, pTempBaseStr ); + delete( pTempBaseStr ); + PropVariantClear( &var ); + } + done: + if ( tempStore ) + { + delete( tempStore ); + } + } + return m_pBuffer; +} + +/*++ +Description: +Rudimentary function to print the Media type +--*/ + +PCHAR CMediaTypePrinter::ToString() +{ + // + //Following are the important ones of Mediatype attributes + // + + HRESULT hr = S_OK; + PROPVARIANT var; + LPSTR pTempBaseStr; + MF_ATTRIBUTE_TYPE pType; + GUID attrGuid; + GUID impGuids[] = { + MF_MT_SUBTYPE, + MF_MT_FRAME_SIZE, + MF_MT_SAMPLE_SIZE, + MF_MT_FRAME_RATE, + MF_MT_DEFAULT_STRIDE, + MF_XVP_DISABLE_FRC + }; + + if (pMediaType && !m_pBuffer) + { + buffLen = MEDIAPRINTER_STARTLEN; + m_pBuffer = new (std::nothrow) char[buffLen]; + DMFTCHECKNULL_GOTO(m_pBuffer, done, E_OUTOFMEMORY); + m_pBuffer[0] = 0; + for (UINT32 ulIndex = 0; ulIndex < ARRAYSIZE(impGuids); ulIndex++) + { + PropVariantInit(&var); + checkAdjustBufferCap(m_pBuffer, buffLen); + attrGuid = impGuids[ulIndex]; + DMFTCHECKHR_GOTO(pMediaType->GetItemType(attrGuid, &pType), done); + DMFTCHECKHR_GOTO(pMediaType->GetItem(attrGuid, &var), done); + if (ulIndex > 0) + strcat_s(m_pBuffer, MEDIAPRINTER_STARTLEN, " : "); + strcat_s(m_pBuffer, buffLen, GetGUIDNameConst(attrGuid)); + strcat_s(m_pBuffer, buffLen, "="); + pTempBaseStr = DumpAttribute(pType, var); + strcat_s(m_pBuffer, buffLen, pTempBaseStr); + delete(pTempBaseStr); + PropVariantClear(&var); + } + } +done: + return m_pBuffer; +} +/*++ +Description: + Debug message printer to print the message passed through WPP +--*/ +void printMessageEvent(MFT_MESSAGE_TYPE msg) +{ + switch (msg) + { + case MFT_MESSAGE_COMMAND_FLUSH: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_COMMAND_FLUSH"); + break; + case MFT_MESSAGE_COMMAND_DRAIN: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_COMMAND_DRAIN"); + break; + case MFT_MESSAGE_COMMAND_MARKER: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_COMMAND_MARKER"); + break; + case MFT_MESSAGE_COMMAND_TICK: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_COMMAND_TICK"); + break; + case MFT_MESSAGE_NOTIFY_END_OF_STREAM: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_NOTIFY_END_OF_STREAM"); + break; + case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_NOTIFY_BEGIN_STREAMING"); + break; + case MFT_MESSAGE_NOTIFY_START_OF_STREAM: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_NOTIFY_START_OF_STREAM"); + break; + case MFT_MESSAGE_DROP_SAMPLES: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_DROP_SAMPLES"); + break; + case MFT_MESSAGE_SET_D3D_MANAGER: + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! :PROCESSMESSAGE: MFT_MESSAGE_SET_D3D_MANAGER"); + break; + + } +} + +HRESULT GetDXGIAdapterLuid(_In_ IMFDXGIDeviceManager *pDXManager, _Out_ LUID &AdapterLuid) +{ + HRESULT hr = S_OK; + ComPtr spDevice; + ComPtr spDXGIDevice; + ComPtr spDXGIAdapter; + DXGI_ADAPTER_DESC adapterDesc = { 0 }; + HANDLE hDevice = NULL; + + DMFTCHECKNULL_GOTO(pDXManager, done, E_INVALIDARG); + + DMFTCHECKHR_GOTO(pDXManager->OpenDeviceHandle(&hDevice), done); + DMFTCHECKHR_GOTO(pDXManager->GetVideoService(hDevice, IID_PPV_ARGS(&spDevice)), done); + DMFTCHECKHR_GOTO(spDevice->QueryInterface(IID_PPV_ARGS(&spDXGIDevice)), done); + DMFTCHECKHR_GOTO(spDXGIDevice->GetAdapter(&spDXGIAdapter), done); + DMFTCHECKHR_GOTO(spDXGIAdapter->GetDesc(&adapterDesc), done); + + CopyMemory(&AdapterLuid, &adapterDesc.AdapterLuid, sizeof(LUID)); + +done: + if (NULL != hDevice) + { + pDXManager->CloseDeviceHandle(hDevice); + } + + return hr; +} + +HRESULT EnumSWDecoder(_Outptr_ IMFTransform** ppTransform, _In_ GUID subType) +{ + HRESULT hr = S_OK; + IMFActivate** ppActivate = nullptr; + UINT32 count = 0; + ComPtr spTransform; + LPWSTR pszFriendlyName = nullptr; + + MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, subType }; + UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT | + MFT_ENUM_FLAG_LOCALMFT | + MFT_ENUM_FLAG_SORTANDFILTER; + + DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG); + *ppTransform = nullptr; + + DMFTCHECKHR_GOTO(MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, unFlags, + &info, // Input type + NULL, // Output type + &ppActivate, + &count + ), done); + + + if (count == 0) + { + DMFTCHECKHR_GOTO(MF_E_TOPO_CODEC_NOT_FOUND, done); + } + + if (SUCCEEDED(MFGetAttributeString(ppActivate[0], MFT_FRIENDLY_NAME_Attribute, &pszFriendlyName))) + { + // + // Log the friendly name of the decoder + // + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! decoder name: %S ", (pszFriendlyName ? pszFriendlyName : L"UnknownCodec")); + SAFE_COTASKMEMFREE(pszFriendlyName); + } + + DMFTCHECKHR_GOTO(ppActivate[0]->ActivateObject(IID_PPV_ARGS(spTransform.GetAddressOf())), done); + + *ppTransform = spTransform.Detach(); + +done: + if (ppActivate) + { + for (UINT32 uiIndex = 0; uiIndex < count; uiIndex++) + { + ppActivate[uiIndex]->Release(); + } + CoTaskMemFree(ppActivate); + } + return hr; +} +// +// @@@@ README Create the decoder +// +HRESULT CreateDecoderFromLuid( _In_ LUID ullAdapterLuidRunningOn, + _In_ IMFMediaType* pInputType, + _In_ IMFMediaType* pOutputType, + _Inout_ BOOL fHwMft, + _Outptr_ IMFTransform** ppDecoder) +{ + HRESULT hr = S_OK; + ComPtr spAttribs; + ComPtr spMJPGDecoder; + IMFActivate **ppActivates = nullptr; + DWORD dwFlags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_SORTANDFILTER | MFT_ENUM_FLAG_HARDWARE | 0x10000000 /*Internal attribute*/; + UINT32 cMFTActivate = 0; + MFT_REGISTER_TYPE_INFO InputType; + MFT_REGISTER_TYPE_INFO OutputType; + GUID compressedGUID; + ComPtr spD3D11Device; + + fHwMft = FALSE; + + + DMFTCHECKNULL_GOTO(pInputType, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(pOutputType, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(ppDecoder, done, E_INVALIDARG); + *ppDecoder = nullptr; + DMFTCHECKHR_GOTO(pInputType->GetGUID(MF_MT_SUBTYPE, &compressedGUID), done); + + InputType.guidMajorType = MFMediaType_Video; + InputType.guidSubtype = compressedGUID; + + DMFTCHECKHR_GOTO(pOutputType->GetMajorType(&OutputType.guidMajorType), done); + DMFTCHECKHR_GOTO(pOutputType->GetGUID(MF_MT_SUBTYPE, &OutputType.guidSubtype), done); + + DMFTCHECKHR_GOTO(MFCreateAttributes(&spAttribs, 1), done); + DMFTCHECKHR_GOTO(spAttribs->SetBlob(MFT_ENUM_ADAPTER_LUID, (byte*)&ullAdapterLuidRunningOn, sizeof(ullAdapterLuidRunningOn)), done); + DMFTCHECKHR_GOTO(MFTEnum2(MFT_CATEGORY_VIDEO_DECODER, dwFlags, &InputType, &OutputType, spAttribs.Get(), &ppActivates, &cMFTActivate), done); + + for (DWORD i = 0; i < cMFTActivate; i++) + { + HRESULT hrTemp = ppActivates[i]->ActivateObject(IID_PPV_ARGS(spMJPGDecoder.GetAddressOf())); + fHwMft = (MFT_ENUM_FLAG_HARDWARE & MFGetAttributeUINT32(ppActivates[i], MF_TRANSFORM_FLAGS_Attribute, 0)); + // Pickup the first MFT enumerated. Normally, it should be a HW MFT, if HWMFT is available. + if (SUCCEEDED(hrTemp)) + { + break; + } + else + { + spMJPGDecoder = nullptr; + } + } + if (spMJPGDecoder == nullptr) + { + hr = MF_E_NOT_FOUND; + } + *ppDecoder = spMJPGDecoder.Detach(); +done: + + for (UINT32 i = 0; i < cMFTActivate; i++) + { + if (nullptr != ppActivates[i]) + { + ppActivates[i]->Release(); + } + } + SAFE_COTASKMEMFREE(ppActivates); + return hr; +} + +HRESULT SetDX11BindFlags( _In_ IUnknown *pUnkManager, + _In_ GUID guidPinCategory, + _Inout_ DWORD &dwBindFlags) +{ + HRESULT hr = S_OK; + ComPtr spDeviceManager; + BOOL fFL10 = FALSE; + + auto + IsFeatureLevel10OrBetter = [&]() -> BOOL + { + ComPtr spDXGIManager; + ComPtr spDevice; + HANDLE hDevice = 0; + BOOL fRet = FALSE; + UINT level = 0, result = 0; + + if (SUCCEEDED(pUnkManager->QueryInterface(IID_PPV_ARGS(&spDXGIManager))) && + SUCCEEDED(spDXGIManager->OpenDeviceHandle(&hDevice)) && + SUCCEEDED(spDXGIManager->LockDevice(hDevice, IID_PPV_ARGS(&spDevice), FALSE))) + { + + level = (UINT)spDevice->GetFeatureLevel(); + fRet = (level >= D3D_FEATURE_LEVEL_10_0); + if (!fRet) + { + if (SUCCEEDED(spDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &result))) + { + fRet = (result & D3D11_FORMAT_SUPPORT_TEXTURE2D) && (result & D3D11_FORMAT_SUPPORT_RENDER_TARGET); + } + } + (void)spDXGIManager->UnlockDevice(hDevice, FALSE); + (void)spDXGIManager->CloseDeviceHandle(hDevice); + } + return fRet; + }; + + DMFTCHECKNULL_GOTO(pUnkManager, done, E_INVALIDARG); + fFL10 = IsFeatureLevel10OrBetter(); + + dwBindFlags |= fFL10 ? D3D11_BIND_SHADER_RESOURCE : 0; + dwBindFlags |= (guidPinCategory != PINNAME_VIDEO_PREVIEW) ? D3D11_BIND_VIDEO_ENCODER : 0; + if ((dwBindFlags != 0) && ((dwBindFlags & ~(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_VIDEO_ENCODER)) == 0)) + { + dwBindFlags |= D3D11_BIND_RENDER_TARGET; + } +done: + return hr; +} + +// @@@@ README: Create the Decoder +HRESULT CreateDecoderHW(_In_ IMFDXGIDeviceManager* pManager, + _In_ IMFMediaType* inType, + _In_ IMFMediaType* outType, + _Outptr_ IMFTransform** ppTransform, + _Inout_ BOOL& fHwMft) +{ + HRESULT hr = S_OK; + LUID luid; + ComPtr spTransform; + DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG); + *ppTransform = nullptr; + + if (pManager) + { + if (SUCCEEDED(hr = GetDXGIAdapterLuid(pManager, luid))) + { + hr = CreateDecoderFromLuid(luid, inType, outType, fHwMft, spTransform.GetAddressOf()); + if (FAILED(hr)) + { + DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Error creating HW Decoder with LUID %d-%d", luid.HighPart, luid.LowPart); + DMFTCHECKHR_GOTO(hr, done); + } + } + } + *ppTransform = spTransform.Detach(); +done: + return hr; +} + +HRESULT +SubtypeToDXGIFormat( + _In_ GUID subType, + _Inout_ DXGI_FORMAT &format +) +{ + HRESULT hr = S_OK; + typedef struct { + GUID subType; + DXGI_FORMAT format; + }DXGIFormatMap; + DXGIFormatMap formatMap[] + { + { MFVideoFormat_NV12, DXGI_FORMAT_NV12 }, + { MFVideoFormat_YUY2, DXGI_FORMAT_YUY2 }, + { MFVideoFormat_RGB32, DXGI_FORMAT_B8G8R8X8_UNORM }, + { MFVideoFormat_ARGB32, DXGI_FORMAT_B8G8R8A8_UNORM }, + { MFVideoFormat_AYUV, DXGI_FORMAT_AYUV }, + { MFVideoFormat_NV11, DXGI_FORMAT_NV11 }, + { MFVideoFormat_AI44, DXGI_FORMAT_AI44 }, + { MFVideoFormat_P010, DXGI_FORMAT_P010 }, + { MFVideoFormat_P016, DXGI_FORMAT_P016 }, + { MFVideoFormat_Y210, DXGI_FORMAT_Y210 }, + { MFVideoFormat_Y216, DXGI_FORMAT_Y216 }, + { MFVideoFormat_Y410, DXGI_FORMAT_Y410 }, + { MFVideoFormat_Y416, DXGI_FORMAT_Y416 }, + }; + format = DXGI_FORMAT_UNKNOWN; + for (UINT32 uiIndex = 0; uiIndex < _countof(formatMap); uiIndex++) + { + if (formatMap[uiIndex].subType == subType) + { + format = formatMap[uiIndex].format; + break; + } + } + // compressed media type or unsupported of the range + hr = (format == DXGI_FORMAT_UNKNOWN) ? E_NOTIMPL : S_OK; + return hr; +} + +HRESULT IsDXFormatSupported( + _In_ IMFDXGIDeviceManager* pDeviceManager , + _In_ GUID subType, + _Outptr_opt_ ID3D11Device** ppDevice, + _In_opt_ PUINT32 pSupportedFormat) +{ + HRESULT hr = S_OK; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + UINT32 supportedFormat = 0; + HANDLE hDevice = NULL; + ComPtr spDevice; + DMFTCHECKNULL_GOTO(pDeviceManager, done, E_INVALIDARG); + DMFTCHECKHR_GOTO(pDeviceManager->OpenDeviceHandle(&hDevice), done); + DMFTCHECKHR_GOTO(pDeviceManager->GetVideoService(hDevice, IID_PPV_ARGS(&spDevice)), done); + DMFTCHECKHR_GOTO(SubtypeToDXGIFormat(subType, format), done); + DMFTCHECKHR_GOTO(spDevice->CheckFormatSupport(format, &supportedFormat), done); + if (pSupportedFormat) + { + *pSupportedFormat = supportedFormat; + } + if (ppDevice) + { + *ppDevice = spDevice.Detach(); + } +done: + if (hDevice != NULL) + { + pDeviceManager->CloseDeviceHandle(hDevice); + } + return hr; +} + +HRESULT +UpdateAllocatorAttributes( + _In_ IMFAttributes *pAttributes, + _In_ REFGUID guidStreamCategory, + _In_ GUID subType, + _In_ IMFDXGIDeviceManager *pDeviceManager +) +{ + HRESULT hr = S_OK; + UINT32 supportedFormat = 0; + ComPtr spDevice; + DWORD dwBindFlags = 0; + + DMFTCHECKHR_GOTO(IsDXFormatSupported(pDeviceManager,subType, + spDevice.GetAddressOf(),&supportedFormat),done); + + // MF_SA_D3D11_USAGE should be D3D11_USAGE_DEFAULT, same as previous release. + DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_USAGE, D3D11_USAGE_DEFAULT), done); + + DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_SHARED_WITHOUT_MUTEX, TRUE), done); + DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_SHARED_WITH_NTHANDLE_PRIVATE, TRUE), done); + + // Bind Flags + dwBindFlags |= ((supportedFormat & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0 ? D3D11_BIND_RENDER_TARGET : 0); + + if (((supportedFormat & D3D11_FORMAT_SUPPORT_VIDEO_ENCODER) != 0) && + (!IsEqualGUID(guidStreamCategory, PINNAME_VIDEO_PREVIEW)) && + IsEqualGUID(subType, MFVideoFormat_NV12)) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS4 Options = { 0 }; + + // "D3D11_BIND_VIDEO_ENCODER + sharing" is only supported on those devices that + // advertise ExtendedNV12SharedTextureSupported. + DMFTCHECKHR_GOTO(spDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS4, &Options, sizeof(Options)), done); + if (Options.ExtendedNV12SharedTextureSupported) + { + dwBindFlags |= D3D11_BIND_VIDEO_ENCODER; + } + } + + // D3D requires one of the flags (D3D11_BIND_RENDER_TARGET, D3D11_PRIVATE_BIND_CAPTURE, or D3D11_BIND_VIDEO_ENCODER) to be set for non-zero bind flags. + if (dwBindFlags != 0) + { + D3D_FEATURE_LEVEL level; + + // D3D11_BIND_SHADER_RESOURCE + level = spDevice->GetFeatureLevel(); + dwBindFlags |= ((level >= D3D_FEATURE_LEVEL_10_0) ? D3D11_BIND_SHADER_RESOURCE : 0); + } + + DMFTCHECKHR_GOTO(pAttributes->SetUINT32(MF_SA_D3D11_BINDFLAGS, dwBindFlags), done); + +done: + return hr; +} + +const UINT32 ALLOCATOR_MIN_SAMPLES = 10; +const UINT32 ALLOCATOR_MAX_SAMPLES = 50; + +HRESULT ConfigureAllocator( + _In_ IMFMediaType* pOutputMediaType, + _In_ GUID streamCategory, + _In_ IUnknown* pDeviceManagerUnk, + _In_ BOOL &bDxAllocator, + _In_ IMFVideoSampleAllocator* pAllocator) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow spPrivateAllocator; +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + wil::com_ptr_nothrow spDefaultAllocator; +#endif + wil::com_ptr_nothrow spAllocatorAttributes; + GUID guidMajorType = GUID_NULL; + GUID guidSubtype = GUID_NULL; + BOOL fDXAllocator = FALSE; + + RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator ); + RETURN_HR_IF_NULL(E_INVALIDARG, pOutputMediaType ); + + RETURN_IF_FAILED(pOutputMediaType->GetMajorType(&guidMajorType)); + + if (!IsEqualGUID(guidMajorType, MFMediaType_Video)) + { + RETURN_HR(MF_E_INVALIDMEDIATYPE); + } + + RETURN_IF_FAILED(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype)); + // + // Set Attributes on the allocator we need. First get the Bind Flags. + // + RETURN_IF_FAILED(MFCreateAttributes(&spAllocatorAttributes, 8)); + RETURN_IF_FAILED(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1)); + + if (pDeviceManagerUnk != nullptr) + { + if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.get(), streamCategory, guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk))) + { + fDXAllocator = TRUE; + } + } + + if (fDXAllocator) + { + RETURN_IF_FAILED(pAllocator->SetDirectXManager(pDeviceManagerUnk)); + } + + if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spPrivateAllocator)))) + { + RETURN_IF_FAILED(spPrivateAllocator->InitializeSampleAllocatorEx( + ALLOCATOR_MIN_SAMPLES, + ALLOCATOR_MAX_SAMPLES, + spAllocatorAttributes.get(), + pOutputMediaType)); + } +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + else if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spDefaultAllocator)))) + { + RETURN_IF_FAILED(spDefaultAllocator->InitializeCaptureSampleAllocator( + 0, /*use sample size by MediaType*/ + 0, /*metadata size*/ + 0, /*default alignment*/ + ALLOCATOR_MIN_SAMPLES, + spAllocatorAttributes.get(), + pOutputMediaType)); + } +#endif + else + { + hr = E_INVALIDARG; + } + + bDxAllocator = fDXAllocator; + + return hr; +} +// +//@@@@ README: Creating an Allocator.. Please don't allocate samples individually using MFCreateSample as that can lead to fragmentation and is +// extremely inefficent. Instead create an Allocator which will create a fixed number of samples which are recycled when the pipeline returns back +// the buffers. The above has defines will enable to create a circular allocator which will have maximum 20 samples flowing in the pipeline +// This way we can also catch samples leaks if any. +// +HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType, + _In_ GUID streamCategory, + _In_ IUnknown* pDeviceManagerUnk, + _In_ BOOL &bDxAllocator, + _Outptr_ IMFVideoSampleAllocatorEx** ppAllocator ) +{ + HRESULT hr = S_OK; + ComPtr spVideoSampleAllocator; + ComPtr spAllocatorAttributes; + GUID guidMajorType = GUID_NULL; + GUID guidSubtype = GUID_NULL; + BOOL fDXAllocator = FALSE; + + DMFTCHECKNULL_GOTO(ppAllocator, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(pOutputMediaType, done, E_INVALIDARG); + DMFTCHECKHR_GOTO(pOutputMediaType->GetMajorType(&guidMajorType), done); + + *ppAllocator = nullptr; + if (!IsEqualGUID(guidMajorType, MFMediaType_Video)) + { + DMFTCHECKHR_GOTO(MF_E_INVALIDMEDIATYPE, done); + } + + DMFTCHECKHR_GOTO(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done); + // + // Set Attributes on the allocator we need. First get the Bind Flags. + // + DMFTCHECKHR_GOTO(MFCreateAttributes(&spAllocatorAttributes, 8), done); + DMFTCHECKHR_GOTO(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1), done); + + if (pDeviceManagerUnk != nullptr) + { + if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.Get(), streamCategory,guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk))) + { + fDXAllocator = TRUE; + } + } + DMFTCHECKHR_GOTO(MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(spVideoSampleAllocator.ReleaseAndGetAddressOf())), done); + if (fDXAllocator) + { + DMFTCHECKHR_GOTO(spVideoSampleAllocator->SetDirectXManager(pDeviceManagerUnk), done); + } + + DMFTCHECKHR_GOTO(spVideoSampleAllocator->InitializeSampleAllocatorEx(ALLOCATOR_MIN_SAMPLES, ALLOCATOR_MAX_SAMPLES, spAllocatorAttributes.Get(), pOutputMediaType), done); + + *ppAllocator = spVideoSampleAllocator.Detach(); + bDxAllocator = fDXAllocator; +done: + return hr; +} + +HRESULT CheckPassthroughMediaType(_In_ IMFMediaType *pMediaType1, + _In_ IMFMediaType *pMediaType2, + _Out_ BOOL& pfPassThrough) +{ + HRESULT hr = S_OK; + BOOL fPassThrough = FALSE; + UINT32 uWidth, uHeight; + UINT32 uWidth2, uHeight2; + + // Compare Width/Height. + DMFTCHECKHR_GOTO(MFGetAttributeSize(pMediaType1, MF_MT_FRAME_SIZE, &uWidth, &uHeight), done); + DMFTCHECKHR_GOTO(MFGetAttributeSize(pMediaType2, MF_MT_FRAME_SIZE, &uWidth2, &uHeight2), done); + if ((uWidth != uWidth2) || (uHeight != uHeight2)) + { + goto done; + } + + // Compare rotation + { + UINT32 uRotation; + UINT32 uRotation2; + + uRotation = MFGetAttributeUINT32(pMediaType1, MF_MT_VIDEO_ROTATION, 0); + uRotation2 = MFGetAttributeUINT32(pMediaType2, MF_MT_VIDEO_ROTATION, 0); + if (uRotation != uRotation2) + { + goto done; + } + } + + // Compare Aspect Ratio + { + UINT32 uNumerator = 1, uDenominator = 1; + UINT32 uNumerator2 = 1, uDenominator2 = 1; + + (void)MFGetAttributeRatio(pMediaType1, MF_MT_FRAME_RATE, &uNumerator, &uDenominator); + (void)MFGetAttributeRatio(pMediaType2, MF_MT_FRAME_RATE, &uNumerator2, &uDenominator2); + if ((uNumerator * uDenominator2) != (uNumerator2 * uDenominator)) + { + goto done; + } + } + + // Compare Nominal Range + { + UINT32 uNorminalRange; + UINT32 uNorminalRange2; + + uNorminalRange = MFGetAttributeUINT32(pMediaType1, MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_Unknown); + uNorminalRange2 = MFGetAttributeUINT32(pMediaType2, MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_Unknown); + if (uNorminalRange != uNorminalRange2) + { + goto done; + } + } + + // Compare color primaries + { + UINT32 uPrimaries; + UINT32 uPrimaries2; + + uPrimaries = MFGetAttributeUINT32(pMediaType1, MF_MT_VIDEO_PRIMARIES, MFVideoPrimaries_Unknown); + uPrimaries2 = MFGetAttributeUINT32(pMediaType2, MF_MT_VIDEO_PRIMARIES, MFVideoPrimaries_Unknown); + if (uPrimaries != uPrimaries2) + { + goto done; + } + } + + + // Compare InterlaceMode + { + UINT32 uInterlaceMode; + UINT32 uInterlaceMode2; + + uInterlaceMode = MFGetAttributeUINT32(pMediaType1, MF_MT_INTERLACE_MODE, MFVideoInterlace_Unknown); + uInterlaceMode2 = MFGetAttributeUINT32(pMediaType2, MF_MT_INTERLACE_MODE, MFVideoInterlace_Unknown); + if (uInterlaceMode != uInterlaceMode2) + { + goto done; + } + } + + // Compare display aperture + { + MFVideoArea VideoArea = { 0 }; + MFVideoArea VideoArea2 = { 0 }; + UINT32 cbBlobSize = 0; + + if (SUCCEEDED(pMediaType1->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&VideoArea, sizeof(MFVideoArea), &cbBlobSize))) + { + if ((VideoArea.OffsetX.value == 0 && VideoArea.OffsetX.fract == 0) && + (VideoArea.OffsetY.value == 0 && VideoArea.OffsetY.fract == 0) && + (VideoArea.Area.cx == (LONG)uWidth) && + (VideoArea.Area.cy == (LONG)uHeight)) + { + // If the display aperture is the whole frame size, ignore it. + ZeroMemory(&VideoArea, sizeof(VideoArea)); + } + } + + if (SUCCEEDED(pMediaType2->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&VideoArea2, sizeof(MFVideoArea), &cbBlobSize))) + { + if ((VideoArea2.OffsetX.value == 0 && VideoArea2.OffsetX.fract == 0) && + (VideoArea2.OffsetY.value == 0 && VideoArea2.OffsetY.fract == 0) && + (VideoArea2.Area.cx == (LONG)uWidth) && + (VideoArea2.Area.cy == (LONG)uHeight)) + { + // If the display aperture is the whole frame size, ignore it. + ZeroMemory(&VideoArea, sizeof(VideoArea)); + } + } + + if (memcmp(&VideoArea, &VideoArea2, sizeof(MFVideoArea)) != 0) + { + goto done; + } + } + + fPassThrough = TRUE; + +done: + pfPassThrough = fPassThrough; + return hr; +} + + +HRESULT MergeSampleAttributes( _In_ IMFSample* pInSample, _Inout_ IMFSample* pOutSample) +{ + HRESULT hr = S_OK; + UINT32 cAttributes = 0; + GUID guidAttribute; + PROPVARIANT varAttribute; + PROPVARIANT varAttributeExists; + PropVariantInit(&varAttribute); + PropVariantInit(&varAttributeExists); + + DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG); + DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG); + + DMFTCHECKHR_GOTO(pInSample->GetCount(&cAttributes), done); + for (UINT32 i = 0; i < cAttributes; i++) + { + PropVariantClear(&varAttribute); + PropVariantClear(&varAttributeExists); + + DMFTCHECKHR_GOTO(pInSample->GetItemByIndex(i, &guidAttribute, &varAttribute), done); + + if (S_OK == pOutSample->GetItem(guidAttribute, &varAttributeExists)) + { + // Exists.. dont clobber + continue; + } + + DMFTCHECKHR_GOTO(pOutSample->SetItem(guidAttribute, varAttribute), done); + } + +done: + PropVariantClear(&varAttribute); + PropVariantClear(&varAttributeExists); + return hr; +} diff --git a/avstream/sampledevicemft/multipinmft.vcxproj b/avstream/sampledevicemft/multipinmft.vcxproj index f13ed67d6..152ff207e 100644 --- a/avstream/sampledevicemft/multipinmft.vcxproj +++ b/avstream/sampledevicemft/multipinmft.vcxproj @@ -30,7 +30,7 @@ Windows10 False - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -38,7 +38,7 @@ Windows10 True - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver WindowsApplicationForDrivers10.0 DynamicLibrary @@ -189,7 +189,7 @@ %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD - %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + onecore.lib;D2d1.lib;mfcore.lib;mfplat.lib;mfuuid.lib;uuid.lib Source.def @@ -204,7 +204,7 @@ %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD - %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + onecore.lib;D2d1.lib;mfcore.lib;mfplat.lib;mfuuid.lib;uuid.lib Source.def @@ -219,7 +219,7 @@ %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD - %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + onecore.lib;D2d1.lib;mfcore.lib;mfplat.lib;mfuuid.lib;uuid.lib Source.def @@ -234,7 +234,7 @@ %(PreprocessorDefinitions);UNICODE;MF_WPP;SECURITY_WIN32;MFT_UNIQUE_METHOD_NAMES;MF_DEVICEMFT_ALLOW_MFT0_LOAD - %(AdditionalDependencies);D2d1.lib;mf.lib;mfplat.lib;mfuuid.lib;uuid.lib + onecore.lib;D2d1.lib;mfcore.lib;mfplat.lib;mfuuid.lib;uuid.lib Source.def diff --git a/biometrics/Package/package.VcxProj b/biometrics/Package/package.VcxProj deleted file mode 100644 index fb98576d7..000000000 --- a/biometrics/Package/package.VcxProj +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - {22EED378-7FE9-4946-A653-05BB1EE20717} - - - {321860DA-56D9-427A-A5C2-346DFE8FB529} - - - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2} - - - {474A1976-0414-48E7-9F2B-4FDED5BA700C} - - - - WindowsKernelModeDriver10.0 - Utility - Package - true - Debug - - - - {93931C7A-00DC-4E0F-8D54-06A960AF23FC} - {A1648E68-56F1-41FA-903C-F64C87787413} - $(MSBuildProjectName) - - - Windows10 - true - - - Windows10 - false - - - Windows10 - true - - - Windows10 - false - - - - - - - - - - - DbgengRemoteDebugger - False - None - - - - - - %PathToInf% - False - False - True - - 133563 - - - - sha256 - - - - - sha256 - - - - - sha256 - - - - - sha256 - - - - - - \ No newline at end of file diff --git a/biometrics/Package/package.VcxProj.Filters b/biometrics/Package/package.VcxProj.Filters deleted file mode 100644 index fc0e5c564..000000000 --- a/biometrics/Package/package.VcxProj.Filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* - {7DC6547C-49AA-4ABD-B48E-1C589CF982E2} - - - h;hpp;hxx;hm;inl;inc;xsd - {98781539-8891-4798-9778-6AF2451E1062} - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml - {3D1F0D76-620A-4046-A834-772C416DE4E5} - - - inf;inv;inx;mof;mc; - {7FA33C20-27C2-45C8-AD85-B5686078DB41} - - - \ No newline at end of file diff --git a/biometrics/README.md b/biometrics/README.md deleted file mode 100644 index abf0235e6..000000000 --- a/biometrics/README.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -page_type: sample -description: "Contains the Windows Biometric Driver Interface sample and the Windows Biometric Service Adapter samples." -languages: -- cpp -products: -- windows -- windows-wdk ---- - -# Windows Biometric Driver Samples (UMDF Version 1) - -The Windows Biometric Driver Samples contain the Windows Biometric Driver Interface sample and the Windows Biometric Service Adapter samples. - -## Windows Biometric Driver Interface - -This sample implements the Windows Biometric Driver Interface (WBDI). It contains skeleton code for handling the mandatory IOCTLs necessary to interoperate with the Windows Biometric Framework. A WBDI driver can be deployed in conjunction with an engine adapter DLL to allow a sensor to be exposed from the Windows Biometric Framework. This sample has been written to make use of the UMDF framework, which allows for ease of development and system stability. - -## Windows Biometric Service Adapters - -These samples provide skeleton code that developers can use as a basis for writing Sensor, Engine, and Storage Adapters for the Windows Biometric Service. Note that the stubs in these samples are non-functional, and Adapter writers will need to follow the programming guidelines in the WinBio Service documentation in order produce a working Adapter component. - -## Build the sample - -For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver). - -> [!NOTE] -> You can obtain the co-installers by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). - -## Installation - -### Windows Biometric Driver Interface installation - -The sample requires the use of a suitable fingerprint sensor. It does not capture real data, but it does create a biometric unit in the Windows Biometric Framework. - -### Windows Biometric Service Adapters installation - -To write and test an Adapter plug-in, it will be necessary to have a biometric device and a working WBDI driver for the device. - -Adapters are generally installed along with the WBDI driver for the corresponding device. Consult the WinBio Service documentation for information on the INF file commands used for installing Adapters. Note that Adapters are trusted plug-in components, so they can only be installed using a privileged account. - -## Design and operation - -### Windows Biometric Driver Interface - -This sample is taken from the UMDF FX2 sample and has been modified to expose WBDI. It has the necessary hooks to make this a WBDI driver: - -- Installs WBDI driver, including correct class GUID settings and icons, and registry settings for Windows Biometric Framework configuration. -- Publishes WBDI device interface. -- Supports all the mandatory [WBDI IOCTLs](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_biometric/#ioctls). -- Supports cancellation. -- Can be opened with exclusivity. - -All of these things are required for the Windows Biometric Framework service to recognize this device as a biometric device and set up a Biometric Unit. It allows the service to properly control the device. - -The sample makes use of ATL support for simplified handling of COM objects with UMDF. - -The driver makes use of a parallel queue so that multiple requests can be outstanding at once. - -It uses device level-locking to simplify internal thread synchronization. This means that only one framework callback can be active at a time. - -It supports cancellation of any IOCTL which may be I/O intensive, particularly a capture IOCTL. This sample does not have a real capture mechanism, so it is simulated by a 5 second delay returning a capture IOCTL. Cancellation is supported through the mechanism exposed by WUDF, with a callback for a request object. Cancellation support is required for all IOCTLs. - -There are hooks for all [WBDI IOCTLs](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_biometric/#ioctls), including the optional IOCTLs. - -PnP is very simple for this driver. It needs to only implement **OnPrepareHardware** and **OnReleaseHardware** from **IPnpCallbackHardware**. - -Some device drivers may need to keep several pending reads to the WinUsb I/O target in order to properly flush all I/O that comes from the device during a capture. - -### Windows Biometric Service Adapters - -WinBio Adapters are plug-in components that provide a standard interface layer between the Windows Biometric Service and a biometric device. The WinBio Service recognizes three types of Adapters: - -- Sensor Adapters - expose the sample-capture capabilities of the biometric device. -- Engine Adapters - expose the sample manipulation, template generation, and matching capabilities of the device. -- Storage Adapters - expose the template storage and retrieval capabilities of the device. - -For many simple biometric devices, it will only be necessary to write a WBDI driver for the device plus an Engine Adapter to perform matching operations. Consult the programming guidelines in the WinBio Service documentation for more details. - -Each Adapter sample contains a well-known interface-discovery function, whose job is to return the address of a function dispatch table. When the WinBio Service loads an Adapter plug-in, it uses the interface-discovery function to locate the dispatch table, and then calls various methods in the table to communicate with the biometric device. The purpose, arguments, and return codes of each Adapter method are described in the WinBio Service programming guidelines. More information on adapter plug-ins is available at [WBDI Plug-in Reference](https://docs.microsoft.com/windows/desktop/SecBioMet/plug-in-reference). diff --git a/biometrics/WBDIsample.sln b/biometrics/WBDIsample.sln deleted file mode 100644 index 98de6df9d..000000000 --- a/biometrics/WBDIsample.sln +++ /dev/null @@ -1,90 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0 -MinimumVisualStudioVersion = 12.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{2E5F1FF5-DA6C-4935-8389-17811F54BC28}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Storage_adapter", "Storage_adapter", "{AB84BCF3-9781-47FE-9AF0-8D96FF6F27DE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Adapters", "Adapters", "{B6C842E0-023A-40CE-84EA-76C0A7B366FD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sensor_adapter", "Sensor_adapter", "{CFF6A5A2-CF3E-413B-A36E-3B4B81657D5D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine_adapter", "Engine_adapter", "{15B79D52-B6B0-431E-AA93-EAF3D204EB81}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Driver", "Driver", "{038A4A81-D088-4E25-AEE5-93D35BF5B25C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{93931C7A-00DC-4E0F-8D54-06A960AF23FC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StorageAdapter", "adapters\storage_adapter\StorageAdapter.vcxproj", "{339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SensorAdapter", "adapters\sensor_adapter\SensorAdapter.vcxproj", "{321860DA-56D9-427A-A5C2-346DFE8FB529}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EngineAdapter", "adapters\engine_adapter\EngineAdapter.vcxproj", "{22EED378-7FE9-4946-A653-05BB1EE20717}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WudfBioUsbSample", "driver\WudfBioUsbSample.vcxproj", "{474A1976-0414-48E7-9F2B-4FDED5BA700C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Debug|Win32.ActiveCfg = Debug|Win32 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Debug|Win32.Build.0 = Debug|Win32 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Release|Win32.ActiveCfg = Release|Win32 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Release|Win32.Build.0 = Release|Win32 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Debug|x64.ActiveCfg = Debug|x64 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Debug|x64.Build.0 = Debug|x64 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Release|x64.ActiveCfg = Release|x64 - {93931C7A-00DC-4E0F-8D54-06A960AF23FC}.Release|x64.Build.0 = Release|x64 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Debug|Win32.ActiveCfg = Debug|Win32 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Debug|Win32.Build.0 = Debug|Win32 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Release|Win32.ActiveCfg = Release|Win32 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Release|Win32.Build.0 = Release|Win32 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Debug|x64.ActiveCfg = Debug|x64 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Debug|x64.Build.0 = Debug|x64 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Release|x64.ActiveCfg = Release|x64 - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2}.Release|x64.Build.0 = Release|x64 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Debug|Win32.ActiveCfg = Debug|Win32 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Debug|Win32.Build.0 = Debug|Win32 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Release|Win32.ActiveCfg = Release|Win32 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Release|Win32.Build.0 = Release|Win32 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Debug|x64.ActiveCfg = Debug|x64 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Debug|x64.Build.0 = Debug|x64 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Release|x64.ActiveCfg = Release|x64 - {321860DA-56D9-427A-A5C2-346DFE8FB529}.Release|x64.Build.0 = Release|x64 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Debug|Win32.ActiveCfg = Debug|Win32 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Debug|Win32.Build.0 = Debug|Win32 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Release|Win32.ActiveCfg = Release|Win32 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Release|Win32.Build.0 = Release|Win32 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Debug|x64.ActiveCfg = Debug|x64 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Debug|x64.Build.0 = Debug|x64 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Release|x64.ActiveCfg = Release|x64 - {22EED378-7FE9-4946-A653-05BB1EE20717}.Release|x64.Build.0 = Release|x64 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Debug|Win32.ActiveCfg = Debug|Win32 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Debug|Win32.Build.0 = Debug|Win32 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Release|Win32.ActiveCfg = Release|Win32 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Release|Win32.Build.0 = Release|Win32 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Debug|x64.ActiveCfg = Debug|x64 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Debug|x64.Build.0 = Debug|x64 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Release|x64.ActiveCfg = Release|x64 - {474A1976-0414-48E7-9F2B-4FDED5BA700C}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {93931C7A-00DC-4E0F-8D54-06A960AF23FC} = {2E5F1FF5-DA6C-4935-8389-17811F54BC28} - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2} = {AB84BCF3-9781-47FE-9AF0-8D96FF6F27DE} - {321860DA-56D9-427A-A5C2-346DFE8FB529} = {CFF6A5A2-CF3E-413B-A36E-3B4B81657D5D} - {22EED378-7FE9-4946-A653-05BB1EE20717} = {15B79D52-B6B0-431E-AA93-EAF3D204EB81} - {474A1976-0414-48E7-9F2B-4FDED5BA700C} = {038A4A81-D088-4E25-AEE5-93D35BF5B25C} - {AB84BCF3-9781-47FE-9AF0-8D96FF6F27DE} = {B6C842E0-023A-40CE-84EA-76C0A7B366FD} - {CFF6A5A2-CF3E-413B-A36E-3B4B81657D5D} = {B6C842E0-023A-40CE-84EA-76C0A7B366FD} - {15B79D52-B6B0-431E-AA93-EAF3D204EB81} = {B6C842E0-023A-40CE-84EA-76C0A7B366FD} - EndGlobalSection -EndGlobal diff --git a/biometrics/adapters/engine_adapter/EngineAdapter.cpp b/biometrics/adapters/engine_adapter/EngineAdapter.cpp deleted file mode 100644 index 229611248..000000000 --- a/biometrics/adapters/engine_adapter/EngineAdapter.cpp +++ /dev/null @@ -1,665 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - EngineAdapter.cpp - -Abstract: - - This module contains a stub implementation of an Engine Adapter - plug-in for the Windows Biometric service. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ - -/////////////////////////////////////////////////////////////////////////////// -// -// Header files... -// -/////////////////////////////////////////////////////////////////////////////// -#include "precomp.h" -#include "winbio_adapter.h" -#include "EngineAdapter.h" - - -/////////////////////////////////////////////////////////////////////////////// -// -// Forward declarations for the Engine Adapter's interface routines... -// -/////////////////////////////////////////////////////////////////////////////// -static HRESULT -WINAPI -EngineAdapterAttach( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -EngineAdapterDetach( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -EngineAdapterClearContext( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -EngineAdapterEndOperation( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -EngineAdapterQueryPreferredFormat( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REGISTERED_FORMAT StandardFormat, - _Out_ PWINBIO_UUID VendorFormat - ); - -static HRESULT -WINAPI -EngineAdapterQueryIndexVectorSize( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T IndexElementCount - ); - -static HRESULT -WINAPI -EngineAdapterQueryHashAlgorithms( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T AlgorithmCount, - _Out_ PSIZE_T AlgorithmBufferSize, - _Out_ PUCHAR *AlgorithmBuffer - ); - -static HRESULT -WINAPI -EngineAdapterSetHashAlgorithm( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ SIZE_T AlgorithmBufferSize, - _In_ PUCHAR AlgorithmBuffer - ); - -static HRESULT -WINAPI -EngineAdapterAcceptSampleHint( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T SampleHint - ); - -static HRESULT -WINAPI -EngineAdapterAcceptSampleData( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_BIR SampleBuffer, - _In_ SIZE_T SampleSize, - _In_ WINBIO_BIR_PURPOSE Purpose, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -EngineAdapterExportEngineData( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIR_DATA_FLAGS Flags, - _Out_ PWINBIO_BIR *SampleBuffer, - _Out_ PSIZE_T SampleSize - ); - -static HRESULT -WINAPI -EngineAdapterVerifyFeatureSet( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor, - _Out_ PBOOLEAN Match, - _Out_ PUCHAR *PayloadBlob, - _Out_ PSIZE_T PayloadBlobSize, - _Out_ PUCHAR *HashValue, - _Out_ PSIZE_T HashSize, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -EngineAdapterIdentifyFeatureSet( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_IDENTITY Identity, - _Out_ PWINBIO_BIOMETRIC_SUBTYPE SubFactor, - _Out_ PUCHAR *PayloadBlob, - _Out_ PSIZE_T PayloadBlobSize, - _Out_ PUCHAR *HashValue, - _Out_ PSIZE_T HashSize, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -EngineAdapterCreateEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -EngineAdapterUpdateEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -EngineAdapterGetEnrollmentStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -EngineAdapterGetEnrollmentHash( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PUCHAR *HashValue, - _Out_ PSIZE_T HashSize - ); - -static HRESULT -WINAPI -EngineAdapterCheckForDuplicate( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_IDENTITY Identity, - _Out_ PWINBIO_BIOMETRIC_SUBTYPE SubFactor, - _Out_ PBOOLEAN Duplicate - ); - -static HRESULT -WINAPI -EngineAdapterCommitEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor, - _In_ PUCHAR PayloadBlob, - _In_ SIZE_T PayloadBlobSize - ); - -static HRESULT -WINAPI -EngineAdapterDiscardEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -EngineAdapterControlUnit( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ); - -static HRESULT -WINAPI -EngineAdapterControlUnitPrivileged( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ); -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Interface dispatch table -// -/////////////////////////////////////////////////////////////////////////////// -static WINBIO_ENGINE_INTERFACE g_EngineInterface = { - WINBIO_ENGINE_INTERFACE_VERSION_1, - WINBIO_ADAPTER_TYPE_ENGINE, - sizeof(WINBIO_ENGINE_INTERFACE), - {0xb876fdc8, 0x34e7, 0x471a, {0x82, 0xc8, 0x9c, 0xba, 0x6a, 0x35, 0x38, 0xec}}, - - EngineAdapterAttach, - EngineAdapterDetach, - EngineAdapterClearContext, - EngineAdapterQueryPreferredFormat, - EngineAdapterQueryIndexVectorSize, - EngineAdapterQueryHashAlgorithms, - EngineAdapterSetHashAlgorithm, - EngineAdapterAcceptSampleHint, - EngineAdapterAcceptSampleData, - EngineAdapterExportEngineData, - EngineAdapterVerifyFeatureSet, - EngineAdapterIdentifyFeatureSet, - EngineAdapterCreateEnrollment, - EngineAdapterUpdateEnrollment, - EngineAdapterGetEnrollmentStatus, - EngineAdapterGetEnrollmentHash, - EngineAdapterCheckForDuplicate, - EngineAdapterCommitEnrollment, - EngineAdapterDiscardEnrollment, - EngineAdapterControlUnit, - EngineAdapterControlUnitPrivileged -}; -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Mandatory DLL entrypoint function. -// -/////////////////////////////////////////////////////////////////////////////// -BOOL APIENTRY -DllMain( - HANDLE ModuleHandle, - DWORD ReasonForCall, - LPVOID Reserved - ) -{ - UNREFERENCED_PARAMETER(ModuleHandle); - UNREFERENCED_PARAMETER(ReasonForCall); - UNREFERENCED_PARAMETER(Reserved); - - return TRUE; -} -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Well-known interface-discovery function exported by the Engine Adapter -// -/////////////////////////////////////////////////////////////////////////////// -HRESULT -WINAPI -WbioQueryEngineInterface( - _Out_ PWINBIO_ENGINE_INTERFACE *EngineInterface - ) -{ - *EngineInterface = &g_EngineInterface; - return S_OK; -} -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Engine Adapter action routines -// -/////////////////////////////////////////////////////////////////////////////// -static HRESULT -WINAPI -EngineAdapterAttach( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterDetach( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterClearContext( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterQueryPreferredFormat( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REGISTERED_FORMAT StandardFormat, - _Out_ PWINBIO_UUID VendorFormat - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(StandardFormat); - UNREFERENCED_PARAMETER(VendorFormat); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterQueryIndexVectorSize( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T IndexElementCount - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(IndexElementCount); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterQueryHashAlgorithms( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T AlgorithmCount, - _Out_ PSIZE_T AlgorithmBufferSize, - _Out_ PUCHAR *AlgorithmBuffer - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(AlgorithmCount); - UNREFERENCED_PARAMETER(AlgorithmBufferSize); - UNREFERENCED_PARAMETER(AlgorithmBuffer); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterSetHashAlgorithm( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ SIZE_T AlgorithmBufferSize, - _In_ PUCHAR AlgorithmBuffer - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(AlgorithmBufferSize); - UNREFERENCED_PARAMETER(AlgorithmBuffer); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterAcceptSampleHint( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T SampleHint - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(SampleHint); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterAcceptSampleData( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_BIR SampleBuffer, - _In_ SIZE_T SampleSize, - _In_ WINBIO_BIR_PURPOSE Purpose, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(SampleBuffer); - UNREFERENCED_PARAMETER(SampleSize); - UNREFERENCED_PARAMETER(Purpose); - UNREFERENCED_PARAMETER(RejectDetail); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterExportEngineData( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIR_DATA_FLAGS Flags, - _Out_ PWINBIO_BIR *SampleBuffer, - _Out_ PSIZE_T SampleSize - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Flags); - UNREFERENCED_PARAMETER(SampleBuffer); - UNREFERENCED_PARAMETER(SampleSize); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterVerifyFeatureSet( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor, - _Out_ PBOOLEAN Match, - _Out_ PUCHAR *PayloadBlob, - _Out_ PSIZE_T PayloadBlobSize, - _Out_ PUCHAR *HashValue, - _Out_ PSIZE_T HashSize, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Identity); - UNREFERENCED_PARAMETER(SubFactor); - UNREFERENCED_PARAMETER(Match); - UNREFERENCED_PARAMETER(PayloadBlob); - UNREFERENCED_PARAMETER(PayloadBlobSize); - UNREFERENCED_PARAMETER(HashValue); - UNREFERENCED_PARAMETER(HashSize); - UNREFERENCED_PARAMETER(RejectDetail); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterIdentifyFeatureSet( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_IDENTITY Identity, - _Out_ PWINBIO_BIOMETRIC_SUBTYPE SubFactor, - _Out_ PUCHAR *PayloadBlob, - _Out_ PSIZE_T PayloadBlobSize, - _Out_ PUCHAR *HashValue, - _Out_ PSIZE_T HashSize, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Identity); - UNREFERENCED_PARAMETER(SubFactor); - UNREFERENCED_PARAMETER(PayloadBlob); - UNREFERENCED_PARAMETER(PayloadBlobSize); - UNREFERENCED_PARAMETER(HashValue); - UNREFERENCED_PARAMETER(HashSize); - UNREFERENCED_PARAMETER(RejectDetail); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterCreateEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterUpdateEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(RejectDetail); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterGetEnrollmentStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(RejectDetail); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterGetEnrollmentHash( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PUCHAR *HashValue, - _Out_ PSIZE_T HashSize - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(HashValue); - UNREFERENCED_PARAMETER(HashSize); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterCheckForDuplicate( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_IDENTITY Identity, - _Out_ PWINBIO_BIOMETRIC_SUBTYPE SubFactor, - _Out_ PBOOLEAN Duplicate - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Identity); - UNREFERENCED_PARAMETER(SubFactor); - UNREFERENCED_PARAMETER(Duplicate); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterCommitEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor, - _In_ PUCHAR PayloadBlob, - _In_ SIZE_T PayloadBlobSize - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Identity); - UNREFERENCED_PARAMETER(SubFactor); - UNREFERENCED_PARAMETER(PayloadBlob); - UNREFERENCED_PARAMETER(PayloadBlobSize); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterDiscardEnrollment( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterControlUnit( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(ControlCode); - UNREFERENCED_PARAMETER(SendBuffer); - UNREFERENCED_PARAMETER(SendBufferSize); - UNREFERENCED_PARAMETER(ReceiveBuffer); - UNREFERENCED_PARAMETER(ReceiveBufferSize); - UNREFERENCED_PARAMETER(ReceiveDataSize); - UNREFERENCED_PARAMETER(OperationStatus); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -EngineAdapterControlUnitPrivileged( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(ControlCode); - UNREFERENCED_PARAMETER(SendBuffer); - UNREFERENCED_PARAMETER(SendBufferSize); - UNREFERENCED_PARAMETER(ReceiveBuffer); - UNREFERENCED_PARAMETER(ReceiveBufferSize); - UNREFERENCED_PARAMETER(ReceiveDataSize); - UNREFERENCED_PARAMETER(OperationStatus); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - diff --git a/biometrics/adapters/engine_adapter/EngineAdapter.def b/biometrics/adapters/engine_adapter/EngineAdapter.def deleted file mode 100644 index 8f8b458fe..000000000 --- a/biometrics/adapters/engine_adapter/EngineAdapter.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY EngineAdapter - -EXPORTS - WbioQueryEngineInterface diff --git a/biometrics/adapters/engine_adapter/EngineAdapter.h b/biometrics/adapters/engine_adapter/EngineAdapter.h deleted file mode 100644 index 1be2cd6d2..000000000 --- a/biometrics/adapters/engine_adapter/EngineAdapter.h +++ /dev/null @@ -1,75 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - EngineAdapter.h - -Abstract: - - This module contains a stub implementation of an Engine Adapter - plug-in for the Windows Biometric service. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ -#pragma once - -#include "winbio_adapter.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// The WINIBIO_ENGINE_CONTEXT structure is privately-defined by each -// Engine Adapter. Its purpose is to maintain any information that -// should persist across Engine Adapter API calls. -// -// The Adapter allocates and initializes one of these structures in its -// 'Attach' routine and saves its address in the Pipeline->EngineContext -// field. -// -// The Engine Adapter's 'Detach' routine cleans up and deallocates the -// structure and sets the PipelineContext->EngineContext field to NULL. -// -/////////////////////////////////////////////////////////////////////////////// -typedef struct _WINIBIO_ENGINE_CONTEXT { - // - // The following fields illustrate the kind of information - // the Engine Adapter needs to keep in this structure: - // - // FeatureSet - A processed description of a biometric - // sample. - // - // Enrollment - An object that tracks the current state - // of an in-progress enrollment operation. - // - // Template - A template either created from the Feature - // Set or from the Enrollment object. - // - // Comparison - An object that tracks the result of a - // one-to-one comparison between the Template - // and the Feature Set. - // - PVOID x; - PVOID y; - PVOID z; - -} WINIBIO_ENGINE_CONTEXT, *PWINIBIO_ENGINE_CONTEXT; - diff --git a/biometrics/adapters/engine_adapter/EngineAdapter.rc b/biometrics/adapters/engine_adapter/EngineAdapter.rc deleted file mode 100644 index d2a99f201..000000000 --- a/biometrics/adapters/engine_adapter/EngineAdapter.rc +++ /dev/null @@ -1,29 +0,0 @@ -//--------------------------------------------------------------------------- -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// -// Copyright (c) 2007 Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - - -#include -#include -#include "resource.h" - -// -// TODO: Change the file description and file names to match your binary. -// - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT_UNKNOWN -#define VER_FILEDESCRIPTION_STR "Engine Adapter Sample" -#define VER_INTERNALNAME_STR "EngineAdapter" -#define VER_ORIGINALFILENAME_STR "EngineAdapter.dll" - -#include "common.ver" diff --git a/biometrics/adapters/engine_adapter/EngineAdapter.vcxproj b/biometrics/adapters/engine_adapter/EngineAdapter.vcxproj deleted file mode 100644 index aa87c108b..000000000 --- a/biometrics/adapters/engine_adapter/EngineAdapter.vcxproj +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {22EED378-7FE9-4946-A653-05BB1EE20717} - $(MSBuildProjectName) - false - true - Debug - Win32 - {9263013E-19E1-41D9-B085-8892CE56B9BB} - - - - Windows10 - False - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - False - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - - $(IntDir) - - - - - - - - - - - - - - - - EngineAdapter - - - EngineAdapter - - - EngineAdapter - - - EngineAdapter - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - EngineAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - EngineAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - EngineAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - EngineAdapter.def - - - - - ;%(AdditionalIncludeDirectories) - precomp.h - Use - $(IntDir)\precomp.h.pch - - - ;%(AdditionalIncludeDirectories) - precomp.h - Create - $(IntDir)\precomp.h.pch - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/biometrics/adapters/engine_adapter/EngineAdapter.vcxproj.Filters b/biometrics/adapters/engine_adapter/EngineAdapter.vcxproj.Filters deleted file mode 100644 index ab887f288..000000000 --- a/biometrics/adapters/engine_adapter/EngineAdapter.vcxproj.Filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* - {010878EC-7BA3-41C4-B355-5556C237FDE3} - - - h;hpp;hxx;hm;inl;inc;xsd - {64493738-BBBD-46B2-995D-EF8EE18A251D} - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml - {E0C063ED-18D1-4D6B-A62A-5E6CF79522C1} - - - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/biometrics/adapters/engine_adapter/precomp.h b/biometrics/adapters/engine_adapter/precomp.h deleted file mode 100644 index c36eb36cd..000000000 --- a/biometrics/adapters/engine_adapter/precomp.h +++ /dev/null @@ -1,62 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - precomp.h - -Abstract: - - This module contains identifies all the headers that - shoulde be pre-compiled. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ -#pragma once - -// -// Necessary for compiling under VC. -// -#if(!defined(WINVER) || (WINVER < 0x0500)) - #undef WINVER - #define WINVER 0x0500 -#endif -#if(!defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)) - #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0500 -#endif - -// -// Required header files that shouldn't change often. -// -#include -#include -#include - -// -// StrSafe.h needs to be included last -// to disallow unsafe string functions. -#include - -#ifndef ARGUMENT_PRESENT -#define ARGUMENT_PRESENT(x) ((x) != NULL) -#endif diff --git a/biometrics/adapters/engine_adapter/precompsrc.cpp b/biometrics/adapters/engine_adapter/precompsrc.cpp deleted file mode 100644 index 5944cf515..000000000 --- a/biometrics/adapters/engine_adapter/precompsrc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "precomp.h" \ No newline at end of file diff --git a/biometrics/adapters/engine_adapter/resource.h b/biometrics/adapters/engine_adapter/resource.h deleted file mode 100644 index 95ed37fa6..000000000 --- a/biometrics/adapters/engine_adapter/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//--------------------------------------------------------------------------- -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// -// Copyright (c) 2007 Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - -#pragma once - diff --git a/biometrics/adapters/sensor_adapter/SensorAdapter.cpp b/biometrics/adapters/sensor_adapter/SensorAdapter.cpp deleted file mode 100644 index 0e5345aaf..000000000 --- a/biometrics/adapters/sensor_adapter/SensorAdapter.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - SensorAdapter.cpp - -Abstract: - - This module contains a stub implementation of a Sensor Adapter - plug-in for the Windows Biometric service. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ - -/////////////////////////////////////////////////////////////////////////////// -// -// Header files... -// -/////////////////////////////////////////////////////////////////////////////// -#include "precomp.h" -#include "winbio_adapter.h" -#include "SensorAdapter.h" - - -/////////////////////////////////////////////////////////////////////////////// -// -// Forward declarations for the Engine Adapter's interface routines... -// -/////////////////////////////////////////////////////////////////////////////// -static HRESULT -WINAPI -SensorAdapterAttach( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -SensorAdapterDetach( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -SensorAdapterClearContext( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -SensorAdapterQueryStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_SENSOR_STATUS Status - ); - -static HRESULT -WINAPI -SensorAdapterReset( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -SensorAdapterSetMode( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_SENSOR_MODE Mode - ); - -static HRESULT -WINAPI -SensorAdapterSetIndicatorStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_INDICATOR_STATUS IndicatorStatus - ); - -static HRESULT -WINAPI -SensorAdapterGetIndicatorStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_INDICATOR_STATUS IndicatorStatus - ); - -static HRESULT -WINAPI -SensorAdapterStartCapture( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIR_PURPOSE Purpose, - _Out_ LPOVERLAPPED *Overlapped - ); - -static HRESULT -WINAPI -SensorAdapterFinishCapture( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -SensorAdapterClearCaptureBuffer( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -SensorAdapterExportSensorData( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_BIR *SampleBuffer, - _Out_ PSIZE_T SampleSize - ); - -static HRESULT -WINAPI -SensorAdapterCancel( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -SensorAdapterPushDataToEngine( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIR_PURPOSE Purpose, - _In_ WINBIO_BIR_DATA_FLAGS Flags, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ); - -static HRESULT -WINAPI -SensorAdapterControlUnit( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ); - -static HRESULT -WINAPI -SensorAdapterControlUnitPrivileged( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ); -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Interface dispatch table -// -/////////////////////////////////////////////////////////////////////////////// -static WINBIO_SENSOR_INTERFACE g_SensorInterface = { - WINBIO_STORAGE_INTERFACE_VERSION_1, - WINBIO_ADAPTER_TYPE_SENSOR, - sizeof(WINBIO_SENSOR_INTERFACE), - {0xa545298c, 0xec34, 0x4306, {0x84, 0x12, 0x83, 0x12, 0x5d, 0xca, 0xfa, 0xe1}}, - - SensorAdapterAttach, - SensorAdapterDetach, - SensorAdapterClearContext, - SensorAdapterQueryStatus, - SensorAdapterReset, - SensorAdapterSetMode, - SensorAdapterSetIndicatorStatus, - SensorAdapterGetIndicatorStatus, - SensorAdapterStartCapture, - SensorAdapterFinishCapture, - SensorAdapterExportSensorData, - SensorAdapterCancel, - SensorAdapterPushDataToEngine, - SensorAdapterControlUnit, - SensorAdapterControlUnitPrivileged -}; -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Mandatory DLL entrypoint function. -// -/////////////////////////////////////////////////////////////////////////////// -BOOL APIENTRY -DllMain( - HANDLE ModuleHandle, - DWORD ReasonForCall, - LPVOID Reserved - ) -{ - UNREFERENCED_PARAMETER(ModuleHandle); - UNREFERENCED_PARAMETER(ReasonForCall); - UNREFERENCED_PARAMETER(Reserved); - - return TRUE; -} -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Well-known interface-discovery function exported by the Sensor Adapter -// -/////////////////////////////////////////////////////////////////////////////// -HRESULT -WINAPI -WbioQuerySensorInterface( - _Out_ PWINBIO_SENSOR_INTERFACE *SensorInterface - ) -{ - *SensorInterface = &g_SensorInterface; - return S_OK; -} -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Storage Adapter action routines -// -/////////////////////////////////////////////////////////////////////////////// -static HRESULT -WINAPI -SensorAdapterAttach( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterDetach( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterClearContext( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterQueryStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_SENSOR_STATUS Status - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Status); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterReset( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterSetMode( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_SENSOR_MODE Mode - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Mode); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterSetIndicatorStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_INDICATOR_STATUS IndicatorStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(IndicatorStatus); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterGetIndicatorStatus( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_INDICATOR_STATUS IndicatorStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(IndicatorStatus); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterStartCapture( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIR_PURPOSE Purpose, - _Out_ LPOVERLAPPED *Overlapped - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Purpose); - UNREFERENCED_PARAMETER(Overlapped); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterFinishCapture( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(RejectDetail); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -// -// Export raw capture buffer -// -static HRESULT -WINAPI -SensorAdapterExportSensorData( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_BIR *SampleBuffer, - _Out_ PSIZE_T SampleSize - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(SampleBuffer); - UNREFERENCED_PARAMETER(SampleSize); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterCancel( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -// -// Push current sample into the Engine and -// convert it into a feature set for use in -// additional processing. -// -static HRESULT -WINAPI -SensorAdapterPushDataToEngine( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIR_PURPOSE Purpose, - _In_ WINBIO_BIR_DATA_FLAGS Flags, - _Out_ PWINBIO_REJECT_DETAIL RejectDetail - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Purpose); - UNREFERENCED_PARAMETER(Flags); - UNREFERENCED_PARAMETER(RejectDetail); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterControlUnit( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(ControlCode); - UNREFERENCED_PARAMETER(SendBuffer); - UNREFERENCED_PARAMETER(SendBufferSize); - UNREFERENCED_PARAMETER(ReceiveBuffer); - UNREFERENCED_PARAMETER(ReceiveBufferSize); - UNREFERENCED_PARAMETER(ReceiveDataSize); - UNREFERENCED_PARAMETER(OperationStatus); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// - -static HRESULT -WINAPI -SensorAdapterControlUnitPrivileged( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(ControlCode); - UNREFERENCED_PARAMETER(SendBuffer); - UNREFERENCED_PARAMETER(SendBufferSize); - UNREFERENCED_PARAMETER(ReceiveBuffer); - UNREFERENCED_PARAMETER(ReceiveBufferSize); - UNREFERENCED_PARAMETER(ReceiveDataSize); - UNREFERENCED_PARAMETER(OperationStatus); - - return E_NOTIMPL; -} -/////////////////////////////////////////////////////////////////////////////// diff --git a/biometrics/adapters/sensor_adapter/SensorAdapter.def b/biometrics/adapters/sensor_adapter/SensorAdapter.def deleted file mode 100644 index e25340089..000000000 --- a/biometrics/adapters/sensor_adapter/SensorAdapter.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY SensorAdapter - -EXPORTS - WbioQuerySensorInterface - diff --git a/biometrics/adapters/sensor_adapter/SensorAdapter.h b/biometrics/adapters/sensor_adapter/SensorAdapter.h deleted file mode 100644 index f70c3f515..000000000 --- a/biometrics/adapters/sensor_adapter/SensorAdapter.h +++ /dev/null @@ -1,68 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - SensorAdapter.h - -Abstract: - - This module contains a stub implementation of an Sensor Adapter - plug-in for the Windows Biometric service. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ -#pragma once - -#include "winbio_adapter.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// The WINIBIO_SENSOR_CONTEXT structure is privately-defined by each -// Sensor Adapter. Its purpose is to maintain any information that -// should persist across Sensor Adapter API calls. -// -// The Adapter allocates and initializes one of these structures in its -// 'Attach' routine and saves its address in the Pipeline->SensorContext -// field. -// -// The Sensor Adapter's 'Detach' routine cleans up and deallocates the -// structure and sets the PipelineContext->SensorContext field to NULL. -// -/////////////////////////////////////////////////////////////////////////////// -typedef struct _WINIBIO_SENSOR_CONTEXT { - // - // The following fields illustrate the kind of information - // the Sensor Adapter needs to keep in this structure: - // - // SampleBuffer - A pointer to the most-recently-captured - // data sample from the sensor device. - // - // SampleSize - Count of the number of bytes in the - // sample buffer. - // - PWINBIO_BIR SampleBuffer; - SIZE_T SampleSize; - -} WINIBIO_SENSOR_CONTEXT, *PWINIBIO_SENSOR_CONTEXT; - - diff --git a/biometrics/adapters/sensor_adapter/SensorAdapter.rc b/biometrics/adapters/sensor_adapter/SensorAdapter.rc deleted file mode 100644 index 0c08a2089..000000000 --- a/biometrics/adapters/sensor_adapter/SensorAdapter.rc +++ /dev/null @@ -1,29 +0,0 @@ -//--------------------------------------------------------------------------- -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// -// Copyright (c) 2007 Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - - -#include -#include -#include "resource.h" - -// -// TODO: Change the file description and file names to match your binary. -// - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT_UNKNOWN -#define VER_FILEDESCRIPTION_STR "Sensor Adapter Sample" -#define VER_INTERNALNAME_STR "SensorAdapter" -#define VER_ORIGINALFILENAME_STR "SensorAdapter.dll" - -#include "common.ver" diff --git a/biometrics/adapters/sensor_adapter/SensorAdapter.vcxproj b/biometrics/adapters/sensor_adapter/SensorAdapter.vcxproj deleted file mode 100644 index 008320a3e..000000000 --- a/biometrics/adapters/sensor_adapter/SensorAdapter.vcxproj +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {321860DA-56D9-427A-A5C2-346DFE8FB529} - $(MSBuildProjectName) - false - true - Debug - Win32 - {6166C525-23D0-4D3C-8DD3-1E3CB527FA23} - - - - Windows10 - False - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - False - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - - $(IntDir) - - - - - - - - - - - - - - - - SensorAdapter - - - SensorAdapter - - - SensorAdapter - - - SensorAdapter - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - SensorAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - SensorAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - SensorAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - SensorAdapter.def - - - - - ;%(AdditionalIncludeDirectories) - precomp.h - Create - $(IntDir)\precomp.h.pch - - - ;%(AdditionalIncludeDirectories) - precomp.h - Use - $(IntDir)\precomp.h.pch - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/biometrics/adapters/sensor_adapter/SensorAdapter.vcxproj.Filters b/biometrics/adapters/sensor_adapter/SensorAdapter.vcxproj.Filters deleted file mode 100644 index 53f0b241f..000000000 --- a/biometrics/adapters/sensor_adapter/SensorAdapter.vcxproj.Filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* - {51205C64-E853-46B7-8706-03C4F355D3FB} - - - h;hpp;hxx;hm;inl;inc;xsd - {65E3A5BF-7427-4CB0-B6C7-F47537AC67BB} - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml - {05AE8E4A-3180-403D-BFB9-122DD85E0D1A} - - - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/biometrics/adapters/sensor_adapter/precomp.h b/biometrics/adapters/sensor_adapter/precomp.h deleted file mode 100644 index c36eb36cd..000000000 --- a/biometrics/adapters/sensor_adapter/precomp.h +++ /dev/null @@ -1,62 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - precomp.h - -Abstract: - - This module contains identifies all the headers that - shoulde be pre-compiled. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ -#pragma once - -// -// Necessary for compiling under VC. -// -#if(!defined(WINVER) || (WINVER < 0x0500)) - #undef WINVER - #define WINVER 0x0500 -#endif -#if(!defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)) - #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0500 -#endif - -// -// Required header files that shouldn't change often. -// -#include -#include -#include - -// -// StrSafe.h needs to be included last -// to disallow unsafe string functions. -#include - -#ifndef ARGUMENT_PRESENT -#define ARGUMENT_PRESENT(x) ((x) != NULL) -#endif diff --git a/biometrics/adapters/sensor_adapter/precompsrc.cpp b/biometrics/adapters/sensor_adapter/precompsrc.cpp deleted file mode 100644 index 5944cf515..000000000 --- a/biometrics/adapters/sensor_adapter/precompsrc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "precomp.h" \ No newline at end of file diff --git a/biometrics/adapters/sensor_adapter/resource.h b/biometrics/adapters/sensor_adapter/resource.h deleted file mode 100644 index 95ed37fa6..000000000 --- a/biometrics/adapters/sensor_adapter/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//--------------------------------------------------------------------------- -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// -// Copyright (c) 2007 Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - -#pragma once - diff --git a/biometrics/adapters/storage_adapter/StorageAdapter.cpp b/biometrics/adapters/storage_adapter/StorageAdapter.cpp deleted file mode 100644 index 4e5cfb664..000000000 --- a/biometrics/adapters/storage_adapter/StorageAdapter.cpp +++ /dev/null @@ -1,594 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Storage.cpp - -Abstract: - - This module contains a stub implementation of a Storage Adapter - plug-in for the Windows Biometric service. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ - -/////////////////////////////////////////////////////////////////////////////// -// -// Header files... -// -/////////////////////////////////////////////////////////////////////////////// -#include "precomp.h" -#include "winbio_adapter.h" -#include "StorageAdapter.h" - - -/////////////////////////////////////////////////////////////////////////////// -// -// Forward declarations for the Storage Adapter's interface routines... -// -/////////////////////////////////////////////////////////////////////////////// -static HRESULT -WINAPI -StorageAdapterAttach( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -StorageAdapterDetach( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -StorageAdapterClearContext( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -StorageAdapterCreateDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_UUID DatabaseId, - _In_ WINBIO_BIOMETRIC_TYPE Factor, - _In_ PWINBIO_UUID Format, - _In_ LPCWSTR FilePath, - _In_ LPCWSTR ConnectString, - _In_ SIZE_T IndexElementCount, - _In_ SIZE_T InitialSize - ); - -static HRESULT -WINAPI -StorageAdapterEraseDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_UUID DatabaseId, - _In_ LPCWSTR FilePath, - _In_ LPCWSTR ConnectString - ); - -static HRESULT -WINAPI -StorageAdapterOpenDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_UUID DatabaseId, - _In_ LPCWSTR FilePath, - _In_ LPCWSTR ConnectString - ); - -static HRESULT -WINAPI -StorageAdapterCloseDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -StorageAdapterGetDataFormat( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_UUID Format, - _Out_ PWINBIO_VERSION Version - ); - -static HRESULT -WINAPI -StorageAdapterGetDatabaseSize( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T AvailableRecordCount, - _Out_ PSIZE_T TotalRecordCount - ); - -static HRESULT -WINAPI -StorageAdapterAddRecord( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_STORAGE_RECORD RecordContents - ); - -static HRESULT -WINAPI -StorageAdapterDeleteRecord( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor - ); - -static HRESULT -WINAPI -StorageAdapterQueryBySubject( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor - ); - -static HRESULT -WINAPI -StorageAdapterQueryByContent( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor, - _In_ ULONG IndexVector[], - _In_ SIZE_T IndexElementCount - ); - -static HRESULT -WINAPI -StorageAdapterGetRecordCount( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T RecordCount - ); - -static HRESULT -WINAPI -StorageAdapterFirstRecord( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -StorageAdapterNextRecord( - _Inout_ PWINBIO_PIPELINE Pipeline - ); - -static HRESULT -WINAPI -StorageAdapterGetCurrentRecord( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_STORAGE_RECORD RecordContents - ); - -static HRESULT -WINAPI -StorageAdapterControlUnit( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ); - -static HRESULT -WINAPI -StorageAdapterControlUnitPrivileged( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ); -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Interface dispatch table -// -/////////////////////////////////////////////////////////////////////////////// -static WINBIO_STORAGE_INTERFACE g_StorageInterface = { - WINBIO_STORAGE_INTERFACE_VERSION_1, - WINBIO_ADAPTER_TYPE_STORAGE, - sizeof(WINBIO_STORAGE_INTERFACE), - {0x7f6c2610, 0xfdba, 0x41a3, {0xae, 0x1c, 0x8f, 0xd5, 0x84, 0x59, 0x8d, 0x13}}, - - StorageAdapterAttach, - StorageAdapterDetach, - StorageAdapterClearContext, - StorageAdapterCreateDatabase, - StorageAdapterEraseDatabase, - StorageAdapterOpenDatabase, - StorageAdapterCloseDatabase, - StorageAdapterGetDataFormat, - StorageAdapterGetDatabaseSize, - StorageAdapterAddRecord, - StorageAdapterDeleteRecord, - StorageAdapterQueryBySubject, - StorageAdapterQueryByContent, - StorageAdapterGetRecordCount, - StorageAdapterFirstRecord, - StorageAdapterNextRecord, - StorageAdapterGetCurrentRecord, - StorageAdapterControlUnit, - StorageAdapterControlUnitPrivileged -}; -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Mandatory DLL entrypoint function. -// -/////////////////////////////////////////////////////////////////////////////// -BOOL APIENTRY -DllMain( - HANDLE ModuleHandle, - DWORD ReasonForCall, - LPVOID Reserved - ) -{ - UNREFERENCED_PARAMETER(ModuleHandle); - UNREFERENCED_PARAMETER(ReasonForCall); - UNREFERENCED_PARAMETER(Reserved); - - return TRUE; -} -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Well-known interface-discovery function exported by the Storage Adapter -// -/////////////////////////////////////////////////////////////////////////////// -HRESULT -WINAPI -WbioQueryStorageInterface( - _Out_ PWINBIO_STORAGE_INTERFACE *StorageInterface - ) -{ - *StorageInterface = &g_StorageInterface; - return S_OK; -} -//----------------------------------------------------------------------------- - - -/////////////////////////////////////////////////////////////////////////////// -// -// Storage Adapter action routines -// -/////////////////////////////////////////////////////////////////////////////// -static HRESULT -WINAPI -StorageAdapterAttach( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterDetach( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterClearContext( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterCreateDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_UUID DatabaseId, - _In_ WINBIO_BIOMETRIC_TYPE Factor, - _In_ PWINBIO_UUID Format, - _In_ LPCWSTR FilePath, - _In_ LPCWSTR ConnectString, - _In_ SIZE_T IndexElementCount, - _In_ SIZE_T InitialSize - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(DatabaseId); - UNREFERENCED_PARAMETER(Factor); - UNREFERENCED_PARAMETER(Format); - UNREFERENCED_PARAMETER(FilePath); - UNREFERENCED_PARAMETER(ConnectString); - UNREFERENCED_PARAMETER(IndexElementCount); - UNREFERENCED_PARAMETER(InitialSize); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterEraseDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_UUID DatabaseId, - _In_ LPCWSTR FilePath, - _In_ LPCWSTR ConnectString - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(DatabaseId); - UNREFERENCED_PARAMETER(FilePath); - UNREFERENCED_PARAMETER(ConnectString); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterOpenDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_UUID DatabaseId, - _In_ LPCWSTR FilePath, - _In_ LPCWSTR ConnectString - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(DatabaseId); - UNREFERENCED_PARAMETER(FilePath); - UNREFERENCED_PARAMETER(ConnectString); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterCloseDatabase( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterGetDataFormat( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_UUID Format, - _Out_ PWINBIO_VERSION Version - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Format); - UNREFERENCED_PARAMETER(Version); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterGetDatabaseSize( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T AvailableRecordCount, - _Out_ PSIZE_T TotalRecordCount - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(AvailableRecordCount); - UNREFERENCED_PARAMETER(TotalRecordCount); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterAddRecord( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_STORAGE_RECORD RecordContents - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(RecordContents); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterDeleteRecord( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Identity); - UNREFERENCED_PARAMETER(SubFactor); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterQueryBySubject( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ PWINBIO_IDENTITY Identity, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(Identity); - UNREFERENCED_PARAMETER(SubFactor); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterQueryByContent( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ WINBIO_BIOMETRIC_SUBTYPE SubFactor, - _In_ ULONG IndexVector[], - _In_ SIZE_T IndexElementCount - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(SubFactor); - UNREFERENCED_PARAMETER(IndexVector); - UNREFERENCED_PARAMETER(IndexElementCount); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterGetRecordCount( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PSIZE_T RecordCount - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(RecordCount); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterFirstRecord( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterNextRecord( - _Inout_ PWINBIO_PIPELINE Pipeline - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterGetCurrentRecord( - _Inout_ PWINBIO_PIPELINE Pipeline, - _Out_ PWINBIO_STORAGE_RECORD RecordContents - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(RecordContents); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterControlUnit( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(ControlCode); - UNREFERENCED_PARAMETER(SendBuffer); - UNREFERENCED_PARAMETER(SendBufferSize); - UNREFERENCED_PARAMETER(ReceiveBuffer); - UNREFERENCED_PARAMETER(ReceiveBufferSize); - UNREFERENCED_PARAMETER(ReceiveDataSize); - UNREFERENCED_PARAMETER(OperationStatus); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - -static HRESULT -WINAPI -StorageAdapterControlUnitPrivileged( - _Inout_ PWINBIO_PIPELINE Pipeline, - _In_ ULONG ControlCode, - _In_ PUCHAR SendBuffer, - _In_ SIZE_T SendBufferSize, - _In_ PUCHAR ReceiveBuffer, - _In_ SIZE_T ReceiveBufferSize, - _Out_ PSIZE_T ReceiveDataSize, - _Out_ PULONG OperationStatus - ) -{ - UNREFERENCED_PARAMETER(Pipeline); - UNREFERENCED_PARAMETER(ControlCode); - UNREFERENCED_PARAMETER(SendBuffer); - UNREFERENCED_PARAMETER(SendBufferSize); - UNREFERENCED_PARAMETER(ReceiveBuffer); - UNREFERENCED_PARAMETER(ReceiveBufferSize); - UNREFERENCED_PARAMETER(ReceiveDataSize); - UNREFERENCED_PARAMETER(OperationStatus); - - return E_NOTIMPL; -} -//----------------------------------------------------------------------------- - - diff --git a/biometrics/adapters/storage_adapter/StorageAdapter.def b/biometrics/adapters/storage_adapter/StorageAdapter.def deleted file mode 100644 index 685b9f3fb..000000000 --- a/biometrics/adapters/storage_adapter/StorageAdapter.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY StorageAdapter - -EXPORTS - WbioQueryStorageInterface diff --git a/biometrics/adapters/storage_adapter/StorageAdapter.h b/biometrics/adapters/storage_adapter/StorageAdapter.h deleted file mode 100644 index d0259213f..000000000 --- a/biometrics/adapters/storage_adapter/StorageAdapter.h +++ /dev/null @@ -1,79 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - StorageAdapter.h - -Abstract: - - This module contains a stub implementation of a Storage Adapter - plug-in for the Windows Biometric service. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ -#pragma once - -#include "winbio_adapter.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// The WINIBIO_STORAGE_CONTEXT structure is privately-defined by each -// Storage Adapter. Its purpose is to maintain any information that -// should persist across Storage Adapter API calls. -// -// The Adapter allocates and initializes one of these structures in its -// 'Attach' routine and saves its address in the Pipeline->StorageContext -// field. -// -// The Storage Adapter's 'Detach' routine cleans up and deallocates the -// structure and sets the PipelineContext->StorageContext field to NULL. -// -/////////////////////////////////////////////////////////////////////////////// -typedef struct _WINIBIO_STORAGE_CONTEXT { - // - // The following fields illustrate the kind of information - // the Storage Adapter needs to keep in this structure: - // - // DatabaseId - Identify of the Adapter's - // currently-opened database. - // - // DatabaseHandle - A handle to the Storage Adapter's - // currently-open database. - // - // ResultSet - A collection of records generated by - // a database query operation. - // - // ResultSetCursor - Current location in the result - // set. Used to iterate through the - // result set and make individual - // records available. - // - WINBIO_UUID DatabaseId; - PVOID DatabaseHandle; - PVOID ResultSet; - PVOID ResultSetCursor; - -} WINIBIO_STORAGE_CONTEXT, *PWINIBIO_STORAGE_CONTEXT; - - - diff --git a/biometrics/adapters/storage_adapter/StorageAdapter.rc b/biometrics/adapters/storage_adapter/StorageAdapter.rc deleted file mode 100644 index 332ed60ce..000000000 --- a/biometrics/adapters/storage_adapter/StorageAdapter.rc +++ /dev/null @@ -1,29 +0,0 @@ -//--------------------------------------------------------------------------- -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// -// Copyright (c) 2007 Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - - -#include -#include -#include "resource.h" - -// -// TODO: Change the file description and file names to match your binary. -// - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT_UNKNOWN -#define VER_FILEDESCRIPTION_STR "Storage Adapter Sample" -#define VER_INTERNALNAME_STR "StorageAdapter" -#define VER_ORIGINALFILENAME_STR "StorageAdapter.dll" - -#include "common.ver" diff --git a/biometrics/adapters/storage_adapter/StorageAdapter.vcxproj b/biometrics/adapters/storage_adapter/StorageAdapter.vcxproj deleted file mode 100644 index d9b4caf00..000000000 --- a/biometrics/adapters/storage_adapter/StorageAdapter.vcxproj +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {339A0554-2E3D-4A12-B45C-8E2D7D59D7C2} - $(MSBuildProjectName) - false - true - Debug - Win32 - {A09D774C-A1A4-4648-8599-3905585E696B} - - - - Windows10 - False - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - False - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - Windows10 - True - Desktop - - WindowsApplicationForDrivers10.0 - DynamicLibrary - - - - $(IntDir) - - - - - - - - - - - - - - - - StorageAdapter - - - StorageAdapter - - - StorageAdapter - - - StorageAdapter - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - StorageAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - StorageAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - StorageAdapter.def - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(AdditionalDependencies);advapi32.lib;kernel32.lib;user32.lib - StorageAdapter.def - - - - - ;%(AdditionalIncludeDirectories) - precomp.h - Create - $(IntDir)\precomp.h.pch - - - ;%(AdditionalIncludeDirectories) - precomp.h - Use - $(IntDir)\precomp.h.pch - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/biometrics/adapters/storage_adapter/StorageAdapter.vcxproj.Filters b/biometrics/adapters/storage_adapter/StorageAdapter.vcxproj.Filters deleted file mode 100644 index 928764979..000000000 --- a/biometrics/adapters/storage_adapter/StorageAdapter.vcxproj.Filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* - {EE3BFC89-6F03-422C-B8F1-B4F4764C10BB} - - - h;hpp;hxx;hm;inl;inc;xsd - {C5BD080B-5F54-4E1D-A8EB-7CD4F15F93CA} - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml - {105F62EC-5AF7-4EA7-BC5B-07BBDD5C3611} - - - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/biometrics/adapters/storage_adapter/precomp.h b/biometrics/adapters/storage_adapter/precomp.h deleted file mode 100644 index c36eb36cd..000000000 --- a/biometrics/adapters/storage_adapter/precomp.h +++ /dev/null @@ -1,62 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - precomp.h - -Abstract: - - This module contains identifies all the headers that - shoulde be pre-compiled. - -Author: - - - - -Environment: - - Win32, user mode only. - -Revision History: - -NOTES: - - (None) - ---*/ -#pragma once - -// -// Necessary for compiling under VC. -// -#if(!defined(WINVER) || (WINVER < 0x0500)) - #undef WINVER - #define WINVER 0x0500 -#endif -#if(!defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)) - #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0500 -#endif - -// -// Required header files that shouldn't change often. -// -#include -#include -#include - -// -// StrSafe.h needs to be included last -// to disallow unsafe string functions. -#include - -#ifndef ARGUMENT_PRESENT -#define ARGUMENT_PRESENT(x) ((x) != NULL) -#endif diff --git a/biometrics/adapters/storage_adapter/precompsrc.cpp b/biometrics/adapters/storage_adapter/precompsrc.cpp deleted file mode 100644 index 5944cf515..000000000 --- a/biometrics/adapters/storage_adapter/precompsrc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "precomp.h" \ No newline at end of file diff --git a/biometrics/adapters/storage_adapter/resource.h b/biometrics/adapters/storage_adapter/resource.h deleted file mode 100644 index 95ed37fa6..000000000 --- a/biometrics/adapters/storage_adapter/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//--------------------------------------------------------------------------- -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// -// Copyright (c) 2007 Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - -#pragma once - diff --git a/biometrics/driver/BioUsbSample.ctl b/biometrics/driver/BioUsbSample.ctl deleted file mode 100644 index bcec77c14..000000000 --- a/biometrics/driver/BioUsbSample.ctl +++ /dev/null @@ -1 +0,0 @@ -864936A6-DB79-451e-B764-E720D61A9361 WudfBioUsbSampleTraceGuid \ No newline at end of file diff --git a/biometrics/driver/BioUsbSample.rc b/biometrics/driver/BioUsbSample.rc deleted file mode 100644 index 36f83c5a6..000000000 --- a/biometrics/driver/BioUsbSample.rc +++ /dev/null @@ -1,26 +0,0 @@ -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A -// PARTICULAR PURPOSE. -// -// Copyright (c) Microsoft Corporation. All rights reserved -// -// BioUsbSample.rc -// - - -#include -#include -#include "resource.h" - -// -// TODO: Change the file description and file names to match your binary. -// - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT_UNKNOWN -#define VER_FILEDESCRIPTION_STR "WUDF: Biometric Sample" -#define VER_INTERNALNAME_STR "WudfBioUsbSample" -#define VER_ORIGINALFILENAME_STR "WudfBioUsbSample.dll" - -#include "common.ver" diff --git a/biometrics/driver/Device.cpp b/biometrics/driver/Device.cpp deleted file mode 100644 index 8f8dd6b45..000000000 --- a/biometrics/driver/Device.cpp +++ /dev/null @@ -1,1834 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Device.cpp - -Abstract: - - This module contains the implementation of the Biometric - device driver. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ -#include "internal.h" -#include "device.tmh" - -#pragma warning(disable : 4189) - -DWORD WINAPI -CaptureSleepThread( - LPVOID lpParam - ) -{ - CBiometricDevice *device = (CBiometricDevice *) lpParam; - PCAPTURE_SLEEP_PARAMS sleepParams = device->GetCaptureSleepParams(); - - // - // Make sure it is less than or equal to 1 minute. - // - if (sleepParams->SleepValue > 60) - { - sleepParams->SleepValue = 60; - } - - Sleep(sleepParams->SleepValue * 1000); - - device->CompletePendingRequest(sleepParams->Hr, sleepParams->Information); - - return 0; -} - - -HRESULT -CBiometricDevice::CreateInstanceAndInitialize( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize * FxDeviceInit, - _Out_ CBiometricDevice **Device - ) -/*++ - - Routine Description: - - This method creates and initializs an instance of the skeleton driver's - device callback object. - - Arguments: - - FxDeviceInit - the settings for the device. - - Device - a location to store the referenced pointer to the device object. - - Return Value: - - Status - ---*/ -{ - // - // Create a new instance of the device class - // - CComObject *pMyDevice = NULL; - HRESULT hr = CComObject::CreateInstance( &pMyDevice ); - - if (SUCCEEDED(hr)) - { - - // - // Initialize the instance. This calls the WUDF framework, - // which keeps a reference to the device interface for the lifespan - // of the device. - // - if (NULL != pMyDevice) - { - hr = pMyDevice->Initialize(FxDriver, FxDeviceInit); - - if (FAILED(hr)) - { - BiometricSafeRelease(pMyDevice); - } - - } - - *Device = pMyDevice; - - } - - return hr; -} - -HRESULT -CBiometricDevice::Initialize( - _In_ IWDFDriver * FxDriver, - _In_ IWDFDeviceInitialize * FxDeviceInit - ) -/*++ - - Routine Description: - - This method initializes the device callback object and creates the - partner device object. - - The method should perform any device-specific configuration that: - * could fail (these can't be done in the constructor) - * must be done before the partner object is created -or- - * can be done after the partner object is created and which aren't - influenced by any device-level parameters the parent (the driver - in this case) might set. - - Arguments: - - FxDeviceInit - the settings for this device. - - Return Value: - - status. - ---*/ -{ - IWDFDevice *fxDevice = NULL; - HRESULT hr = S_OK; - IUnknown *unknown = NULL; - - // - // Configure things like the locking model before we go to create our - // partner device. - // - - // - // Set the locking model. - // - - FxDeviceInit->SetLockingConstraint(WdfDeviceLevel); - - // - // Any per-device initialization which must be done before - // creating the partner object. - // - - // - // Create a new FX device object and assign the new callback object to - // handle any device level events that occur. - // - - // - // We pass an IUnknown reference to CreateDevice, which takes its own - // reference if everything works. - // - - if (SUCCEEDED(hr)) - { - hr = this->QueryInterface(__uuidof(IUnknown), (void **)&unknown); - - } - - if (SUCCEEDED(hr)) - { - - hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &fxDevice); - BiometricSafeRelease(unknown); - } - - // - // If that succeeded then set our FxDevice member variable. - // - - if (SUCCEEDED(hr)) - { - m_FxDevice = fxDevice; - - // - // Drop the reference we got from CreateDevice. Since this object - // is partnered with the framework object they have the same - // lifespan - there is no need for an additional reference. - // - - BiometricSafeRelease(fxDevice); - } - - return hr; -} - -HRESULT -CBiometricDevice::Configure( - VOID - ) -/*++ - - Routine Description: - - This method is called after the device callback object has been initialized - and returned to the driver. It would setup the device's queues and their - corresponding callback objects. - - Arguments: - - FxDevice - the framework device object for which we're handling events. - - Return Value: - - status - ---*/ -{ - - HRESULT hr = S_OK; - - // - // Create the I/O queue - // - - if (SUCCEEDED(hr)) - { - hr = CBiometricIoQueue::CreateInstanceAndInitialize(m_FxDevice, this, &m_IoQueue); - - if (SUCCEEDED(hr)) - { - hr = m_IoQueue->Configure(); - } - } - - // - // Create Device Interface - // - - if (SUCCEEDED(hr)) - { - hr = m_FxDevice->CreateDeviceInterface(&GUID_DEVINTERFACE_BIOMETRIC_READER, - NULL); - } - - if (SUCCEEDED(hr)) - { - hr = m_FxDevice->AssignDeviceInterfaceState(&GUID_DEVINTERFACE_BIOMETRIC_READER, - NULL, - TRUE); - } - - // - // TODO - this is where additional interfaces can be exposed. - // - - return hr; -} - -HRESULT -CBiometricDevice::OnPrepareHardware( - _In_ IWDFDevice * /* FxDevice */ - ) -/*++ - -Routine Description: - - This routine is invoked to ready the driver - to talk to hardware. It opens the handle to the - device and talks to it using the WINUSB interface. - It invokes WINUSB to discver the interfaces and stores - the information related to bulk endpoints. - -Arguments: - - FxDevice : Pointer to the WDF device interface - -Return Value: - - HRESULT - ---*/ -{ - PWSTR deviceName = NULL; - DWORD deviceNameCch = 0; - - HRESULT hr; - - // - // Get the device name. - // Get the length to allocate first - // - - hr = m_FxDevice->RetrieveDeviceName(NULL, &deviceNameCch); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get device name %!hresult!", - hr - ); - } - - // - // Allocate the buffer - // - - if (SUCCEEDED(hr)) - { - deviceName = (PWSTR) malloc(deviceNameCch * sizeof (WCHAR)); - - if (deviceName == NULL) - { - hr = E_OUTOFMEMORY; - } - } - - // - // Get the actual name - // - - if (SUCCEEDED(hr)) - { - hr = m_FxDevice->RetrieveDeviceName(deviceName, &deviceNameCch); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get device name %!hresult!", - hr - ); - } - } - - if (SUCCEEDED(hr)) - { - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Device name %S", - deviceName - ); - } - - // - // Create USB I/O Targets and configure them - // - - if (SUCCEEDED(hr)) - { - hr = CreateUsbIoTargets(); - } - - if (SUCCEEDED(hr)) - { - ULONG length = sizeof(m_Speed); - - hr = m_pIUsbTargetDevice->RetrieveDeviceInformation(DEVICE_SPEED, - &length, - &m_Speed); - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get usb device speed information %!HRESULT!", - hr - ); - } - } - - if (SUCCEEDED(hr)) - { - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Speed - %x\n", - m_Speed - ); - } - - // - // Setup power-management settings on the device. - // - - if (SUCCEEDED(hr)) - { - hr = SetPowerManagement(); - } - - // - // We have non-power managed queues so we Stop them in OnReleaseHardware - // and start them in OnPrepareHardware - // - - if (SUCCEEDED(hr)) - { - m_IoQueue->Start(); - } - - if (SUCCEEDED(hr)) - { - // - // If the device stack allows read to remain pending across power-down - // and up, it can be initiated during OnPrepareHardware - // - // If the device stack doesn't allow the read to remain pending (i.e. it - // cancels the pending read during power transition) driver will have to - // stop sending pending read during D0Exit and re-initiate it during - // D0Entry - // - // USB core actually doesn't allow read to remain pending across power - // transition but WinUSB does. Since we are layered above WinUSB we don't - // need to manage pending read across power transitions. - // - - hr = InitiatePendingRead(); - } - - if (deviceName) - { - free(deviceName); - deviceName = NULL; - } - - return hr; -} - -HRESULT -CBiometricDevice::OnReleaseHardware( - _In_ IWDFDevice * /* FxDevice */ - ) -/*++ - -Routine Description: - - This routine is invoked when the device is being removed or stopped - It releases all resources allocated for this device. - -Arguments: - - FxDevice - Pointer to the Device object. - -Return Value: - - HRESULT - Always succeeds. - ---*/ -{ - // - // Cancel the pending data collection I/O, if one exists. - // - CompletePendingRequest(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0); - - // - // Since we have non-power managed queues, we need to Stop them - // explicitly - // - // We need to stop them before deleting I/O targets otherwise we - // will continue to get I/O and our I/O processing will try to access - // freed I/O targets - // - // We initialize queues in CMyDevice::Initialize so we can't get - // here with queues being NULL and don't need to guard against that - // - - m_IoQueue->StopSynchronously(); - - // - // Delete USB Target Device WDF Object, this will in turn - // delete all the children - interface and the pipe objects - // - // This makes sure that - // 1. We drain the I/O before releasing the targets - // a. We always need to do that for the pending read which does - // not come from an I/O queue - // b. We need to do this even for I/O coming from I/O queues because - // we set them to non-power managed queues (to leverage wait/wake - // from WinUsb.sys) - // 2. We remove USB target objects from object tree (and thereby free them) - // before any potential subsequent OnPrepareHardware creates new ones - // - // m_pIUsbTargetDevice could be NULL if OnPrepareHardware failed so we need - // to guard against that - // - - if (m_pIUsbTargetDevice) - { - m_pIUsbTargetDevice->DeleteWdfObject(); - } - - // - // This sample has a thread that will sleep for 5 seconds before - // completing a capture request. - // - if (m_SleepThread != INVALID_HANDLE_VALUE) - { - WaitForSingleObject(m_SleepThread, INFINITE); - CloseHandle(m_SleepThread); - m_SleepThread = INVALID_HANDLE_VALUE; - } - - return S_OK; -} - -HRESULT -CBiometricDevice::CreateUsbIoTargets( - ) -/*++ - -Routine Description: - - This routine creates Usb device, interface and pipe objects - -Arguments: - - None - -Return Value: - - HRESULT ---*/ -{ - HRESULT hr; - UCHAR NumEndPoints = 0; - IWDFUsbTargetFactory * pIUsbTargetFactory = NULL; - IWDFUsbTargetDevice * pIUsbTargetDevice = NULL; - IWDFUsbInterface * pIUsbInterface = NULL; - IWDFUsbTargetPipe * pIUsbPipe = NULL; - - hr = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pIUsbTargetFactory)); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get usb target factory %!HRESULT!", - hr - ); - } - - if (SUCCEEDED(hr)) - { - hr = pIUsbTargetFactory->CreateUsbTargetDevice( - &pIUsbTargetDevice); - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to create USB Device I/O Target %!HRESULT!", - hr - ); - } - else - { - m_pIUsbTargetDevice = pIUsbTargetDevice; - - // - // Release the creation reference as object tree will maintain a reference - // - - BiometricSafeRelease(pIUsbTargetDevice); - } - } - - if (SUCCEEDED(hr)) - { - UCHAR NumInterfaces = pIUsbTargetDevice->GetNumInterfaces(); - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Found %u interfaces", - NumInterfaces - ); - - hr = pIUsbTargetDevice->RetrieveUsbInterface(0, &pIUsbInterface); - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to retrieve USB interface from USB Device I/O Target %!HRESULT!", - hr - ); - } - else - { - m_pIUsbInterface = pIUsbInterface; - - BiometricSafeRelease(pIUsbInterface); // release creation reference - } - } - - if (SUCCEEDED(hr)) - { - NumEndPoints = pIUsbInterface->GetNumEndPoints(); - - if (NumEndPoints != NUM_WBDI_ENDPOINTS) - { - hr = E_UNEXPECTED; - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Has %d endpoints, expected %d, returning %!HRESULT! ", - NumEndPoints, - NUM_WBDI_ENDPOINTS, - hr - ); - } - } - - if (SUCCEEDED(hr)) - { - for (UCHAR PipeIndex = 0; PipeIndex < NumEndPoints; PipeIndex++) - { - hr = pIUsbInterface->RetrieveUsbPipeObject(PipeIndex, - &pIUsbPipe); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to retrieve USB Pipe for PipeIndex %d, %!HRESULT!", - PipeIndex, - hr - ); - } - else - { - if ( pIUsbPipe->IsInEndPoint() ) - { - if ( UsbdPipeTypeInterrupt == pIUsbPipe->GetType() ) - { - m_pIUsbInterruptPipe = pIUsbPipe; - } - else if ( UsbdPipeTypeBulk == pIUsbPipe->GetType() ) - { - m_pIUsbInputPipe = pIUsbPipe; - } - else - { - pIUsbPipe->DeleteWdfObject(); - } - } - else if ( pIUsbPipe->IsOutEndPoint() && (UsbdPipeTypeBulk == pIUsbPipe->GetType()) ) - { - m_pIUsbOutputPipe = pIUsbPipe; - } - else - { - pIUsbPipe->DeleteWdfObject(); - } - - BiometricSafeRelease(pIUsbPipe); //release creation reference - } - } - - if (NULL == m_pIUsbInputPipe || NULL == m_pIUsbOutputPipe) - { - hr = E_UNEXPECTED; - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Input or output pipe not found, returning %!HRESULT!", - hr - ); - } - } - - BiometricSafeRelease(pIUsbTargetFactory); - - return hr; -} - -HRESULT -CBiometricDevice::SetPowerManagement( - VOID - ) -/*++ - - Routine Description: - - This method enables the WinUSB driver to power the device down when it is - idle. - - Arguments: - - None - - Return Value: - - Status - ---*/ -{ - - HRESULT hr = S_OK; - ULONG value = WBDI_SUSPEND_DELAY; - - hr = m_pIUsbTargetDevice->SetPowerPolicy( SUSPEND_DELAY, - sizeof(ULONG), - (PVOID) &value ); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to set power policy (SUSPEND_DELAY) for the device %!HRESULT!", - hr - ); - } - - - // - // Finally enable auto-suspend. - // - - if (SUCCEEDED(hr)) - { - BOOL AutoSuspsend = TRUE; - - hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND, - sizeof(BOOL), - (PVOID) &AutoSuspsend ); - } - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to set power policy (AUTO_SUSPEND) for the device %!HRESULT!", - hr - ); - } - - return hr; -} - -HRESULT -CBiometricDevice::SendControlTransferSynchronously( - _In_ PWINUSB_SETUP_PACKET SetupPacket, - _Inout_updates_(BufferLength) PBYTE Buffer, - _In_ ULONG BufferLength, - _Out_ PULONG LengthTransferred - ) -/*++ - - Routine Description: - - This method synchronously sends a control transfer request to - the USB I/O target. - - Arguments: - - SetupPacket - The command parameter structure - - Buffer - The data to transfer - - BufferLength - The size of the data buffer to transfer - - LengthTransferred - Contains the actual number of bytes transferred. - - Return Value: - - HRESULT - ---*/ -{ - HRESULT hr = S_OK; - IWDFIoRequest *pWdfRequest = NULL; - IWDFDriver * FxDriver = NULL; - IWDFMemory * FxMemory = NULL; - IWDFRequestCompletionParams * FxComplParams = NULL; - IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL; - - *LengthTransferred = 0; - - hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface - NULL, //pParentObject - &pWdfRequest); - - if (SUCCEEDED(hr)) - { - m_FxDevice->GetDriver(&FxDriver); - - hr = FxDriver->CreatePreallocatedWdfMemory( Buffer, - BufferLength, - NULL, //pCallbackInterface - pWdfRequest, //pParetObject - &FxMemory ); - } - - if (SUCCEEDED(hr)) - { - hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest, - SetupPacket, - FxMemory, - NULL); //TransferOffset - } - - if (SUCCEEDED(hr)) - { - hr = pWdfRequest->Send( m_pIUsbTargetDevice, - WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - 0); //Timeout - } - - if (SUCCEEDED(hr)) - { - pWdfRequest->GetCompletionParams(&FxComplParams); - - hr = FxComplParams->GetCompletionStatus(); - } - - if (SUCCEEDED(hr)) - { - HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams)); - if (SUCCEEDED(hrQI)) - { - FxUsbComplParams->GetDeviceControlTransferParameters( NULL, - LengthTransferred, - NULL, - NULL ); - } - } - - BiometricSafeRelease(FxUsbComplParams); - BiometricSafeRelease(FxComplParams); - BiometricSafeRelease(FxMemory); - - pWdfRequest->DeleteWdfObject(); - BiometricSafeRelease(pWdfRequest); - - BiometricSafeRelease(FxDriver); - - return hr; -} - -WDF_IO_TARGET_STATE -CBiometricDevice::GetTargetState( - IWDFIoTarget * pTarget - ) -/*++ - - Routine Description: - - This method gets the state of the I/O target - - Arguments: - - pTarget - A pointer to the I/O target - - Return Value: - - WDF_IO_TARGET_STATE - ---*/ -{ - IWDFIoTargetStateManagement * pStateMgmt = NULL; - WDF_IO_TARGET_STATE state = WdfIoTargetStateUndefined; - - HRESULT hrQI = pTarget->QueryInterface(IID_PPV_ARGS(&pStateMgmt)); - if (FAILED(hrQI)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot query interface %!HRESULT!", - hrQI - ); - - return state; - } - - state = pStateMgmt->GetState(); - - BiometricSafeRelease(pStateMgmt); - - return state; -} - -HRESULT -CBiometricDevice::InitiatePendingRead( - VOID - ) -/*++ - - Routine Description: - - This routine starts up a cycling read on the interrupt pipe. As each - read completes it will start up the next one. - - Arguments: - - None - - Return Value: - - Status - ---*/ -{ - HRESULT hr = S_OK; - IWDFIoRequest * FxRequest = NULL; - IWDFMemory * FxMemory = NULL; - IWDFDriver * FxDriver = NULL; - IRequestCallbackRequestCompletion * FxComplCallback = NULL; - - hr = m_FxDevice->CreateRequest(NULL, NULL, &FxRequest); - - if (SUCCEEDED(hr)) - { - m_FxDevice->GetDriver(&FxDriver); - - hr = FxDriver->CreatePreallocatedWdfMemory( (PBYTE) &m_InterruptMessage, - sizeof(m_InterruptMessage), - NULL, //pCallbackInterface - FxRequest, //pParetObject - &FxMemory ); - } - - if (SUCCEEDED(hr)) - { - hr = m_pIUsbInterruptPipe->FormatRequestForRead(FxRequest, - NULL, //pFile - IoTarget would apply its file - FxMemory, - NULL, //Memory offset - NULL); //Device offset - } - - if (SUCCEEDED(hr)) - { - hr = this->QueryInterface(IID_PPV_ARGS(&FxComplCallback)); - if (SUCCEEDED(hr)) - { - FxRequest->SetCompletionCallback(FxComplCallback, NULL); - - hr = FxRequest->Send(m_pIUsbInterruptPipe, 0, 0); - } - } - - if (FAILED(hr)) - { - m_InterruptReadProblem = hr; - - if (FxRequest) - { - FxRequest->DeleteWdfObject(); - } - } - - BiometricSafeRelease(FxRequest); - BiometricSafeRelease(FxMemory); - BiometricSafeRelease(FxDriver); - BiometricSafeRelease(FxComplCallback); - - return hr; -} - -VOID -CBiometricDevice::OnCompletion( - _In_ IWDFIoRequest* FxRequest, - _In_ IWDFIoTarget* pIoTarget, - _In_ IWDFRequestCompletionParams* pParams, - _In_ PVOID pContext - ) -/*++ - - Routine Description: - - This method is called when the asynchronous pending - read on the interrupt pipe completes. - - Arguments: - - FxRequest - The request object - - pIoTarget - The I/O target for the request - - pParams - The completion parameters - - pContext - Optional context - - Return Value: - - None - ---*/ -{ - UNREFERENCED_PARAMETER(pIoTarget); - UNREFERENCED_PARAMETER(pContext); - - IWDFUsbRequestCompletionParams * pUsbComplParams = NULL; - IWDFMemory * FxMemory = NULL; - SIZE_T bytesRead = 0; - HRESULT hrCompletion = pParams->GetCompletionStatus(); - - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Pending read completed with %!hresult!", - hrCompletion - ); - - if (FAILED(hrCompletion)) - { - m_InterruptReadProblem = hrCompletion; - } - else - { - // - // Get the interrupt message - // - - HRESULT hrQI = pParams->QueryInterface(IID_PPV_ARGS(&pUsbComplParams)); - if (SUCCEEDED(hrQI)) - { - pUsbComplParams->GetPipeReadParameters(&FxMemory, &bytesRead, NULL); - if (bytesRead == sizeof(INTERRUPT_MESSAGE)) - { - - PVOID pBuff = FxMemory->GetDataBuffer(NULL); - CopyMemory(&m_InterruptMessage, pBuff, sizeof(m_InterruptMessage)); - - // - // TODO: Parse m_InterruptMessage - // - } - } - } - - // - // Don't complete the request since we created it, just delete it. - // - - FxRequest->DeleteWdfObject(); - - // - // Re-initiate pending read if I/O Target is not stopped/removed - // - - if (WdfIoTargetStarted == GetTargetState(m_pIUsbInterruptPipe)) - { - int numRetries = 0; - HRESULT hr = InitiatePendingRead(); - - // - // If we fail here, the device will become unresponsive. - // Re-issue the request until it succeeds. - // - for (numRetries = 0; FAILED(hr) && numRetries < 3; ++numRetries) - { - hr = InitiatePendingRead(); - } - } - - BiometricSafeRelease(pUsbComplParams); - BiometricSafeRelease(FxMemory); -} - - -// -// I/O handlers -// - -void -CBiometricDevice::GetIoRequestParams( - _In_ IWDFIoRequest *FxRequest, - _Out_ ULONG *MajorControlCode, - _Outptr_result_bytebuffer_(*InputBufferSizeInBytes) PUCHAR *InputBuffer, - _Out_ SIZE_T *InputBufferSizeInBytes, - _Outptr_result_bytebuffer_(*OutputBufferSizeInBytes) PUCHAR *OutputBuffer, - _Out_ SIZE_T *OutputBufferSizeInBytes - ) -/*++ - - Routine Description: - - This method retrieves the input and output buffers associated with the request. - - Arguments: - - FxRequest - The WDF request oject - - MajorControlCode - Contains the control code for the I/O request - - InputBuffer - Contains the input buffer pointer - - InputBufferSizeInBytes - Contains the size of the input buffer - - OutputBuffer - Contains the output buffer pointer - - OutputBufferSizeInBytes - Contains the size of the output buffer - - Return Value: - - None - ---*/ -{ - // - // Get main parameters - // - FxRequest->GetDeviceIoControlParameters(MajorControlCode, - InputBufferSizeInBytes, - OutputBufferSizeInBytes); - - // Get pointer to input buffer - IWDFMemory *fxMemory = NULL; - FxRequest->GetInputMemory(&fxMemory); - if (fxMemory) - { - *InputBuffer = (PUCHAR) fxMemory->GetDataBuffer(InputBufferSizeInBytes); - BiometricSafeRelease(fxMemory); - } - - // Save pointer to reply buffer - fxMemory = NULL; - FxRequest->GetOutputMemory(&fxMemory); - if (fxMemory) - { - *OutputBuffer = (PUCHAR) fxMemory->GetDataBuffer(OutputBufferSizeInBytes); - BiometricSafeRelease(fxMemory); - } -} - -void -CBiometricDevice::OnGetAttributes( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_ATTRIBUTES command is called. - - Arguments: - - FxRequest - The output for this request is a PWINBIO_SENSOR_ATTRIBUTES. - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_SENSOR_ATTRIBUTES sensorAttributes = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&sensorAttributes, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (sensorAttributes == NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - // We only have one supported format, so sizeof (WINBIO_SENSOR_ATTRIBUTES) is sufficient. - if (outputBufferSize < sizeof(WINBIO_SENSOR_ATTRIBUTES)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_SENSOR_ATTRIBUTES)); - sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // Fill in the attribute payload structure - // - RtlZeroMemory(sensorAttributes, outputBufferSize); - sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES); - sensorAttributes->WinBioHresult = S_OK; - sensorAttributes->WinBioVersion.MajorVersion = WINBIO_WBDI_MAJOR_VERSION; - sensorAttributes->WinBioVersion.MinorVersion = WINBIO_WBDI_MINOR_VERSION; - sensorAttributes->SensorType = WINBIO_TYPE_FINGERPRINT; - sensorAttributes->SensorSubType = WINBIO_FP_SENSOR_SUBTYPE_SWIPE; - sensorAttributes->Capabilities = WINBIO_CAPABILITY_SENSOR; - sensorAttributes->SupportedFormatEntries = 1; - sensorAttributes->SupportedFormat[0].Owner = WINBIO_ANSI_381_FORMAT_OWNER; - sensorAttributes->SupportedFormat[0].Type= WINBIO_ANSI_381_FORMAT_TYPE; - RtlCopyMemory(sensorAttributes->ManufacturerName, SAMPLE_MANUFACTURER_NAME, (wcslen(SAMPLE_MANUFACTURER_NAME)+1)*sizeof(WCHAR)); - RtlCopyMemory(sensorAttributes->ModelName, SAMPLE_MODEL_NAME, (wcslen(SAMPLE_MODEL_NAME)+1)*sizeof(WCHAR)); - RtlCopyMemory(sensorAttributes->SerialNumber, SAMPLE_SERIAL_NUMBER, (wcslen(SAMPLE_SERIAL_NUMBER)+1)*sizeof(WCHAR)); - sensorAttributes->FirmwareVersion.MajorVersion = 1; - sensorAttributes->FirmwareVersion.MinorVersion = 0; - - MyRequest.SetInformation(sensorAttributes->PayloadSize); - MyRequest.SetCompletionHr(S_OK); -} - - -void -CBiometricDevice::OnReset( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_RESET command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_BLANK_PAYLOAD blankPayload = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&blankPayload, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (blankPayload== NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - if (outputBufferSize < sizeof(WINBIO_BLANK_PAYLOAD)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS)); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // This is a simulated device. Nothing to do here except cancel the pending data - // collection I/O, if one exists. - // - CompletePendingRequest(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0); - - // - // Fill in the OUT payload structure - // - RtlZeroMemory(blankPayload, outputBufferSize); - blankPayload->PayloadSize = (DWORD) sizeof(WINBIO_BLANK_PAYLOAD); - blankPayload->WinBioHresult = S_OK; - - FxRequest->SetInformation(blankPayload->PayloadSize); - MyRequest.SetCompletionHr(S_OK); - -} - -void -CBiometricDevice::OnCalibrate( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_CALIBRATE command is called. - - Arguments: - - FxRequest - - IN - blank payload - OUT - PWINBIO_CALIBRATION_INFO - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_CALIBRATION_INFO calibrationInfo = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&calibrationInfo, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (calibrationInfo == NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - if (outputBufferSize < sizeof(WINBIO_CALIBRATION_INFO)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS)); - calibrationInfo->PayloadSize = (DWORD) sizeof(WINBIO_CALIBRATION_INFO); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // This is where code to calibrate the device goes. - // - - // - // Fill in the OUT payload structure - // - RtlZeroMemory(calibrationInfo, outputBufferSize); - calibrationInfo->PayloadSize = (DWORD) sizeof(WINBIO_CALIBRATION_INFO); - calibrationInfo->WinBioHresult = S_OK; - - MyRequest.SetInformation(calibrationInfo->PayloadSize); - MyRequest.SetCompletionHr(S_OK); -} - - -void -CBiometricDevice::OnGetSensorStatus( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_SENSOR_STATUS command is called. - - Arguments: - - FxRequest - - IN payload: none - OUT payload: PWINBIO_DIAGNOSTICS - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_DIAGNOSTICS diagnostics = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&diagnostics, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (diagnostics == NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - if (outputBufferSize < sizeof(WINBIO_DIAGNOSTICS)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS)); - diagnostics->PayloadSize = (DWORD) sizeof(WINBIO_DIAGNOSTICS); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // Fill in the OUT payload structure - // - RtlZeroMemory(diagnostics, outputBufferSize); - diagnostics->PayloadSize = (DWORD) sizeof(WINBIO_DIAGNOSTICS); - diagnostics->WinBioHresult = S_OK; - diagnostics->SensorStatus = WINBIO_SENSOR_READY; - - MyRequest.SetInformation(diagnostics->PayloadSize); - MyRequest.SetCompletionHr(S_OK); -} - - -void -CBiometricDevice::OnCaptureData( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_CAPTURE_DATA command is called. - - Arguments: - - FxRequest - - IN payload: PWINBIO_CAPTURE_PARAMETERS - OUT payload: PWINBIO_CAPTURE_DATA - - Return Value: - - None - ---*/ -{ - ULONG controlCode = 0; - PWINBIO_CAPTURE_PARAMETERS captureParams = NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_CAPTURE_DATA captureData = NULL; - SIZE_T outputBufferSize = 0; - - // - // We can only have one outstanding data capture request at a time. - // Check to see if we have a request pending. - // - bool requestPending = false; - - EnterCriticalSection(&m_RequestLock); - - if (m_PendingRequest == NULL) - { - // - // See if we have an active sleep thread. - // If so, tell it to exit. - // Wait for it to exit. - // - if (m_SleepThread != INVALID_HANDLE_VALUE) - { - LeaveCriticalSection(&m_RequestLock); - - // TODO: Add code to signal thread to exit. - - // NOTE: Sleeping for INFINITE time is dangerous. A real driver - // should be able to handle the case where the thread does - // not exit. - WaitForSingleObject(m_SleepThread, INFINITE); - CloseHandle(m_SleepThread); - m_SleepThread = INVALID_HANDLE_VALUE; - - EnterCriticalSection(&m_RequestLock); - } - - // - // We might have had to leave the CS to wait for the sleep thread. - // Double check that the pending request is still NULL. - // - if (m_PendingRequest == NULL) - { - // Save the request. - m_PendingRequest = FxRequest; - - // Mark the request as cancellable. - m_PendingRequest->MarkCancelable(this); - } - else - { - requestPending = true; - } - - } - else - { - requestPending = true; - } - - LeaveCriticalSection(&m_RequestLock); - - if (requestPending) - { - // Complete the request to tell the app that there is already - // a pending data collection request. - FxRequest->Complete(WINBIO_E_DATA_COLLECTION_IN_PROGRESS); - return; - } - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - (PUCHAR *)&captureParams, - &inputBufferSize, - (PUCHAR *)&captureData, - &outputBufferSize); - - // - // Check input parameters. - // - if (inputBufferSize < sizeof (WINBIO_CAPTURE_PARAMETERS)) - { - // Invalid arguments - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Invalid argument(s)."); - CompletePendingRequest(E_INVALIDARG, 0); - return; - } - - // - // Make sure we have an output buffer big enough - // - if (outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - CompletePendingRequest(E_INVALIDARG, 0); - return; - } - - // - // Check output buffer size. - // - if (outputBufferSize < sizeof (WINBIO_CAPTURE_DATA)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - must be at least 0x%x.", sizeof (WINBIO_CAPTURE_DATA)); - // - // NOTE: The output buffer size necessary for this sample is sizeof(WINBIO_CAPTURE_DATA). - // Real devices will need additional space to handle a typical capture. - // The value that should be returned here is sizeof(WINBIO_CAPTURE_DATA) + CaptureBufferSize. - // - captureData->PayloadSize = (DWORD) sizeof(WINBIO_CAPTURE_DATA); - CompletePendingRequest(S_OK, sizeof(DWORD)); - return; - } - - // - // NOTE: This call always fails in this sample since it is not - // written for a real device. - // - - // - // Set default values in output buffer. - // - captureData->PayloadSize = (DWORD) sizeof (WINBIO_CAPTURE_DATA); - captureData->WinBioHresult = WINBIO_E_NO_CAPTURE_DATA; - captureData->SensorStatus = WINBIO_SENSOR_FAILURE; - captureData->RejectDetail= 0; - captureData->CaptureData.Size = 0; - - // - // Check purpose, format and type. - // - if (captureParams->Purpose == WINBIO_NO_PURPOSE_AVAILABLE) - { - captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_PURPOSE; - } - else if ((captureParams->Format.Type != WINBIO_ANSI_381_FORMAT_TYPE) || - (captureParams->Format.Owner != WINBIO_ANSI_381_FORMAT_OWNER)) - { - captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_FORMAT; - } - else if (captureParams->Flags != WINBIO_DATA_FLAG_RAW) - { - captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_TYPE; - } - - // - // NOTE: This sample completes the request after - // sleeping for 5 seconds. A real driver would - // program the device for capture mode, and then - // return from this callback. The request would - // remain pending until cancelled, or until the - // driver detects a capture is complete. - // - // The construct of m_PendingRequest will allow - // a driver to have only one pending request at any - // time, which can be cancelled in a Reset IOCTL, or - // by calling CancelIoEx. - // - - // - // Create thread to sleep 5 seconds before completing the request. - // - m_SleepParams.SleepValue = 5; - m_SleepParams.Hr = S_OK; - m_SleepParams.Information = captureData->PayloadSize; - m_SleepThread = CreateThread(NULL, // default security attributes - 0, // use default stack size - CaptureSleepThread, // thread function name - this, // argument to thread function - 0, // use default creation flags - NULL); // returns the thread identifier -} - - -void -CBiometricDevice::OnUpdateFirmware( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_UPDATE_FIRMWARE command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - -void -CBiometricDevice::OnGetSupportedAlgorithms( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_SUPPORTED_ALGORITHMS command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - -void -CBiometricDevice::OnGetIndicator( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_INDICATOR command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - - -void -CBiometricDevice::OnSetIndicator( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_SET_INDICATOR command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - -void -CBiometricDevice::OnControlUnit( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_CONTROL_UNIT command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - - -VOID -CBiometricDevice::CompletePendingRequest( - HRESULT hr, - DWORD information - ) -{ - EnterCriticalSection(&m_RequestLock); - - if (m_PendingRequest) - { - // - // Only complete the request if we weren't cancelled. Otherwise, the - // OnCancel callback will complete the request. - // - HRESULT hrUnmark = m_PendingRequest->UnmarkCancelable(); - if (HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) != hrUnmark) - { - m_PendingRequest->SetInformation(information); - m_PendingRequest->Complete(hr); - m_PendingRequest = NULL; - } - } - - LeaveCriticalSection(&m_RequestLock); -} - -VOID -STDMETHODCALLTYPE -CBiometricDevice::OnCancel( - _In_ IWDFIoRequest *pWdfRequest - ) -{ - EnterCriticalSection(&m_RequestLock); - - if (m_PendingRequest != pWdfRequest) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cancelled request does not match pending request."); - } - - // - // TODO: In a real driver, the device would be reset so that it is no longer in capture mode. - // Add your code to do so here. - // - - if (m_PendingRequest == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Pending request is NULL."); - } - else - { - m_PendingRequest->Complete(HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)); - m_PendingRequest = NULL; - } - - LeaveCriticalSection(&m_RequestLock); -} diff --git a/biometrics/driver/Device.h b/biometrics/driver/Device.h deleted file mode 100644 index 690943255..000000000 --- a/biometrics/driver/Device.h +++ /dev/null @@ -1,360 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Device.h - -Abstract: - - This module contains the type definitions of the Biometric - device driver. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// TODO: Change this to match your device -// -#define NUM_WBDI_ENDPOINTS 3 - -// -// Power policy suspend delay time. 10 seconds. -// -#define WBDI_SUSPEND_DELAY ((ULONG)(10 * 1000)) - -// -// Struct for passing parameters for capture request completion. -// -typedef struct _CAPTURE_SLEEP_PARAMS -{ - DWORD SleepValue; - HRESULT Hr; - DWORD Information; -} CAPTURE_SLEEP_PARAMS, *PCAPTURE_SLEEP_PARAMS; - - -// -// Class for the Biometric driver. -// - -class CBiometricDevice : - public CComObjectRootEx, - public IRequestCallbackRequestCompletion, - public IRequestCallbackCancel, - public IPnpCallbackHardware -{ -public: - - DECLARE_NOT_AGGREGATABLE(CBiometricDevice) - - BEGIN_COM_MAP(CBiometricDevice) - COM_INTERFACE_ENTRY(IPnpCallbackHardware) - COM_INTERFACE_ENTRY(IRequestCallbackRequestCompletion) - COM_INTERFACE_ENTRY(IRequestCallbackCancel) - END_COM_MAP() - - CBiometricDevice() : - m_FxDevice(NULL), - m_IoQueue(NULL), - m_pIUsbTargetDevice(NULL), - m_pIUsbInterface(NULL), - m_pIUsbInputPipe(NULL), - m_pIUsbOutputPipe(NULL), - m_pIUsbInterruptPipe(NULL), - m_PendingRequest(NULL), - m_Speed(0), - m_InterruptReadProblem(S_OK), - m_SleepThread(INVALID_HANDLE_VALUE) - { - InitializeCriticalSection(&m_RequestLock); - } - - ~CBiometricDevice() - { - DeleteCriticalSection(&m_RequestLock); - } - -// -// Private data members. -// -private: - - // - // Weak reference to framework device object. - // - IWDFDevice * m_FxDevice; - - // - // Weak reference to I/O queue - // - PCBiometricIoQueue m_IoQueue; - - // - // USB Device I/O Target - // - IWDFUsbTargetDevice * m_pIUsbTargetDevice; - - // - // USB Interface - // - IWDFUsbInterface * m_pIUsbInterface; - - // - // USB Input pipe for Reads - // - IWDFUsbTargetPipe * m_pIUsbInputPipe; - - // - // USB Output pipe for writes - // - IWDFUsbTargetPipe * m_pIUsbOutputPipe; - - // - // USB interrupt pipe - // - IWDFUsbTargetPipe * m_pIUsbInterruptPipe; - - // - // Device Speed (Low, Full, High) - // - UCHAR m_Speed; - - // - // If reads stopped because of a transient problem, the error status - // is stored here. - // - - HRESULT m_InterruptReadProblem; - - // - // Interrupt message buffer - // - - INTERRUPT_MESSAGE m_InterruptMessage; - - // - // Holds a reference to a pending data I/O request. - // - - IWDFIoRequest *m_PendingRequest; - - // - // Synchronization for m_PendingRequest - // - - CRITICAL_SECTION m_RequestLock; - - // - // Handle to a thread that will sleep before completing a request. - // - HANDLE m_SleepThread; - CAPTURE_SLEEP_PARAMS m_SleepParams; - -// -// Private methods. -// -private: - - HRESULT - Initialize( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit - ); - - // - // Helper methods - // - - HRESULT - CreateUsbIoTargets( - VOID - ); - - HRESULT - SetPowerManagement( - VOID - ); - - // - // Helper functions - // - - HRESULT - SendControlTransferSynchronously( - _In_ PWINUSB_SETUP_PACKET SetupPacket, - _Inout_updates_(BufferLength) PBYTE Buffer, - _In_ ULONG BufferLength, - _Out_ PULONG LengthTransferred - ); - - static - WDF_IO_TARGET_STATE - GetTargetState( - IWDFIoTarget * pTarget - ); - - HRESULT - InitiatePendingRead( - ); - -// -// Public methods -// -public: - - // - // The factory method used to create an instance of this driver. - // - - static - HRESULT - CreateInstanceAndInitialize( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit, - _Out_ CBiometricDevice **Device - ); - - HRESULT - Configure( - VOID - ); - -// -// COM methods -// -public: - - // - // IPnpCallbackHardware - // - - virtual - HRESULT - STDMETHODCALLTYPE - OnPrepareHardware( - _In_ IWDFDevice *FxDevice - ); - - virtual - HRESULT - STDMETHODCALLTYPE - OnReleaseHardware( - _In_ IWDFDevice *FxDevice - ); - - - // - // IRequestCallbackRequestCompletion - // - virtual - void - STDMETHODCALLTYPE - OnCompletion( - _In_ IWDFIoRequest* FxRequest, - _In_ IWDFIoTarget* pIoTarget, - _In_ IWDFRequestCompletionParams* pParams, - _In_ PVOID pContext - ); - - // - // IRequestCallbackCancel - // - virtual - VOID - STDMETHODCALLTYPE - OnCancel( - _In_ IWDFIoRequest *pWdfRequest - ); - -public: - - // - // I/O handlers. - // - void - GetIoRequestParams( - _In_ IWDFIoRequest *FxRequest, - _Out_ ULONG *MajorControlCode, - _Outptr_result_bytebuffer_(*InputBufferSizeInBytes) PUCHAR *InputBuffer, - _Out_ SIZE_T *InputBufferSizeInBytes, - _Outptr_result_bytebuffer_(*OutputBufferSizeInBytes) PUCHAR *OutputBuffer, - _Out_ SIZE_T *OutputBufferSizeInBytes - ); - - void - OnGetAttributes( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnReset( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnCalibrate( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnGetSensorStatus( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnCaptureData( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnUpdateFirmware( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnGetSupportedAlgorithms( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnGetIndicator( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnSetIndicator( - _Inout_ IWDFIoRequest *FxRequest - ); - - void - OnControlUnit( - _Inout_ IWDFIoRequest *FxRequest - ); - - VOID - CompletePendingRequest( - HRESULT hr, - DWORD information - ); - - inline PCAPTURE_SLEEP_PARAMS - GetCaptureSleepParams() - { - return &m_SleepParams; - } - -}; - - diff --git a/biometrics/driver/Driver.cpp b/biometrics/driver/Driver.cpp deleted file mode 100644 index 0d5c0797f..000000000 --- a/biometrics/driver/Driver.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Driver.cpp - -Abstract: - - This module contains the implementation of the Biometric - core driver callback object. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#include "internal.h" -#include "driver.tmh" - -HRESULT -CBiometricDriver::OnDeviceAdd( - _In_ IWDFDriver *FxWdfDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit - ) -/*++ - - Routine Description: - - The FX invokes this method when it wants to install our driver on a device - stack. This method creates a device callback object, then calls the Fx - to create an Fx device object and associate the new callback object with - it. - - Arguments: - - FxWdfDriver - the Fx driver object. - - FxDeviceInit - the initialization information for the device. - - Return Value: - - status - ---*/ -{ - HRESULT hr = S_OK; - CBiometricDevice *device = NULL; - - // - // Create device callback object - // - - hr = CBiometricDevice::CreateInstanceAndInitialize(FxWdfDriver, - FxDeviceInit, - &device); - - // - // Call the device's construct method. This - // allows the device to create any queues or other structures that it - // needs now that the corresponding fx device object has been created. - // - - if (SUCCEEDED(hr)) - { - hr = device->Configure(); - } - - return hr; -} diff --git a/biometrics/driver/Driver.h b/biometrics/driver/Driver.h deleted file mode 100644 index 0fc2566a9..000000000 --- a/biometrics/driver/Driver.h +++ /dev/null @@ -1,95 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Driver.h - -Abstract: - - This module contains the type definitions for the Biometric - driver callback class. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// This class handles driver events for the skeleton sample. In particular -// it supports the OnDeviceAdd event, which occurs when the driver is called -// to setup per-device handlers for a new device stack. -// - -EXTERN_C const CLSID CLSID_BiometricUsbSample; - -class CBiometricDriver : - public CComObjectRootEx, - public CComCoClass, - public IDriverEntry -{ -public: - - CBiometricDriver() - { - } - - DECLARE_NO_REGISTRY() - - DECLARE_NOT_AGGREGATABLE(CBiometricDriver) - - BEGIN_COM_MAP(CBiometricDriver) - COM_INTERFACE_ENTRY(IDriverEntry) - END_COM_MAP() - -// -// Public methods -// -public: - - // - // IDriverEntry methods - // - - virtual - HRESULT - STDMETHODCALLTYPE - OnInitialize( - _In_ IWDFDriver *FxWdfDriver - ) - { - UNREFERENCED_PARAMETER(FxWdfDriver); - return S_OK; - } - - virtual - HRESULT - STDMETHODCALLTYPE - OnDeviceAdd( - _In_ IWDFDriver *FxWdfDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit - ); - - virtual - VOID - STDMETHODCALLTYPE - OnDeinitialize( - _In_ IWDFDriver *FxWdfDriver - ) - { - UNREFERENCED_PARAMETER(FxWdfDriver); - return; - } - -}; - -OBJECT_ENTRY_AUTO(CLSID_BiometricUsbSample, CBiometricDriver) diff --git a/biometrics/driver/Internalsrc.cpp b/biometrics/driver/Internalsrc.cpp deleted file mode 100644 index 1e8fe6f23..000000000 --- a/biometrics/driver/Internalsrc.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "Internal.h" \ No newline at end of file diff --git a/biometrics/driver/IoQueue.cpp b/biometrics/driver/IoQueue.cpp deleted file mode 100644 index ce8837d92..000000000 --- a/biometrics/driver/IoQueue.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - IoQueue.cpp - -Abstract: - - This file implements the I/O queue interface and performs - the ioctl operations. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#include "internal.h" -#include "ioqueue.tmh" - - -HRESULT -CBiometricIoQueue::CreateInstanceAndInitialize( - _In_ IWDFDevice *FxDevice, - _In_ CBiometricDevice *BiometricDevice, - _Out_ CBiometricIoQueue** Queue - ) -/*++ - -Routine Description: - - CreateInstanceAndInitialize creates an instance of the queue object. - -Arguments: - - -Return Value: - - HRESULT indicating success or failure - ---*/ -{ - // - // Create a new instance of the device class - // - CComObject *pMyQueue = NULL; - HRESULT hr = CComObject::CreateInstance( &pMyQueue ); - - if (SUCCEEDED(hr)) { - - // - // Initialize the instance. - // - - if (NULL != pMyQueue) - { - hr = pMyQueue->Initialize(FxDevice, BiometricDevice); - } - - *Queue = pMyQueue; - - } - - return hr; -} - -HRESULT -CBiometricIoQueue::Initialize( - _In_ IWDFDevice *FxDevice, - _In_ CBiometricDevice *BiometricDevice - ) -/*++ - -Routine Description: - - Initialize creates a framework queue and sets up I/O for the queue object. - -Arguments: - - FxDevice - Framework device associated with this queue. - - BiometricDevice - Pointer to the Biometric device class object. - -Return Value: - - HRESULT indicating success or failure - ---*/ -{ - IWDFIoQueue *fxQueue = NULL; - HRESULT hr = S_OK; - IUnknown *unknown = NULL; - - // - // Make sure we have valid parameters. - // - if (FxDevice == NULL) { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_QUEUE, - "%!FUNC!Pointer to framework device object is NULL."); - return (E_INVALIDARG); - } - if (BiometricDevice == NULL) { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_QUEUE, - "%!FUNC!Pointer to Biometric device is NULL."); - return (E_INVALIDARG); - } - - // - // Create the framework queue - // - - if (SUCCEEDED(hr)) - { - hr = this->QueryInterface(__uuidof(IUnknown), (void **)&unknown); - - } - - if (SUCCEEDED(hr)) - { - hr = FxDevice->CreateIoQueue(unknown, - FALSE, // Default Queue? - WdfIoQueueDispatchParallel, // Dispatch type - FALSE, // Power managed? - FALSE, // Allow zero-length requests? - &fxQueue); // I/O queue - BiometricSafeRelease(unknown); - } - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_QUEUE, - "%!FUNC!Failed to create framework queue."); - return hr; - } - - // - // Configure this queue to filter all Device I/O requests. - // - hr = FxDevice->ConfigureRequestDispatching(fxQueue, - WdfRequestDeviceIoControl, - TRUE); - - if (SUCCEEDED(hr)) - { - m_FxQueue = fxQueue; - m_BiometricDevice= BiometricDevice; - } - - // - // Safe to release here. The framework keeps a reference to the Queue - // for the lifetime of the device. - // - BiometricSafeRelease(fxQueue); - - return hr; -} - -VOID -STDMETHODCALLTYPE -CBiometricIoQueue::OnDeviceIoControl( - _In_ IWDFIoQueue *FxQueue, - _In_ IWDFIoRequest *FxRequest, - _In_ ULONG ControlCode, - _In_ SIZE_T InputBufferSizeInBytes, - _In_ SIZE_T OutputBufferSizeInBytes - ) -/*++ - -Routine Description: - - - DeviceIoControl dispatch routine - -Aruments: - - FxQueue - Framework Queue instance - FxRequest - Framework Request instance - ControlCode - IO Control Code - InputBufferSizeInBytes - Lenth of input buffer - OutputBufferSizeInBytes - Lenth of output buffer - - Always succeeds DeviceIoIoctl -Return Value: - - VOID - ---*/ -{ - UNREFERENCED_PARAMETER(FxQueue); - UNREFERENCED_PARAMETER(InputBufferSizeInBytes); - UNREFERENCED_PARAMETER(OutputBufferSizeInBytes); - - if (m_BiometricDevice == NULL) { - // We don't have pointer to device object - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_QUEUE, - "%!FUNC!NULL pointer to device object."); - FxRequest->Complete(E_POINTER); - return; - } - - // - // Process the IOCTLs - // - - switch (ControlCode) { - - // - // Mandatory IOCTLs - // - case IOCTL_BIOMETRIC_GET_ATTRIBUTES: - m_BiometricDevice->OnGetAttributes(FxRequest); - break; - - case IOCTL_BIOMETRIC_RESET: - m_BiometricDevice->OnReset(FxRequest); - break; - - case IOCTL_BIOMETRIC_CALIBRATE: - m_BiometricDevice->OnCalibrate(FxRequest); - break; - - case IOCTL_BIOMETRIC_GET_SENSOR_STATUS: - m_BiometricDevice->OnGetSensorStatus(FxRequest); - break; - - case IOCTL_BIOMETRIC_CAPTURE_DATA: - m_BiometricDevice->OnCaptureData(FxRequest); - break; - - // - // Optional IOCTLs - // - case IOCTL_BIOMETRIC_UPDATE_FIRMWARE: - m_BiometricDevice->OnUpdateFirmware(FxRequest); - break; - - case IOCTL_BIOMETRIC_GET_SUPPORTED_ALGORITHMS: - m_BiometricDevice->OnGetSupportedAlgorithms(FxRequest); - break; - - case IOCTL_BIOMETRIC_GET_INDICATOR: - m_BiometricDevice->OnGetIndicator(FxRequest); - break; - - case IOCTL_BIOMETRIC_SET_INDICATOR: - m_BiometricDevice->OnSetIndicator(FxRequest); - break; - - default: - - // - // First check to see if this is for a BIOMETRIC file. - // - if ((ControlCode & CTL_CODE(0xFFFFFFFF, 0, 0, 0)) == CTL_CODE(FILE_DEVICE_BIOMETRIC, 0, 0, 0)) { - - if ((ControlCode & IOCTL_BIOMETRIC_VENDOR) == IOCTL_BIOMETRIC_VENDOR) { - // This is a vendor IOCTL. - m_BiometricDevice->OnControlUnit(FxRequest); - break; - } - - } else { - - // This is a legacy IOCTL - non-Windows Biometric Framework - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_QUEUE, - "%!FUNC!Legacy control units not supported by the driver."); - - } - - // - // Didn't match any of the above. - // - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_QUEUE, - "%!FUNC! Unsupported IOCTL - 0x%x.", - ControlCode); - FxRequest->Complete(HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION)); - break; - - } - - return; - -} - diff --git a/biometrics/driver/IoQueue.h b/biometrics/driver/IoQueue.h deleted file mode 100644 index 1a68416b1..000000000 --- a/biometrics/driver/IoQueue.h +++ /dev/null @@ -1,123 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - IoQueue.h - -Abstract: - - This file defines the queue callback interface. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// Queue Callback Object. -// - -class CBiometricIoQueue : - public CComObjectRootEx, - public IQueueCallbackDeviceIoControl -{ - -public: - - DECLARE_NOT_AGGREGATABLE(CBiometricIoQueue) - - BEGIN_COM_MAP(CBiometricIoQueue) - COM_INTERFACE_ENTRY(IQueueCallbackDeviceIoControl) - END_COM_MAP() - - CBiometricIoQueue() : - m_FxQueue(NULL), - m_BiometricDevice(NULL) - { - } - - ~CBiometricIoQueue() - { - // empty - } - - HRESULT - Initialize( - _In_ IWDFDevice *FxDevice, - _In_ CBiometricDevice *BiometricDevice - ); - - static - HRESULT - CreateInstanceAndInitialize( - _In_ IWDFDevice *FxDevice, - _In_ CBiometricDevice *BiometricDevice, - _Out_ CBiometricIoQueue** Queue - ); - - HRESULT - Configure( - VOID - ) - { - return S_OK; - } - - VOID - Start( - ) - { - m_FxQueue->Start(); - } - - VOID - StopSynchronously( - ) - { - m_FxQueue->StopSynchronously(); - } - - // - // Wdf Callbacks - // - - // - // IQueueCallbackDeviceIoControl - // - virtual - VOID - STDMETHODCALLTYPE - OnDeviceIoControl( - _In_ IWDFIoQueue *pWdfQueue, - _In_ IWDFIoRequest *pWdfRequest, - _In_ ULONG ControlCode, - _In_ SIZE_T InputBufferSizeInBytes, - _In_ SIZE_T OutputBufferSizeInBytes - ); - -// -// Private member variables. -// -private: - - // - // Weak reference to framework queue object. - // - IWDFIoQueue * m_FxQueue; - - // - // Pointer to device class. - // - CBiometricDevice * m_BiometricDevice; - -}; diff --git a/biometrics/driver/RequestHelper.h b/biometrics/driver/RequestHelper.h deleted file mode 100644 index 89a8747c7..000000000 --- a/biometrics/driver/RequestHelper.h +++ /dev/null @@ -1,89 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - RequestHelper.h - -Abstract: - - This module contains the class definition and implementation - of an RAII Request object helper class. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// This class handles RAII for IWdfIoRequest pointers. -// A function can declare this class at the beginning, and -// set the HRESULT for the request completion. -// -// The destructor is always called on function exit. -// It will complete the request only if the HRESULT -// is something besides HRESULT_FROM_WIN32(ERROR_IO_PENDING) -// -// If the function does not want to complete the request, -// it should not call SetCompletionHr. Then the request -// will remain pending. -// - -class CRequestHelper -{ - -// -// Public methods -// -public: - - CRequestHelper( - IWDFIoRequest *FxRequest - ) - { - m_Request = FxRequest; - m_Hr = HRESULT_FROM_WIN32(ERROR_IO_PENDING); - } - - ~CRequestHelper() - { - if (m_Hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING)) - { - m_Request->Complete(m_Hr); - } - } - - void - SetCompletionHr( - HRESULT Hr - ) - { - m_Hr = Hr; - } - - void - SetInformation( - SIZE_T Information - ) - { - m_Request->SetInformation(Information); - } - -// -// Private members -// -private: - - IWDFIoRequest * m_Request; - HRESULT m_Hr; - -}; diff --git a/biometrics/driver/WudfBioUsbSample.inx b/biometrics/driver/WudfBioUsbSample.inx deleted file mode 100644 index 71f9277b3..000000000 Binary files a/biometrics/driver/WudfBioUsbSample.inx and /dev/null differ diff --git a/biometrics/driver/WudfBioUsbSample.vcxproj b/biometrics/driver/WudfBioUsbSample.vcxproj deleted file mode 100644 index c54af93e0..000000000 --- a/biometrics/driver/WudfBioUsbSample.vcxproj +++ /dev/null @@ -1,327 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {474A1976-0414-48E7-9F2B-4FDED5BA700C} - $(MSBuildProjectName) - 1 - 1 - false - true - Debug - Win32 - {446E3007-2D5F-41DF-80D9-3B5FD3ACBF57} - - - - Windows10 - False - Desktop - UMDF - WindowsUserModeDriver10.0 - DynamicLibrary - - - Windows10 - True - Desktop - UMDF - WindowsUserModeDriver10.0 - DynamicLibrary - - - Windows10 - False - Desktop - UMDF - WindowsUserModeDriver10.0 - DynamicLibrary - - - Windows10 - True - Desktop - UMDF - WindowsUserModeDriver10.0 - DynamicLibrary - - - - $(IntDir) - - - - - - - - - - - - - - - - true - true - internal.h - ;%(AdditionalIncludeDirectories) - Internal.h - Use - $(IntDir)\Internal.h.pch - - - true - true - internal.h - ;%(AdditionalIncludeDirectories) - Internal.h - Use - $(IntDir)\Internal.h.pch - - - true - true - internal.h - ;%(AdditionalIncludeDirectories) - Internal.h - Use - $(IntDir)\Internal.h.pch - - - true - true - internal.h - ;%(AdditionalIncludeDirectories) - Internal.h - Use - $(IntDir)\Internal.h.pch - - - $(InfArch) - true - .\$(IntDir)\WudfBioUsbSample.inf - - - true - true - internal.h - - - - WudfBioUsbSample - 0x0A00 - 0x0A000000 - Dynamic - - - WudfBioUsbSample - 0x0A00 - 0x0A000000 - Dynamic - - - WudfBioUsbSample - 0x0A00 - 0x0A000000 - Dynamic - - - WudfBioUsbSample - 0x0A00 - 0x0A000000 - Dynamic - - - - true - Level4 - %(DisableSpecificWarnings);4201 - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - %(DisableSpecificWarnings);4201 - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - %(DisableSpecificWarnings);4201 - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - true - Level4 - %(DisableSpecificWarnings);4201 - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - %(PreprocessorDefinitions);_UNICODE;UNICODE - - - _DllMainCRTStartup@12 - _DllMainCRTStartup - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalDependencies);$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\ole32.lib;$(SDK_LIB_PATH)\oleaut32.lib;$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\user32.lib;$(SDK_LIB_PATH)\uuid.lib - exports.def - - - sha256 - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalDependencies);$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\ole32.lib;$(SDK_LIB_PATH)\oleaut32.lib;$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\user32.lib;$(SDK_LIB_PATH)\uuid.lib - exports.def - - - sha256 - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalDependencies);$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\ole32.lib;$(SDK_LIB_PATH)\oleaut32.lib;$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\user32.lib;$(SDK_LIB_PATH)\uuid.lib - exports.def - - - sha256 - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - - - %(AdditionalIncludeDirectories);inc;$(DDK_INC_PATH) - - - %(AdditionalDependencies);$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\ole32.lib;$(SDK_LIB_PATH)\oleaut32.lib;$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\user32.lib;$(SDK_LIB_PATH)\uuid.lib - exports.def - - - sha256 - - - - - ;%(AdditionalIncludeDirectories) - Internal.h - Create - $(IntDir)\Internal.h.pch - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/biometrics/driver/WudfBioUsbSample.vcxproj.Filters b/biometrics/driver/WudfBioUsbSample.vcxproj.Filters deleted file mode 100644 index f4bbd976f..000000000 --- a/biometrics/driver/WudfBioUsbSample.vcxproj.Filters +++ /dev/null @@ -1,73 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* - {E6E929B2-2CDF-41CF-9E24-FC00BD508586} - - - h;hpp;hxx;hm;inl;inc;xsd - {4197754B-41E9-46E9-BB6C-32A9FD55F25C} - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml - {216999F8-06DE-407C-B349-8709AD141CCF} - - - inf;inv;inx;mof;mc; - {41FD81A3-D683-4D3C-91BE-D00EB56515FE} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Driver Files - - - - - Resource Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/biometrics/driver/dllsup.cpp b/biometrics/driver/dllsup.cpp deleted file mode 100644 index 8030a1c0b..000000000 --- a/biometrics/driver/dllsup.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Dllsup.cpp - -Abstract: - - This module contains the implementation of the Driver DLL entry point. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#include "internal.h" -#include "dllsup.tmh" - -// -// TODO - define a new GUID here -// This GUID goes in the inf file in the DriverCLSID value for the service binary -// {F1CB3C15-A916-47bc-BEA1-D5D4163BC6AE} -// -const CLSID CLSID_BiometricUsbSample = -{ 0xf1cb3c15, 0xa916, 0x47bc, { 0xbe, 0xa1, 0xd5, 0xd4, 0x16, 0x3b, 0xc6, 0xae } }; - - - -HINSTANCE g_hInstance = NULL; - -class CBiometricDriverModule : - public CAtlDllModuleT< CBiometricDriverModule > -{ -}; - -CBiometricDriverModule _AtlModule; - -// -// DLL Entry Point -// - -extern "C" -BOOL -WINAPI -DllMain( - HINSTANCE hInstance, - DWORD dwReason, - LPVOID lpReserved - ) -{ - if (dwReason == DLL_PROCESS_ATTACH) { - WPP_INIT_TRACING(MYDRIVER_TRACING_ID); - - g_hInstance = hInstance; - DisableThreadLibraryCalls(hInstance); - - } else if (dwReason == DLL_PROCESS_DETACH) { - WPP_CLEANUP(); - } - - return _AtlModule.DllMain(dwReason, lpReserved); -} - - -// -// Returns a class factory to create an object of the requested type -// - -STDAPI -DllGetClassObject( - _In_ REFCLSID rclsid, - _In_ REFIID riid, - _Outptr_ LPVOID FAR* ppv - ) -{ - return _AtlModule.DllGetClassObject(rclsid, riid, ppv); -} - - diff --git a/biometrics/driver/exports.def b/biometrics/driver/exports.def deleted file mode 100644 index 37b136229..000000000 --- a/biometrics/driver/exports.def +++ /dev/null @@ -1,10 +0,0 @@ -; Exports.def : Declares the module parameters. - -; -; TODO: Change the library name here to match your binary name. -; - -LIBRARY "WudfBioUsbSample.DLL" - -EXPORTS - DllGetClassObject PRIVATE diff --git a/biometrics/driver/inc/public.h b/biometrics/driver/inc/public.h deleted file mode 100644 index 11a7e8fa1..000000000 --- a/biometrics/driver/inc/public.h +++ /dev/null @@ -1,42 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - public.h - -Abstract: - - Public definitions for the Biometric Device. - -Environment: - - User & Kernel mode - ---*/ - -#ifndef _PUBLIC_H -#define _PUBLIC_H - -#include - -// -// INTERRUPT_MESSAGE -// - -typedef struct _INTERRUPT_MESSAGE -{ - - // - // TODO: Fill this in with your device specific fields. - // - -} INTERRUPT_MESSAGE, *PINTERRUPT_MESSAGE; - -#endif diff --git a/biometrics/driver/inc/usb_hw.h b/biometrics/driver/inc/usb_hw.h deleted file mode 100644 index 299e7a02f..000000000 --- a/biometrics/driver/inc/usb_hw.h +++ /dev/null @@ -1,238 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Usb.h - -Abstract: - - Contains prototypes for interfacing with a USB connected device. These - are copied from the KMDF WDFUSB.H header file (but with the WDF specific - portions removed) - -Environment: - - kernel mode only - ---*/ - -#pragma once - -typedef enum _WINUSB_BMREQUEST_DIRECTION { - BmRequestHostToDevice = BMREQUEST_HOST_TO_DEVICE, - BmRequestDeviceToHost = BMREQUEST_DEVICE_TO_HOST, -} WINUSB_BMREQUEST_DIRECTION; - -typedef enum _WINUSB_BMREQUEST_TYPE { - BmRequestStandard = BMREQUEST_STANDARD, - BmRequestClass = BMREQUEST_CLASS, - BmRequestVendor = BMREQUEST_VENDOR, -} WINUSB_BMREQUEST_TYPE; - -typedef enum _WINUSB_BMREQUEST_RECIPIENT { - BmRequestToDevice = BMREQUEST_TO_DEVICE, - BmRequestToInterface = BMREQUEST_TO_INTERFACE, - BmRequestToEndpoint = BMREQUEST_TO_ENDPOINT, - BmRequestToOther = BMREQUEST_TO_OTHER, -} WINUSB_BMREQUEST_RECIPIENT; - -typedef enum _WINUSB_DEVICE_TRAITS { - WINUSB_DEVICE_TRAIT_SELF_POWERED = 0x00000001, - WINUSB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE = 0x00000002, - WINUSB_DEVICE_TRAIT_AT_HIGH_SPEED = 0x00000004, -} WINUSB_DEVICE_TRAITS; - -typedef enum _WdfUsbTargetDeviceSelectInterfaceType { - WdfUsbTargetDeviceSelectInterfaceTypeInterface = 0x10, - WdfUsbTargetDeviceSelectInterfaceTypeUrb = 0x11, -} WdfUsbTargetDeviceSelectInterfaceType; - - - -typedef union _WINUSB_CONTROL_SETUP_PACKET { - struct { - union { - #pragma warning(disable:4214) // bit field types other than int - struct { - // - // Valid values are BMREQUEST_TO_DEVICE, BMREQUEST_TO_INTERFACE, - // BMREQUEST_TO_ENDPOINT, BMREQUEST_TO_OTHER - // - BYTE Recipient:2; - - BYTE Reserved:3; - - // - // Valid values are BMREQUEST_STANDARD, BMREQUEST_CLASS, - // BMREQUEST_VENDOR - // - BYTE Type:2; - - // - // Valid values are BMREQUEST_HOST_TO_DEVICE, - // BMREQUEST_DEVICE_TO_HOST - // - BYTE Dir:1; - } Request; - #pragma warning(default:4214) // bit field types other than int - BYTE Byte; - } bm; - - BYTE bRequest; - - union { - struct { - BYTE LowByte; - BYTE HiByte; - } Bytes; - USHORT Value; - } wValue; - - union { - struct { - BYTE LowByte; - BYTE HiByte; - } Bytes; - USHORT Value; - } wIndex; - - USHORT wLength; - } Packet; - - struct { - BYTE Bytes[8]; - } Generic; - - WINUSB_SETUP_PACKET WinUsb; - -} WINUSB_CONTROL_SETUP_PACKET, *PWINUSB_CONTROL_SETUP_PACKET; - -VOID -FORCEINLINE -WINUSB_CONTROL_SETUP_PACKET_INIT( - PWINUSB_CONTROL_SETUP_PACKET Packet, - WINUSB_BMREQUEST_DIRECTION Direction, - WINUSB_BMREQUEST_RECIPIENT Recipient, - BYTE Request, - USHORT Value, - USHORT Index - ) -{ - RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET)); - - Packet->Packet.bm.Request.Dir = (BYTE) Direction; - Packet->Packet.bm.Request.Type = (BYTE) BmRequestStandard; - Packet->Packet.bm.Request.Recipient = (BYTE) Recipient; - - Packet->Packet.bRequest = Request; - Packet->Packet.wValue.Value = Value; - Packet->Packet.wIndex.Value = Index; - - // Packet->Packet.wLength will be set by the formatting function -} - -VOID -FORCEINLINE -WINUSB_CONTROL_SETUP_PACKET_INIT_CLASS( - PWINUSB_CONTROL_SETUP_PACKET Packet, - WINUSB_BMREQUEST_DIRECTION Direction, - WINUSB_BMREQUEST_RECIPIENT Recipient, - BYTE Request, - USHORT Value, - USHORT Index - ) -{ - RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET)); - - Packet->Packet.bm.Request.Dir = (BYTE) Direction; - Packet->Packet.bm.Request.Type = (BYTE) BmRequestClass; - Packet->Packet.bm.Request.Recipient = (BYTE) Recipient; - - Packet->Packet.bRequest = Request; - Packet->Packet.wValue.Value = Value; - Packet->Packet.wIndex.Value = Index; - - // Packet->Packet.wLength will be set by the formatting function -} - -VOID -FORCEINLINE -WINUSB_CONTROL_SETUP_PACKET_INIT_VENDOR( - PWINUSB_CONTROL_SETUP_PACKET Packet, - WINUSB_BMREQUEST_DIRECTION Direction, - WINUSB_BMREQUEST_RECIPIENT Recipient, - BYTE Request, - USHORT Value, - USHORT Index - ) -{ - RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET)); - - Packet->Packet.bm.Request.Dir = (BYTE) Direction; - Packet->Packet.bm.Request.Type = (BYTE) BmRequestVendor; - Packet->Packet.bm.Request.Recipient = (BYTE) Recipient; - - Packet->Packet.bRequest = Request; - Packet->Packet.wValue.Value = Value; - Packet->Packet.wIndex.Value = Index; - - // Packet->Packet.wLength will be set by the formatting function -} - -VOID -FORCEINLINE -WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE( - PWINUSB_CONTROL_SETUP_PACKET Packet, - WINUSB_BMREQUEST_RECIPIENT BmRequestRecipient, - USHORT FeatureSelector, - USHORT Index, - BOOLEAN SetFeature - ) -{ - RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET)); - - Packet->Packet.bm.Request.Dir = (BYTE) BmRequestHostToDevice; - Packet->Packet.bm.Request.Type = (BYTE) BmRequestStandard; - Packet->Packet.bm.Request.Recipient = (BYTE) BmRequestRecipient; - - if (SetFeature) { - Packet->Packet.bRequest = USB_REQUEST_SET_FEATURE; - } - else { - Packet->Packet.bRequest = USB_REQUEST_CLEAR_FEATURE; - } - - Packet->Packet.wValue.Value = FeatureSelector; - Packet->Packet.wIndex.Value = Index; - - // Packet->Packet.wLength will be set by the formatting function -} - -VOID -FORCEINLINE -WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS( - PWINUSB_CONTROL_SETUP_PACKET Packet, - WINUSB_BMREQUEST_RECIPIENT BmRequestRecipient, - USHORT Index - ) -{ - RtlZeroMemory(Packet, sizeof(WINUSB_CONTROL_SETUP_PACKET)); - - Packet->Packet.bm.Request.Dir = (BYTE) BmRequestDeviceToHost; - Packet->Packet.bm.Request.Type = (BYTE) BmRequestStandard; - Packet->Packet.bm.Request.Recipient = (BYTE) BmRequestRecipient; - - Packet->Packet.bRequest = USB_REQUEST_GET_STATUS; - Packet->Packet.wIndex.Value = Index; - Packet->Packet.wValue.Value = 0; - - // Packet->Packet.wLength will be set by the formatting function -} - diff --git a/biometrics/driver/internal.h b/biometrics/driver/internal.h deleted file mode 100644 index bbccbdba0..000000000 --- a/biometrics/driver/internal.h +++ /dev/null @@ -1,164 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Internal.h - -Abstract: - - This module contains necessary include directives, WPP tracing macros, - and string definitions for the Biometric driver sample. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// ATL support -// -#include "atlbase.h" -#include "atlcom.h" - -// -// Include the WUDF Headers -// - -#include "wudfddi.h" - -// -// Use specstrings for in/out annotation of function parameters. -// - -#include "specstrings.h" - -// -// Get limits on common data types (ULONG_MAX for example) -// - -#include "limits.h" - -// -// We need usb I/O targets to talk to the USB device. -// - -#include "wudfusb.h" - -// -// WinUsb structures. -// - -#include "usb_hw.h" - -// -// Public definitions. -// -#include "public.h" - -// -// GUID include -// -#include - -// -// Windows IOCTL definitions. -// -#include "winioctl.h" - -// -// WinBio includes -// -#include "winbio_types.h" -#include "winbio_err.h" -#include "winbio_ioctl.h" - -// -// RAII helper class for requests -// -#include "RequestHelper.h" - -// -// Define the tracing flags. -// -// Tracing GUID defined in BioUsbSample.ctl - 864936A6-DB79-451e-B764-E720D61A9361 -// -// TODO: Generate a new tracing GUID for your driver, and replace all -// instances of the GUID above with your new GUID. -// - -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID( \ - WudfBioUsbSampleTraceGuid, (864936A6,DB79,451e,B764,E720D61A9361), \ - \ - WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ - WPP_DEFINE_BIT(BIOMETRIC_TRACE_DRIVER) \ - WPP_DEFINE_BIT(BIOMETRIC_TRACE_DEVICE) \ - WPP_DEFINE_BIT(BIOMETRIC_TRACE_QUEUE) \ - ) - -#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. -// -// begin_wpp config -// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); -// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); -// end_wpp -// - -// -// Forward definition of queue. -// -typedef class CBiometricIoQueue *PCBiometricIoQueue; - -// -// Include the type specific headers. -// -#include "Driver.h" -#include "Device.h" -#include "IoQueue.h" - -// -// Driver specific #defines -// TODO: Put strings specific to your device here. -// - -#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF\\Biometric USB Sample V1.0" - -#define SAMPLE_MANUFACTURER_NAME L"Biometric Sample Manufacturer" -#define SAMPLE_MODEL_NAME L"Biometric Sample Model" -#define SAMPLE_SERIAL_NUMBER L"000-000-000" - - -template -inline void BiometricSafeRelease(T *&t) -{ - if (t) - { - t->Release(); - } - t = NULL; -} diff --git a/biometrics/driver/resource.h b/biometrics/driver/resource.h deleted file mode 100644 index 09e852e8e..000000000 --- a/biometrics/driver/resource.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Copyright (C) Microsoft. All rights reserved. -// -#define IDR_MYDRIVER_CLASSINFO 101 diff --git a/bluetooth/bthecho/README.md b/bluetooth/bthecho/README.md index 6f7c92c89..275cf8d9f 100644 --- a/bluetooth/bthecho/README.md +++ b/bluetooth/bthecho/README.md @@ -58,7 +58,7 @@ You can build the sample in two ways: using the Visual Studio Integrated Develop #### Server Installation -1. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\ ), BthEchoSampleSrv.Sys, BthEchoSampleSrv.inf and bthsrvinst.exe on a temporary directory on the target machine. +1. Copy BthEchoSampleSrv.Sys, BthEchoSampleSrv.inf and bthsrvinst.exe on a temporary directory on the target machine. 1. Run bthsrvinst.exe /i to install the echo server device. This enables the Bluetooth Enumerator (BthEnum.sys) to enumerate echo server device and create a PDO for the device (please refer to the device tree below). @@ -111,7 +111,7 @@ You can build the sample in two ways: using the Visual Studio Integrated Develop > [!IMPORTANT] > This must be done on a separate machine from the one where echo server device was installed. -1. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\), BthEchoSampleCli.Sys, BthEchoSampleCli.inf and bthecho.exe on a temporary directory on the target machine. +1. Copy BthEchoSampleCli.Sys, BthEchoSampleCli.inf and bthecho.exe on a temporary directory on the target machine. 1. Run bthprops.cpl from a command line or right click on the Bluetooth icon in the system tray and select 'Show Devices' to bring up a list of installed Bluetooth devices. diff --git a/bluetooth/bthecho/bthcli/app/BthEcho.vcxproj b/bluetooth/bthecho/bthcli/app/BthEcho.vcxproj index 382f447b7..2d15392b3 100644 --- a/bluetooth/bthecho/bthcli/app/BthEcho.vcxproj +++ b/bluetooth/bthecho/bthcli/app/BthEcho.vcxproj @@ -29,7 +29,7 @@ Windows10 False - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -37,7 +37,7 @@ Windows10 True - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -45,7 +45,7 @@ Windows10 False - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -53,7 +53,7 @@ Windows10 True - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application diff --git a/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.inx b/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.inx index 16c1ef51a..6f326ff3a 100644 Binary files a/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.inx and b/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.inx differ diff --git a/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.vcxproj b/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.vcxproj index 6f79e19b5..389e659e2 100644 --- a/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.vcxproj +++ b/bluetooth/bthecho/bthcli/sys/BthEchoSampleCli.vcxproj @@ -30,7 +30,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -38,7 +38,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -46,7 +46,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -54,7 +54,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver diff --git a/bluetooth/bthecho/bthsrv/inst/bthsrvinst.vcxproj b/bluetooth/bthecho/bthsrv/inst/bthsrvinst.vcxproj index c5f3d960b..035024e84 100644 --- a/bluetooth/bthecho/bthsrv/inst/bthsrvinst.vcxproj +++ b/bluetooth/bthecho/bthsrv/inst/bthsrvinst.vcxproj @@ -29,7 +29,7 @@ Windows10 False - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -37,7 +37,7 @@ Windows10 True - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -45,7 +45,7 @@ Windows10 False - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -53,7 +53,7 @@ Windows10 True - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application diff --git a/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.inx b/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.inx index efb08654b..3079c6d0d 100644 Binary files a/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.inx and b/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.inx differ diff --git a/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.vcxproj b/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.vcxproj index f612a2bc2..6c186f8ec 100644 --- a/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.vcxproj +++ b/bluetooth/bthecho/bthsrv/sys/BthEchoSampleSrv.vcxproj @@ -30,7 +30,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -38,7 +38,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -46,7 +46,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -54,7 +54,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver diff --git a/bluetooth/bthecho/common/lib/bthecho.vcxproj b/bluetooth/bthecho/common/lib/bthecho.vcxproj index 27ac5cc62..329d8f306 100644 --- a/bluetooth/bthecho/common/lib/bthecho.vcxproj +++ b/bluetooth/bthecho/common/lib/bthecho.vcxproj @@ -30,7 +30,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -38,7 +38,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -46,7 +46,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary @@ -54,7 +54,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 StaticLibrary diff --git a/bluetooth/serialhcibus/WDK/SerialBusWdk.inx b/bluetooth/serialhcibus/WDK/SerialBusWdk.inx index 6fa29006f..27f70ab60 100644 Binary files a/bluetooth/serialhcibus/WDK/SerialBusWdk.inx and b/bluetooth/serialhcibus/WDK/SerialBusWdk.inx differ diff --git a/exclusions.csv b/exclusions.csv index ebaea66a8..1a5ed717d 100644 --- a/exclusions.csv +++ b/exclusions.csv @@ -1,17 +1,7 @@ Path,Configurations,MinBuild,MaxBuild,Reason -avstream\sampledevicemft,*,26031,,Only GE: Fails to build -general\dchu\osrfx2_dchu_base,*,,,Wrong Toolset - needs migration -general\dchu\osrfx2_dchu_extension_loose,*,,,Needs fix for project not found -general\dchu\osrfx2_dchu_extension_tight,*,,,Wrong Toolset - needs migration -general\filehistory,*,,,Deprecated APIs -general\simplemediasource,Debug|arm64,,,Only Debug|arm64: LNK1181: cannot open input file 'SimpleMediaSource.lib' -general\winhec 2017 lab\toaster driver,*,,,Needs input from end user -general\winhec 2017 lab\toaster support app,*,,,Needs input from end user -network\trans\stmedit,*,,,Invalid Win32 architecture -network\trans\wfpsampler,*,,,Missing INF section; missing libs -network\wlan\wdi,*,,,Invalid architecture -print\oem printer customization plug-in samples\c++,*,,,Invalid architecture -print\v4printdriversamples\printerextensionsample,*,,,Invalid architecture -storage\class\cdrom,*,26031,,Only GE: Fails to build +audio\acx\samples\audiocodec\driver,*,,22621,Only NI: error C1083: Cannot open include file: 'acx.h': No such file or directory +general\dchu\osrfx2_dchu_extension_loose,*|x64,,22621,Only NI: Only x64: Fails to build +general\dchu\osrfx2_dchu_extension_tight,*|x64,,22621,Only NI: Only x64: Fails to build +prm,*,,22621,Only NI: Not supported on NI. +video\indirectdisplay,*,,,Only EWDK: Fails to build with EWDK (builds fine with regular WDK). tree,*,,,Missing headers -video\indirectdisplay,*|arm64,,,Only arm64: Warning C4530: C++ exception handler used but unwind semantics are not enabled diff --git a/filesys/cdfs/cdfs.vcxproj b/filesys/cdfs/cdfs.vcxproj index 5e053a300..9a32ad6ca 100644 --- a/filesys/cdfs/cdfs.vcxproj +++ b/filesys/cdfs/cdfs.vcxproj @@ -30,7 +30,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -38,7 +38,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver diff --git a/filesys/fastfat/fastfat.vcxproj b/filesys/fastfat/fastfat.vcxproj index 09c805a23..8ad4848e8 100644 --- a/filesys/fastfat/fastfat.vcxproj +++ b/filesys/fastfat/fastfat.vcxproj @@ -30,7 +30,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -38,7 +38,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -46,7 +46,7 @@ Windows10 False - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -54,7 +54,7 @@ Windows10 True - Universal + Windows Driver WDM WindowsKernelModeDriver10.0 Driver diff --git a/filesys/fastfat/lockctrl.c b/filesys/fastfat/lockctrl.c index 58aacdcaf..1cb183fbd 100644 --- a/filesys/fastfat/lockctrl.c +++ b/filesys/fastfat/lockctrl.c @@ -666,7 +666,7 @@ Return Value: } // - // Acquire exclusive access to the Fcb and enqueue the Irp if we didn't + // Acquire shared access to the Fcb and enqueue the Irp if we didn't // get access // diff --git a/filesys/miniFilter/MetadataManager/MetadataManagerInit.c b/filesys/miniFilter/MetadataManager/MetadataManagerInit.c index 222159f7c..dbedd3a89 100644 --- a/filesys/miniFilter/MetadataManager/MetadataManagerInit.c +++ b/filesys/miniFilter/MetadataManager/MetadataManagerInit.c @@ -86,8 +86,31 @@ FmmInstanceTeardownComplete ( #if DBG +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +FmmGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +FmmOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + VOID FmmInitializeDebugLevel ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -101,6 +124,8 @@ FmmInitializeDebugLevel ( #pragma alloc_text(INIT, DriverEntry) #if DBG +#pragma alloc_text(INIT, FmmGetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, FmmOpenServiceParametersKey) #pragma alloc_text(INIT, FmmInitializeDebugLevel) #endif @@ -115,11 +140,11 @@ FmmInitializeDebugLevel ( // // If we need to verify that the metadata file is indeed open whenever -// a create suceeds on the volume, then we need to monitor all creates +// a create suceeds on the volume, then we need to monitor all creates // not just DASD creates. -// If that is not the case, then we are better off telling filter manager -// to show us only DASD creates. That way we can avoid the performance +// If that is not the case, then we are better off telling filter manager +// to show us only DASD creates. That way we can avoid the performance // penalty of being called for all creates when we only have use for DASD // creates. // @@ -241,7 +266,7 @@ Return Value: // // Default to NonPagedPoolNx for non paged pool allocations where supported. // - + ExInitializeDriverRuntime( DrvRtPoolNxOptIn ); @@ -253,7 +278,7 @@ Return Value: // Initialize global debug level // - FmmInitializeDebugLevel( RegistryPath ); + FmmInitializeDebugLevel( DriverObject, RegistryPath ); #else @@ -299,8 +324,147 @@ Return Value: #if DBG +PFN_IoOpenDriverRegistryKey +FmmGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +FmmOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible + // + + pIoOpenDriverRegistryKey = FmmGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API + // + + status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + + } else { + + // + // Open specified service root key + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + + // + // Open the parameters key relative to service key path + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + } + + // + // Return value to caller + // + + *ServiceParametersKey = ParametersKey; + +cleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return status; + +} + VOID FmmInitializeDebugLevel ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -313,6 +477,9 @@ Routine Description: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -321,8 +488,7 @@ Return Value: --*/ { - OBJECT_ATTRIBUTES attributes; - HANDLE driverRegKey; + HANDLE driverRegKey = NULL; NTSTATUS status; ULONG resultLength; UNICODE_STRING valueName; @@ -331,47 +497,46 @@ Return Value: Globals.DebugLevel = DEBUG_TRACE_ERROR; // - // Open the desired registry key + // Open service parameters key to query values from. // - InitializeObjectAttributes( &attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); + status = FmmOpenServiceParametersKey( DriverObject, + RegistryPath, + &driverRegKey ); - status = ZwOpenKey( &driverRegKey, - KEY_READ, - &attributes ); + if (!NT_SUCCESS( status )) { - if (NT_SUCCESS( status )) { + driverRegKey = NULL; + goto cleanup; + } - // - // Read the DebugFlags value from the registry. - // + // + // Read the DebugFlags value from the registry. + // - RtlInitUnicodeString( &valueName, L"DebugLevel" ); + RtlInitUnicodeString( &valueName, L"DebugLevel" ); - status = ZwQueryValueKey( driverRegKey, - &valueName, - KeyValuePartialInformation, - buffer, - sizeof(buffer), - &resultLength ); + status = ZwQueryValueKey( driverRegKey, + &valueName, + KeyValuePartialInformation, + buffer, + sizeof(buffer), + &resultLength ); - if (NT_SUCCESS( status )) { + if (NT_SUCCESS( status )) { - Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data)); - } - - // - // Close the registry entry - // - - ZwClose( driverRegKey ); - + Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data)); } +cleanup: + + // + // Close the registry entry + // + + if (driverRegKey != NULL) { + ZwClose( driverRegKey ); + } } #endif @@ -678,22 +843,22 @@ Return Value: } // - // If this is an automatic attachment (mount, load, etc) and we are not - // attaching to this volume because we do not support attaching to this - // volume, then simply return STATUS_FLT_DO_NOT_ATTACH. If we return - // anything else fltmgr logs an event log indicating failure to attach. - // Since this failure to attach is not really an error, we do not want + // If this is an automatic attachment (mount, load, etc) and we are not + // attaching to this volume because we do not support attaching to this + // volume, then simply return STATUS_FLT_DO_NOT_ATTACH. If we return + // anything else fltmgr logs an event log indicating failure to attach. + // Since this failure to attach is not really an error, we do not want // this failure to be logged as an error in the event log. For all other // error codes besides the ones we consider "normal", if is ok for fltmgr // to actually log the failure to attach. // - // If this is a manual attach attempt that we have failed then we want to - // give the user a clear indication of why the attachment failed. Hence in + // If this is a manual attach attempt that we have failed then we want to + // give the user a clear indication of why the attachment failed. Hence in // this case, we will not override the error status with STATUS_FLT_DO_NOT_ATTACH // irrespective of the cause of the failure to attach // - if (status == STATUS_NOT_SUPPORTED && + if (status == STATUS_NOT_SUPPORTED && !FlagOn( Flags, FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT )) { status = STATUS_FLT_DO_NOT_ATTACH; diff --git a/filesys/miniFilter/MetadataManager/fmm.inf b/filesys/miniFilter/MetadataManager/fmm.inf index 5c39ed069..ad231a8c1 100644 Binary files a/filesys/miniFilter/MetadataManager/fmm.inf and b/filesys/miniFilter/MetadataManager/fmm.inf differ diff --git a/filesys/miniFilter/NameChanger/NameChanger.inf b/filesys/miniFilter/NameChanger/NameChanger.inf index cd74fb44c..7c0b2364c 100644 Binary files a/filesys/miniFilter/NameChanger/NameChanger.inf and b/filesys/miniFilter/NameChanger/NameChanger.inf differ diff --git a/filesys/miniFilter/NameChanger/nc.c b/filesys/miniFilter/NameChanger/nc.c index 9bcdc0944..c59742e53 100644 --- a/filesys/miniFilter/NameChanger/nc.c +++ b/filesys/miniFilter/NameChanger/nc.c @@ -988,7 +988,7 @@ Return Value: NcCompatInit( ); - Status = NcInitializeMapping( RegistryPath ); + Status = NcInitializeMapping( DriverObject, RegistryPath ); if (!NT_SUCCESS( Status )) { return Status; } diff --git a/filesys/miniFilter/NameChanger/nc.h b/filesys/miniFilter/NameChanger/nc.h index c2509faa9..47d582b44 100644 --- a/filesys/miniFilter/NameChanger/nc.h +++ b/filesys/miniFilter/NameChanger/nc.h @@ -59,7 +59,7 @@ // // Typedefs for dynamically imported routines -// +// typedef NTSTATUS @@ -277,27 +277,27 @@ typedef struct _NC_DIR_NOT_IO_CACHE { // Stores the state of the cache. // If the pointer is NULL, there is nothing in cache. // - + NC_CACHE_ENTRY Cache; // // If ReadyToIssue is TRUE, then its safe to fire off the request. // - + BOOLEAN ReadyToIssue; // // Io is a pointer to the callback data. // When ReadyToUse new io can be issued. // - + PFLT_CALLBACK_DATA Io; // // SystemBuffer is a pointer to a system buffer which will // be used to issue the IO. // - + char * SystemBuffer; ULONG SystemBufferLength; @@ -479,7 +479,7 @@ extern NC_GLOBAL_DATA NcGlobalData; // // Function declarations -// +// // // The following functions exist in nchelper.c @@ -487,18 +487,18 @@ extern NC_GLOBAL_DATA NcGlobalData; _When_(Data == NULL, _Pre_satisfies_(FileObject != NULL && Instance != NULL)) _When_(FileObject == NULL || Instance == NULL, _Pre_satisfies_(Data != NULL)) -NTSTATUS +NTSTATUS NcGetFileNameInformation( _In_opt_ PFLT_CALLBACK_DATA Data, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PFLT_INSTANCE Instance, _In_ FLT_FILE_NAME_OPTIONS NameOptions, - _Outptr_ PFLT_FILE_NAME_INFORMATION *FileNameInformation + _Outptr_ PFLT_FILE_NAME_INFORMATION *FileNameInformation ); NTSTATUS NcAllocateEResource( - _Out_ PERESOURCE * OutputLock + _Out_ PERESOURCE * OutputLock ); VOID @@ -600,8 +600,9 @@ NcBuildMapping ( // The following functions exist in ncinit.c // -NTSTATUS +NTSTATUS NcInitializeMapping( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -642,7 +643,7 @@ NcParseFinalComponent ( // NTSTATUS -NcStreamHandleContextAllocAndAttach( +NcStreamHandleContextAllocAndAttach( _In_ PFLT_FILTER Filter, _In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, @@ -709,7 +710,7 @@ NcDetermineStructureOffsets ( _In_ FILE_INFORMATION_CLASS Information ); -VOID +VOID NcCalculateDirectoryNotificationOffsets ( PDIRECTORY_CONTROL_OFFSETS Offsets ); @@ -762,7 +763,7 @@ NcSetNextEntryOffset ( _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets, _In_ BOOLEAN ForceLast); -VOID +VOID NcSetFileName ( _In_ PVOID Entry, _In_ PWSTR NewName, @@ -771,7 +772,7 @@ NcSetFileName ( _In_ BOOLEAN ForceLast ); -VOID +VOID NcSetShortName ( _In_ PVOID Entry, _In_ PWSTR NewShortName, @@ -800,7 +801,7 @@ NcEnumerateDirectorySetupInjection ( ); VOID -NcEnumerateDirectoryReset ( +NcEnumerateDirectoryReset ( _Inout_ PNC_DIR_QRY_CONTEXT dirCtx ); @@ -818,9 +819,9 @@ NcPopulateCacheEntry ( _Out_ PNC_CACHE_ENTRY Cache ); -PNC_CACHE_ENTRY -NcDirEnumSelectNextEntry ( - _Inout_ PNC_DIR_QRY_CONTEXT Context, +PNC_CACHE_ENTRY +NcDirEnumSelectNextEntry ( + _Inout_ PNC_DIR_QRY_CONTEXT Context, _In_ PDIRECTORY_CONTROL_OFFSETS Offsets, _In_ BOOLEAN IgnoreCase ); @@ -828,7 +829,7 @@ NcDirEnumSelectNextEntry ( BOOLEAN NcSkipName ( _In_ PDIRECTORY_CONTROL_OFFSETS Offsets, - _In_ PNC_DIR_QRY_CONTEXT Context, + _In_ PNC_DIR_QRY_CONTEXT Context, _In_ NC_PATH_OVERLAP RealOverlap, _In_ PNC_MAPPING Mapping, _In_ BOOLEAN IgnoreCase @@ -836,22 +837,22 @@ NcSkipName ( _Success_(*Copied) ULONG -NcCopyDirEnumEntry ( - _Out_ PVOID UserBuffer, - _In_ ULONG UserOffset, - _In_ ULONG UserSize, +NcCopyDirEnumEntry ( + _Out_ PVOID UserBuffer, + _In_ ULONG UserOffset, + _In_ ULONG UserSize, _Inout_ PNC_CACHE_ENTRY Entry, _In_ PDIRECTORY_CONTROL_OFFSETS Offsets, - _Out_ PBOOLEAN Copied + _Out_ PBOOLEAN Copied ); NTSTATUS NcStreamHandleContextDirEnumCreate ( - _Out_ PNC_DIR_QRY_CONTEXT Context + _Out_ PNC_DIR_QRY_CONTEXT Context ); NTSTATUS -NcStreamHandleContextEnumSetup ( +NcStreamHandleContextEnumSetup ( _Inout_ PNC_DIR_QRY_CONTEXT DirContext, _In_ PNC_INSTANCE_CONTEXT InstanceContext, _In_ PDIRECTORY_CONTROL_OFFSETS Offsets, @@ -861,9 +862,9 @@ NcStreamHandleContextEnumSetup ( _Out_ PBOOLEAN FirstUsage ); -VOID +VOID NcStreamHandleContextEnumClose ( - _In_ PNC_DIR_QRY_CONTEXT DirContext + _In_ PNC_DIR_QRY_CONTEXT DirContext ); // @@ -885,19 +886,19 @@ NcPostNotifyDirectory ( _In_ FLT_POST_OPERATION_FLAGS Flags ); -NTSTATUS -NcStreamHandleContextNotCreate ( +NTSTATUS +NcStreamHandleContextNotCreate ( _Out_ PNC_DIR_NOT_CONTEXT Context ); -VOID +VOID NcStreamHandleContextNotCleanup( - _In_ PNC_STREAM_HANDLE_CONTEXT HandleContext + _In_ PNC_STREAM_HANDLE_CONTEXT HandleContext ); -VOID +VOID NcStreamHandleContextNotClose ( - _In_ PNC_DIR_NOT_CONTEXT DirContext + _In_ PNC_DIR_NOT_CONTEXT DirContext ); // @@ -970,10 +971,10 @@ NcPostEnumUsnData ( NTSTATUS NcStreamHandleContextFindBySidCreate ( - _Out_ PNC_FIND_BY_SID_CONTEXT Context + _Out_ PNC_FIND_BY_SID_CONTEXT Context ); -VOID +VOID NcStreamHandleContextFindBySidClose ( _In_ PNC_FIND_BY_SID_CONTEXT Context ); diff --git a/filesys/miniFilter/NameChanger/ncinit.c b/filesys/miniFilter/NameChanger/ncinit.c index d34dc0f06..7d125498a 100644 --- a/filesys/miniFilter/NameChanger/ncinit.c +++ b/filesys/miniFilter/NameChanger/ncinit.c @@ -15,7 +15,31 @@ NcIs8DOT3Compatible ( _In_opt_ PUNICODE_STRING LongName ); +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +NcGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +NcOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + #ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, NcGetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, NcOpenServiceParametersKey) #pragma alloc_text(INIT, NcInitializeMapping) #pragma alloc_text(INIT, NcLoadRegistryString) #pragma alloc_text(INIT, NcIs8DOT3Compatible) @@ -278,8 +302,147 @@ NcIs8DOT3Compatible ( } +PFN_IoOpenDriverRegistryKey +NcGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +NcOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible + // + + pIoOpenDriverRegistryKey = NcGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API + // + + status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + + } else { + + // + // Open specified service root key + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + + // + // Open the parameters key relative to service key path + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + } + + // + // Return value to caller + // + + *ServiceParametersKey = ParametersKey; + +cleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return status; + +} + NTSTATUS NcInitializeMapping( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -292,6 +455,9 @@ Routine Descrition: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -301,7 +467,6 @@ Return Value: --*/ { NTSTATUS Status; - OBJECT_ATTRIBUTES Attributes; HANDLE DriverRegKey = NULL; UNICODE_STRING TempPath = EMPTY_UNICODE_STRING; USHORT Index; @@ -311,22 +476,16 @@ Return Value: RtlZeroMemory( &NcGlobalData, sizeof( NcGlobalData )); // - // Open the mapping registry key. + // Open service parameters key to query values from. // - InitializeObjectAttributes( &Attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); - - Status = ZwOpenKey( &DriverRegKey, - KEY_READ, - &Attributes ); + Status = NcOpenServiceParametersKey( DriverObject, + RegistryPath, + &DriverRegKey ); if (!NT_SUCCESS( Status )) { - FLT_ASSERT( DriverRegKey == NULL ); + DriverRegKey = NULL; goto NcInitializeMappingCleanup; } diff --git a/filesys/miniFilter/avscan/avscan.inf b/filesys/miniFilter/avscan/avscan.inf index 2162f0b4d..cfc9c9abd 100644 Binary files a/filesys/miniFilter/avscan/avscan.inf and b/filesys/miniFilter/avscan/avscan.inf differ diff --git a/filesys/miniFilter/avscan/filter/avscan.c b/filesys/miniFilter/avscan/filter/avscan.c index 82e1045cd..3c96fd087 100644 --- a/filesys/miniFilter/avscan/filter/avscan.c +++ b/filesys/miniFilter/avscan/filter/avscan.c @@ -9,9 +9,9 @@ Module Name: Abstract: This is the main module of the avscan mini-filter driver. - This filter demonstrates how to implement a transaction-aware + This filter demonstrates how to implement a transaction-aware anti-virus filter. - + Av prefix denotes "Anti-virus" module. Environment: @@ -22,7 +22,7 @@ Module Name: #include #include "avscan.h" - + /************************************************************************* Local Function Prototypes *************************************************************************/ @@ -34,8 +34,32 @@ DriverEntry ( _In_ PUNICODE_STRING RegistryPath ); -NTSTATUS -AvSetConfiguration ( +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +AvGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +AvOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + + +NTSTATUS +AvSetConfiguration ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -112,20 +136,20 @@ AvKtmNotificationCallback ( _In_ PFLT_CONTEXT TransactionContext, _In_ ULONG TransactionNotification ); - + NTSTATUS AvScanAbortCallbackAsync ( _Unreferenced_parameter_ PFLT_INSTANCE Instance, _In_ PFLT_CONTEXT Context, _Unreferenced_parameter_ PFLT_CALLBACK_DATA Data ); - + // // Local routines // BOOLEAN -AvOperationsModifyingFile ( +AvOperationsModifyingFile ( _In_ PFLT_CALLBACK_DATA Data ); @@ -134,14 +158,14 @@ AvQueryTransactionOutcome( _In_ PKTRANSACTION Transaction, _Out_ PULONG TxOutcome ); - + NTSTATUS AvProcessPreviousTransaction ( _In_ PCFLT_RELATED_OBJECTS FltObjects, _Inout_ PAV_STREAM_CONTEXT StreamContext ); - -NTSTATUS + +NTSTATUS AvProcessTransactionOutcome ( _Inout_ PAV_TRANSACTION_CONTEXT TransactionContext, _In_ ULONG TransactionOutcome @@ -154,9 +178,9 @@ AvLoadFileStateFromCache ( _Out_ LONG volatile* State, _Out_ PLONGLONG VolumeRevision, _Out_ PLONGLONG CacheRevision, - _Out_ PLONGLONG FileRevision + _Out_ PLONGLONG FileRevision ); - + NTSTATUS AvSyncCache ( _In_ PFLT_INSTANCE Instance, @@ -168,12 +192,12 @@ AvIsPrefetchEcpPresent ( _In_ PFLT_FILTER Filter, _In_ PFLT_CALLBACK_DATA Data ); - + BOOLEAN AvIsStreamAlternate ( _Inout_ PFLT_CALLBACK_DATA Data ); - + NTSTATUS AvScan ( _Inout_ PFLT_CALLBACK_DATA Data, @@ -183,24 +207,26 @@ AvScan ( _In_ BOOLEAN IsInTxWriter, _Inout_ PAV_STREAM_CONTEXT StreamContext ); - + VOID AvDoCancelScanAndRelease ( _In_ PAV_SCAN_CONTEXT ScanContext, _In_ PAV_SECTION_CONTEXT SectionContext ); - + NTSTATUS -AvSendUnloadingToUser ( +AvSendUnloadingToUser ( VOID - ); - + ); + // // Assign text sections for each routine. // #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(INIT, AvGetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, AvOpenServiceParametersKey) #pragma alloc_text(INIT, AvSetConfiguration) #pragma alloc_text(PAGE, AvUnload) #pragma alloc_text(PAGE, AvInstanceQueryTeardown) @@ -225,7 +251,7 @@ AvSendUnloadingToUser ( #pragma alloc_text(PAGE, AvDoCancelScanAndRelease) #pragma alloc_text(PAGE, AvSendAbortToUser) #pragma alloc_text(PAGE, AvSendUnloadingToUser) -#endif +#endif // // operation registration @@ -251,7 +277,7 @@ CONST FLT_OPERATION_REGISTRATION Callbacks[] = { 0, AvPreOperationCallback, NULL }, - + { IRP_MJ_FILE_SYSTEM_CONTROL, 0, AvPreFsControl, @@ -330,7 +356,7 @@ Return Value: NTSTATUS status; PAV_INSTANCE_CONTEXT instanceContext = NULL; BOOLEAN isOnCsv = FALSE; - + UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); @@ -348,13 +374,13 @@ Return Value: } // - // Determine if the filter is attaching to the hidden NTFS volume - // that corresponds to a CSV volume. If so do not attach. Note - // that it would be feasible for the filter to attach to this + // Determine if the filter is attaching to the hidden NTFS volume + // that corresponds to a CSV volume. If so do not attach. Note + // that it would be feasible for the filter to attach to this // volume as part of a distrubuted filter implementation but that // is beyond the scope of this sample. // - + if (VolumeFilesystemType == FLT_FSTYPE_NTFS) { isOnCsv = AvIsVolumeOnCsvDisk( FltObjects->Volume ); if (isOnCsv) { @@ -362,7 +388,7 @@ Return Value: return STATUS_FLT_DO_NOT_ATTACH; } } - + status = FltAllocateContext( Globals.Filter, FLT_INSTANCE_CONTEXT, AV_INSTANCE_CONTEXT_SIZE, @@ -373,46 +399,46 @@ Return Value: AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvInstanceSetup: allocate instance context failed. status = 0x%x\n", status) ); - + return STATUS_FLT_DO_NOT_ATTACH; } // // Setup instance context // - + RtlZeroMemory(instanceContext, AV_INSTANCE_CONTEXT_SIZE); instanceContext->Volume = FltObjects->Volume; instanceContext->Instance = FltObjects->Instance; instanceContext->VolumeFSType = VolumeFilesystemType; instanceContext->IsOnCsvMDS = isOnCsv; - + // // There will be a file state cache table for each NTFS volume instance. - // As for other file systems, file id is not unique, and thus we do - // not have cache for other kinds of file systems. Since the cache - // table is not mandatory to implement an anti-virus filter, we + // As for other file systems, file id is not unique, and thus we do + // not have cache for other kinds of file systems. Since the cache + // table is not mandatory to implement an anti-virus filter, we // only have the volatile cache for NTFS, CSVFS and REFS. // - // It is worth mentioning that the table is potentially very large. - // We use an AVL tree to improve insertion and query times. We do not - // set an upper bound for the size of the tree which is not optimal. + // It is worth mentioning that the table is potentially very large. + // We use an AVL tree to improve insertion and query times. We do not + // set an upper bound for the size of the tree which is not optimal. // Consider limiting the size of the tree for a production filter. // - + if (FS_SUPPORTS_FILE_STATE_CACHE( VolumeFilesystemType )) { - + // // Initialize file state cache in the instance context. // ExInitializeResourceLite( &instanceContext->Resource ); - + RtlInitializeGenericTable( &instanceContext->FileStateCacheTable, AvCompareEntry, AvAllocateGenericTableEntry, AvFreeGenericTableEntry, - NULL ); + NULL ); } status = FltSetInstanceContext( FltObjects->Instance, @@ -435,22 +461,22 @@ Return Value: } // - // Register this instance as a datascan filter. If this call - // fails the underlying filesystem does not support using + // Register this instance as a datascan filter. If this call + // fails the underlying filesystem does not support using // the filter manager datascan API. Currently only the // the namedpipe and mailslot file systems are unsupported. - // - + // + status = FltRegisterForDataScan( FltObjects->Instance ); if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvInstanceSetup: FltRegisterForDataScan failed. status = 0x%x\n", status) ); return STATUS_FLT_DO_NOT_ATTACH; } - + return STATUS_SUCCESS; } @@ -525,36 +551,36 @@ Return Value: PLIST_ENTRY next; PAV_SCAN_CONTEXT scanCtx = NULL; PAV_INSTANCE_CONTEXT instanceContext = NULL; - + UNREFERENCED_PARAMETER( Flags ); PAGED_CODE(); - + AV_DBG_PRINT( AVDBG_TRACE_DEBUG, ("[AV] AvInstanceTeardownStart: Entered\n") ); - + status = FltGetInstanceContext( FltObjects->Instance, &instanceContext ); - + if (!NT_SUCCESS( status )) { AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvInstanceTeardownStart: FltGetInstanceContext failed. status = 0x%x\n", status) ); return; } - + // // Search the scan context from the global list. // - + AvAcquireResourceExclusive( &Globals.ScanCtxListLock ); - + LIST_FOR_EACH_SAFE( scan, next, &Globals.ScanCtxListHead ) { - + scanCtx = CONTAINING_RECORD( scan, AV_SCAN_CONTEXT, List ); - + if (scanCtx->FilterInstance != FltObjects->Instance) { - + continue; } @@ -564,45 +590,45 @@ Return Value: status = AvSendAbortToUser(scanCtx->ScanThreadId, scanCtx->ScanId); - + // - // If we fail to send message to the user, then we - // do the cancel and cleanup by ourself; otherwise, - // the listening thread will call back to cleanup and + // If we fail to send message to the user, then we + // do the cancel and cleanup by ourself; otherwise, + // the listening thread will call back to cleanup and // I/O request thred will tear down the scan context. // - + if (!NT_SUCCESS( status ) || status == STATUS_TIMEOUT) { AvFinalizeScanAndSection(scanCtx); } } - + AvReleaseResource( &Globals.ScanCtxListLock ); - + // // Clean up the cache table if the volume supports one. // - + if (FS_SUPPORTS_FILE_STATE_CACHE( instanceContext->VolumeFSType )) { PAV_GENERIC_TABLE_ENTRY entry = NULL; AvAcquireResourceExclusive( &instanceContext->Resource ); - + while (!RtlIsGenericTableEmpty( &instanceContext->FileStateCacheTable ) ) { entry = RtlGetElementGenericTable(&instanceContext->FileStateCacheTable, 0); AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, - ("[AV] AvInstanceTeardownStart: %I64x,%I64x requesting deletion, state:%d\n", + ("[AV] AvInstanceTeardownStart: %I64x,%I64x requesting deletion, state:%d\n", entry->FileId.FileId64.UpperZeroes, entry->FileId.FileId64.Value, entry->InfectedState) ); RtlDeleteElementGenericTable(&instanceContext->FileStateCacheTable, entry); } - + AvReleaseResource( &instanceContext->Resource ); } - + FltReleaseContext( instanceContext ); - + FltDeleteInstanceContext( FltObjects->Instance, NULL ); } @@ -673,15 +699,13 @@ Return Value: NTSTATUS status = STATUS_SUCCESS; PSECURITY_DESCRIPTOR sd = NULL; - UNREFERENCED_PARAMETER( RegistryPath ); - AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] DriverEntry: Entered\n") ); // // Set default global configuration // - + RtlZeroMemory( &Globals, sizeof(Globals) ); InitializeListHead( &Globals.ScanCtxListHead ); ExInitializeResourceLite( &Globals.ScanCtxListLock ); @@ -691,7 +715,7 @@ Return Value: Globals.NetworkScanTimeout = 60000; #if DBG - + Globals.DebugLevel = 0xffffffff; // AVDBG_TRACE_ERROR | AVDBG_TRACE_DEBUG; #endif @@ -702,7 +726,7 @@ Return Value: // Set the filter configuration based on registry keys // - status = AvSetConfiguration( RegistryPath ); + status = AvSetConfiguration( DriverObject, RegistryPath ); if (!NT_SUCCESS( status )) { @@ -710,7 +734,7 @@ Return Value: ("[AV]: DriverEntry: SetConfiguration FAILED. status = 0x%x\n", status) ); leave; - } + } // // Register with FltMgr to tell it our callback routines @@ -721,19 +745,19 @@ Return Value: &Globals.Filter ); if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] DriverEntry: FltRegisterFilter FAILED. status = 0x%x\n", status) ); leave; } - + // // Builds a default security descriptor for use with FltCreateCommunicationPort. // - + status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS ); - + if (!NT_SUCCESS( status )) { @@ -744,34 +768,34 @@ Return Value: // // Prepare ports between kernel and user. // - + status = AvPrepareServerPort( sd, AvConnectForScan ); - + if (!NT_SUCCESS( status )) { AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] DriverEntry: AvPrepareServerPort Scan Port FAILED. status = 0x%x\n", status) ); leave; } - + status = AvPrepareServerPort( sd, AvConnectForAbort ); - + if (!NT_SUCCESS( status )) { AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] DriverEntry: AvPrepareServerPort Abort Port FAILED. status = 0x%x\n", status) ); leave; } - + status = AvPrepareServerPort( sd, AvConnectForQuery ); - + if (!NT_SUCCESS( status )) { AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] DriverEntry: AvPrepareServerPort Query Port FAILED. status = 0x%x\n", status) ); leave; } - + // // Start filtering i/o // @@ -784,16 +808,16 @@ Return Value: ("[AV] DriverEntry: FltStartFiltering FAILED. status = 0x%x\n", status) ); leave; } - + } finally { - + if ( sd != NULL ) { - + FltFreeSecurityDescriptor( sd ); } - + if (!NT_SUCCESS( status ) ) { - + if (NULL != Globals.ScanServerPort) { FltCloseCommunicationPort( Globals.ScanServerPort ); @@ -807,13 +831,13 @@ Return Value: FltCloseCommunicationPort( Globals.QueryServerPort ); } if (NULL != Globals.Filter) { - + FltUnregisterFilter( Globals.Filter ); Globals.Filter = NULL; } - ExDeleteResourceLite( &Globals.ScanCtxListLock ); - } + ExDeleteResourceLite( &Globals.ScanCtxListLock ); + } } return status; @@ -848,20 +872,20 @@ Return Value: AV_DBG_PRINT( AVDBG_TRACE_DEBUG, ("[AV] AvUnload: Entered\n") ); - + // // Traverse the scan context list, and cancel the scan if it exists. // - + AvAcquireResourceExclusive( &Globals.ScanCtxListLock ); Globals.Unloading = TRUE; AvReleaseResource( &Globals.ScanCtxListLock ); - + // - // This function will wait for the user to abort the outstanding scan and - // close the section + // This function will wait for the user to abort the outstanding scan and + // close the section // - + AvSendUnloadingToUser(); FltCloseCommunicationPort( Globals.ScanServerPort ); @@ -872,7 +896,7 @@ Return Value: Globals.QueryServerPort = NULL; FltUnregisterFilter( Globals.Filter ); // This will typically trigger instance tear down. Globals.Filter = NULL; - + ExDeleteResourceLite( &Globals.ScanCtxListLock ); return STATUS_SUCCESS; @@ -884,7 +908,7 @@ Return Value: *************************************************************************/ BOOLEAN -AvOperationsModifyingFile ( +AvOperationsModifyingFile ( _In_ PFLT_CALLBACK_DATA Data ) /*++ @@ -905,14 +929,14 @@ Return Value: --*/ { PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb; - + PAGED_CODE(); switch(iopb->MajorFunction) { - + case IRP_MJ_WRITE: return TRUE; - + case IRP_MJ_FILE_SYSTEM_CONTROL: switch ( iopb->Parameters.FileSystemControl.Common.FsControlCode ) { case FSCTL_OFFLOAD_WRITE: @@ -922,7 +946,7 @@ Return Value: default: break; } break; - + case IRP_MJ_SET_INFORMATION: switch ( iopb->Parameters.SetFileInformation.FileInformationClass ) { case FileEndOfFileInformation: @@ -947,11 +971,11 @@ AvQueryTransactionOutcome( Routine Description: This is a helper function that qeury the KTM that how trasnaction was ended. - + Arguments: Transaction - Pointer to transaction object. - + TxOutcome - Output. Specifies the type of transaction outcome. Return Value: @@ -962,9 +986,9 @@ Return Value: HANDLE transactionHandle; NTSTATUS status; TRANSACTION_BASIC_INFORMATION txBasicInfo = {0}; - + PAGED_CODE(); - + status = ObOpenObjectByPointer( Transaction, OBJ_KERNEL_HANDLE, NULL, @@ -972,9 +996,9 @@ Return Value: *TmTransactionObjectType, KernelMode, &transactionHandle ); - + if (!NT_SUCCESS(status)) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvQueryTransactionOutcome: ObOpenObjectByPointer failed.\n") ); return status; @@ -986,18 +1010,18 @@ Return Value: sizeof(TRANSACTION_BASIC_INFORMATION), NULL ); if (!NT_SUCCESS(status)) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvQueryTransactionOutcome: ObOpenObjectByPointer failed.\n") ); goto Cleanup; } - + *TxOutcome = txBasicInfo.Outcome; - + Cleanup: ZwClose(transactionHandle); - + return status; } @@ -1012,46 +1036,46 @@ AvPropagateFileState( Routine Description: An inline function that propagate the TxState to State in stream context. - + Arguments: StreamContext - The stream context to be propagated. - + TransactionOutcome - TRANSACTION_OUTCOME enumeration indicating how transaction was ended. - + Return Value: None. - + --*/ { // // Only when the transaction was committed will we propagate the state. // - + if (TransactionOutcome == TransactionOutcomeCommitted) { - + AV_FILE_INFECTED_STATE oldTxState = InterlockedExchange( &StreamContext->TxState, AvFileModified ); switch (oldTxState) { case AvFileModified: case AvFileInfected: case AvFileNotInfected: - + // // Propagate the file state from TxState to State. // - + InterlockedExchange( &StreamContext->State, oldTxState ); break; case AvFileScanning: - + // // It is possible at KTM callback, file Tx state is still in scanning. - // All we can do here is to be conservative, that is to assume that + // All we can do here is to be conservative, that is to assume that // this commit did involve the modification of the file. // - + InterlockedExchange( &StreamContext->State, AvFileModified ); break; default: @@ -1059,15 +1083,15 @@ Return Value: break; } } - + // // Either cleanup or commited, we need to reset TxState to be default state. // - + SET_FILE_TX_MODIFIED( StreamContext ); } -NTSTATUS +NTSTATUS AvProcessTransactionOutcome ( _Inout_ PAV_TRANSACTION_CONTEXT TransactionContext, _In_ ULONG TransactionOutcome @@ -1076,21 +1100,21 @@ AvProcessTransactionOutcome ( Routine Description: - This is a helper function that process transaction commitment or rollback - + This is a helper function that process transaction commitment or rollback + Arguments: TransactionContext - Pointer to the minifilter driver's transaction context set at PostCreate. - + TransactionOutcome - Specifies the type of notifications. Should be either TransactionOutcomeCommitted or TransactionOutcomeAborted Return Value: - STATUS_SUCCESS - Returning this status value indicates that the minifilter + STATUS_SUCCESS - Returning this status value indicates that the minifilter driver is finished with the transaction. This is a success code. - + --*/ { PLIST_ENTRY scan; @@ -1099,7 +1123,7 @@ Return Value: PAV_TRANSACTION_CONTEXT oldTxCtx = NULL; PAGED_CODE(); - + // // Tranversing the stream context list, and // sync the TxState -> State. @@ -1107,21 +1131,21 @@ Return Value: // Either commit or rollback, we need to cleanup the list // Tear down stream context list inside transactionContext // - + AvAcquireResourceExclusive( TransactionContext->Resource ); - + LIST_FOR_EACH_SAFE( scan, next, &TransactionContext->ScListHead ) { - + streamContext = CONTAINING_RECORD( scan, AV_STREAM_CONTEXT, ListInTransaction ); oldTxCtx = InterlockedCompareExchangePointer( &streamContext->TxContext, NULL, TransactionContext ); if (oldTxCtx == TransactionContext) { - + // // The exchange pointer was successful // RemoveEntryList ( scan ); - + AV_DBG_PRINT( AVDBG_TRACE_DEBUG, ("[AV] AvProcessTransactionOutcome: Requesting deletion of entry in transaction context: %I64x,%I64x, modified: %d\n", streamContext->FileId.FileId64.UpperZeroes, @@ -1134,7 +1158,7 @@ Return Value: } SetFlag( TransactionContext->Flags, AV_TXCTX_LISTDRAINED ); AvReleaseResource( TransactionContext->Resource ); - + return STATUS_SUCCESS; } @@ -1145,20 +1169,20 @@ AvLoadFileStateFromCache ( _Out_ LONG volatile *State, _Out_ PLONGLONG VolumeRevision, _Out_ PLONGLONG CacheRevision, - _Out_ PLONGLONG FileRevision + _Out_ PLONGLONG FileRevision ) /*++ Routine Description: - This routine lookups the file state in the cache table. + This routine lookups the file state in the cache table. Arguments: Instance - Opaque filter pointer for the caller. This parameter is required and cannot be NULL. - + FileID - The ID to lookup in the cache - + State - The cached state for the file Return Value: @@ -1171,7 +1195,7 @@ Return Value: PAV_INSTANCE_CONTEXT instanceContext = NULL; AV_GENERIC_TABLE_ENTRY query = {0}; PAV_GENERIC_TABLE_ENTRY entry = NULL; - + PAGED_CODE(); // @@ -1195,8 +1219,8 @@ Return Value: goto Cleanup; } - RtlCopyMemory( &query.FileId, FileId, sizeof(query.FileId) ); - + RtlCopyMemory( &query.FileId, FileId, sizeof(query.FileId) ); + AvAcquireResourceShared( &instanceContext->Resource ); entry = RtlLookupElementGenericTable( &instanceContext->FileStateCacheTable, @@ -1234,9 +1258,9 @@ Routine Description: Arguments: Instance - Opaque filter pointer for the caller. This parameter is required and cannot be NULL. - + StreamContext - The stream context of the target file. - + Return Value: Returns the final status of this operation. @@ -1274,7 +1298,7 @@ Return Value: } // - // If originally, we failed to get the file id, + // If originally, we failed to get the file id, // then we do not cache it. // @@ -1286,7 +1310,7 @@ Return Value: // If the file system is NTFS, CSVFS or REFS, overwrite the entry in the // cache table if exists // - + RtlCopyMemory( &entry.FileId, &StreamContext->FileId, sizeof(entry.FileId) ); AvAcquireResourceExclusive( &instanceContext->Resource ); @@ -1302,9 +1326,9 @@ Return Value: // // - // It is possible that after entering the following else-if - // branch, thread A modifies the file, and before thread A - // closes the handle, thread B opens the same file. This + // It is possible that after entering the following else-if + // branch, thread A modifies the file, and before thread A + // closes the handle, thread B opens the same file. This // is fine because in such a case, the streamcontext exists // AvLoadFileStateFromCache would return the state in stream // context. Thus, thread B will need to scan the file. @@ -1327,7 +1351,7 @@ Return Value: Cleanup: FltReleaseContext( instanceContext ); - return status; + return status; } BOOLEAN @@ -1340,13 +1364,13 @@ AvIsPrefetchEcpPresent ( Routine Description: This local function will return if this data stream is alternate or not. - It by default returns FALSE if it fails to retrieve the name information + It by default returns FALSE if it fails to retrieve the name information from the file system. - + Arguments: Data - Pointer to the filter callbackData that is passed to us. - + Return Value: TRUE - This data stream is alternate. @@ -1357,13 +1381,13 @@ Return Value: NTSTATUS status; PECP_LIST ecpList; PVOID ecpContext; - + PAGED_CODE(); status = FltGetEcpListFromCallbackData( Filter, Data, &ecpList ); if (NT_SUCCESS(status) && (ecpList != NULL)) { - + status = FltFindExtraCreateParameter( Filter, ecpList, &GUID_ECP_PREFETCH_OPEN, @@ -1373,7 +1397,7 @@ Return Value: if (NT_SUCCESS(status)) { if (!FltIsEcpFromUserMode( Filter, ecpContext )) { - return TRUE; + return TRUE; } } } @@ -1390,13 +1414,13 @@ AvIsStreamAlternate( Routine Description: This local function will return if this data stream is alternate or not. - It by default returns FALSE if it fails to retrieve the name information + It by default returns FALSE if it fails to retrieve the name information from the file system. - + Arguments: Data - Pointer to the filter callbackData that is passed to us. - + Return Value: TRUE - This data stream is alternate. @@ -1409,32 +1433,32 @@ Return Value: PFLT_FILE_NAME_INFORMATION nameInfo = NULL; PAGED_CODE(); - + status = FltGetFileNameInformation( Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &nameInfo ); - + if (!NT_SUCCESS(status)) { - + goto Cleanup; } status = FltParseFileNameInformation( nameInfo ); if (!NT_SUCCESS(status)) { - + goto Cleanup; } AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, - ("[Av]: Dir: %wZ, FinalComponent: %wZ, Stream: %wZ, sLen: %d\n", + ("[Av]: Dir: %wZ, FinalComponent: %wZ, Stream: %wZ, sLen: %d\n", nameInfo->ParentDir, nameInfo->FinalComponent, nameInfo->Stream, nameInfo->Stream.Length) ); - + alternate = (nameInfo->Stream.Length > 0); - + Cleanup: if (nameInfo != NULL) { @@ -1466,13 +1490,13 @@ Routine Description: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing opaque handles to this filter, instance, its associated volume and file object. - + ScanMode - Can either be AvUserMode or AvKernelMode. - + IOMajorFunctionAtScan - Major function of an IRP. - + StreamContext - The stream context of the target file. - + Return Value: Returns the final status of this operation. @@ -1485,20 +1509,20 @@ Return Value: LONGLONG fileSize; FLT_VOLUME_PROPERTIES volumeProperties; ULONG volumePropertiesLength; - + PAGED_CODE(); - + // // Skip the empty file. // - + status = AvGetFileSize( FltObjects->Instance, - FltObjects->FileObject, + FltObjects->FileObject, &fileSize ); - if (NT_SUCCESS( status ) && + if (NT_SUCCESS( status ) && (0 == fileSize)) { - + AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[Av]: AvScan: Skip the EMPTY file.\n") ); @@ -1511,9 +1535,9 @@ Return Value: // We could cause deadlocks if the thread were suspended once // we have started scanning so enter a critical region. // - + FsRtlEnterFileSystem(); - + // // Wait here for an existing scan on the stream to complete. // We wait indefinitely since scans themselves will timeout. @@ -1531,7 +1555,7 @@ Return Value: // if (IS_FILE_NEED_SCAN( StreamContext )){ - + if (ScanMode == AvUserMode) { status = FltGetVolumeProperties( FltObjects->Volume, @@ -1541,21 +1565,21 @@ Return Value: if (!NT_SUCCESS(status)) { volumeProperties.DeviceType = FILE_DEVICE_NETWORK; } - + // - // If the scan mode is user mode, the section context will + // If the scan mode is user mode, the section context will // be created as needed (at MessageNotification callback). // - // Setting the file state will be done at + // Setting the file state will be done at // MessageNotification callback as well. // - + status = AvScanInUser( Data, FltObjects, IOMajorFunctionAtScan, IsInTxWriter, volumeProperties.DeviceType ); - + if (!NT_SUCCESS( status ) || status == STATUS_TIMEOUT) { AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, @@ -1564,37 +1588,37 @@ Return Value: } else { - status = AvScanInKernel( FltObjects, + status = AvScanInKernel( FltObjects, IOMajorFunctionAtScan, IsInTxWriter, StreamContext ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] AvScan: failed to scan the file.\n") ); } } - + } // // Signal ScanSynchronizationEvent to release any con-current scan of the stream, - // - KeSetEvent( StreamContext->ScanSynchronizationEvent, 0, FALSE ); + // + KeSetEvent( StreamContext->ScanSynchronizationEvent, 0, FALSE ); } else if (IOMajorFunctionAtScan == IRP_MJ_CREATE) { // - // I/O requesting thread if waiting on synchronization event is cancelled, + // I/O requesting thread if waiting on synchronization event is cancelled, // we need to clean up the file object too. // AvCancelFileOpen(Data, FltObjects, status); } - + FsRtlExitFileSystem(); - + return status; } @@ -1612,7 +1636,7 @@ Routine Description: Arguments: ScanContext - The scan context. - + SectionContext - The section context associated with the scan context. Return Value: @@ -1623,9 +1647,9 @@ Return Value: { NTSTATUS status; PAV_STREAM_CONTEXT streamContext = NULL; - + PAGED_CODE(); - + AvFinalizeSectionContext( SectionContext ); status = FltGetStreamContext( ScanContext->FilterInstance, @@ -1633,21 +1657,21 @@ Return Value: &streamContext ); if (NT_SUCCESS( status )) { - + KeSetEvent( streamContext->ScanSynchronizationEvent, 0, FALSE ); FltReleaseContext( streamContext ); } - + // // Release I/O request thread. // - + KeSetEvent( &ScanContext->ScanCompleteNotification, 0, FALSE ); return; } NTSTATUS -AvSendAbortToUser ( +AvSendAbortToUser ( _In_ ULONG ScanThreadId, _In_ LONGLONG ScanId ) @@ -1656,7 +1680,7 @@ AvSendAbortToUser ( Routine Description: This routine sends an abortion message to the user scan thread. - The cancel callback is asynchronous and thus we send which + The cancel callback is asynchronous and thus we send which scan id to abort; otherwise the worker thread in the user may abort the 'next' scan task. @@ -1676,19 +1700,19 @@ Return Value: ULONG replyLength = 0; LARGE_INTEGER timeout = {0}; AV_SCANNER_NOTIFICATION notification = {0}; - + PAGED_CODE(); - + notification.Message = AvMsgAbortScanning; notification.ScanThreadId = ScanThreadId; notification.ScanId = ScanId; - + timeout.QuadPart = -((LONGLONG)10) * (LONGLONG)1000 * (LONGLONG)1000; // 1s - + // // Tell the user-scanner to abort the scan. // - + status = FltSendMessage( Globals.Filter, &Globals.AbortClientPort, ¬ification, @@ -1697,11 +1721,11 @@ Return Value: &replyLength, &timeout ); - - if (!NT_SUCCESS( status ) || + + if (!NT_SUCCESS( status ) || (status == STATUS_TIMEOUT)) { - - if ((status != STATUS_PORT_DISCONNECTED) && + + if ((status != STATUS_PORT_DISCONNECTED) && (status != STATUS_TIMEOUT)) { AV_DBG_PRINT( AVDBG_TRACE_ERROR, @@ -1714,7 +1738,7 @@ Return Value: } NTSTATUS -AvSendUnloadingToUser ( +AvSendUnloadingToUser ( VOID ) /*++ @@ -1737,19 +1761,19 @@ Return Value: NTSTATUS status = STATUS_SUCCESS; ULONG replyLength = sizeof(ULONG); AV_SCANNER_NOTIFICATION notification = {0}; - + PAGED_CODE(); - + notification.Message = AvMsgFilterUnloading; - + // // Tell the user-scanner that we are unloading the filter. // and waits for its reply. // - + AV_DBG_PRINT( AVDBG_TRACE_DEBUG, ("[Av]: AvSendUnloadingToUser: BEFORE...\n") ); - + status = FltSendMessage( Globals.Filter, &Globals.AbortClientPort, ¬ification, @@ -1757,17 +1781,17 @@ Return Value: &abortThreadId, &replyLength, NULL ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[Av]: AvSendUnloadingToUser: Failed to FltSendMessage.\n, 0x%08x\n", status) ); } - + AV_DBG_PRINT( AVDBG_TRACE_DEBUG, ("[Av]: AvSendUnloadingToUser: After...\n") ); - + return status; } @@ -1785,8 +1809,8 @@ AvPreOperationCallback ( Routine Description: - This routine is the registered callback routine for filtering - the "write" operation, i.e. the operations that have potentials + This routine is the registered callback routine for filtering + the "write" operation, i.e. the operations that have potentials to modify the file. This is non-pageable because it could be called on the paging path @@ -1799,7 +1823,7 @@ Routine Description: opaque handles to this filter, instance, its associated volume and file object. - CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or + CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or FLT_PREOP_SYNCHRONIZE, this parameter is an optional context pointer to be passed to the corresponding post-operation callback routine. Otherwise, it must be NULL. @@ -1813,21 +1837,21 @@ Return Value: PAV_STREAM_CONTEXT streamContext = NULL; PAV_STREAMHANDLE_CONTEXT streamHandleContext = NULL; ULONG flags; - + UNREFERENCED_PARAMETER( CompletionContext ); AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] AvPreOperationCallback: Entered\n") ); if (!AvOperationsModifyingFile(Data)) { - + return FLT_PREOP_SUCCESS_NO_CALLBACK; } // // Skip prefetcher handles to avoid deadlocks // - + status = FltGetStreamHandleContext( FltObjects->Instance, FltObjects->FileObject, &streamHandleContext ); @@ -1836,20 +1860,20 @@ Return Value: flags = streamHandleContext->Flags; FltReleaseContext( streamHandleContext ); - + if (FlagOn( flags, AV_FLAG_PREFETCH )) { return FLT_PREOP_SUCCESS_NO_CALLBACK; - } + } } status = FltGetStreamContext( FltObjects->Instance, FltObjects->FileObject, &streamContext ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, - ("[AV] AvPreOperationCallback: get stream context failed. rq: %d\n", + ("[AV] AvPreOperationCallback: get stream context failed. rq: %d\n", Data->Iopb->MajorFunction) ); return FLT_PREOP_SUCCESS_NO_CALLBACK; @@ -1858,10 +1882,10 @@ Return Value: // // If this operation is performed in a transacted writer view. // - + if ((streamContext->TxContext != NULL) && (FltObjects->Transaction != NULL)) { - + #if DBG PAV_TRANSACTION_CONTEXT transactionContext = NULL; @@ -1870,32 +1894,32 @@ Return Value: &transactionContext ); FLT_ASSERTMSG( "Transaction context should not fail, because it is supposed to be created at post create.\n", NT_SUCCESS( statusTx )); - FLT_ASSERTMSG( "The file's TxCtx should be identical with the target TxCtx.\n", + FLT_ASSERTMSG( "The file's TxCtx should be identical with the target TxCtx.\n", streamContext->TxContext == transactionContext); if (NT_SUCCESS( statusTx )) { FltReleaseContext( transactionContext ); } - + #endif // DBG - + // - // Instead of updating State, we update TxState here, + // Instead of updating State, we update TxState here, // because the file is part of a transaction writer // - + SET_FILE_TX_MODIFIED( streamContext ); - + } else { - + // // Consider an optimization for the case where another thread // is already scanning the file as it is being modified here. // - + SET_FILE_MODIFIED( streamContext ); } - + FltReleaseContext( streamContext ); return FLT_PREOP_SUCCESS_NO_CALLBACK; @@ -1922,7 +1946,7 @@ Routine Description: opaque handles to this filter, instance, its associated volume and file object. - CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or + CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or FLT_PREOP_SYNCHRONIZE, this parameter is an optional context pointer to be passed to the corresponding post-operation callback routine. Otherwise, it must be NULL. @@ -1934,15 +1958,15 @@ Return Value: { PAGED_CODE(); - + if (Data->Iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_TXFS_SAVEPOINT_INFORMATION ) { - - // + + // // We explicitly fail the request of save point here since we // are deprecating savepoint support for the OS version targeted - // for this filter. + // for this filter. // - + Data->IoStatus.Status = STATUS_NOT_SUPPORTED; return FLT_PREOP_COMPLETE; } @@ -1960,7 +1984,7 @@ AvPreCreate ( Routine Description: This routine is the pre-create completion routine. - + Arguments: @@ -1970,7 +1994,7 @@ Routine Description: opaque handles to this filter, instance, its associated volume and file object. - CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or + CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or FLT_PREOP_SYNCHRONIZE, this parameter is an optional context pointer to be passed to the corresponding post-operation callback routine. Otherwise, it must be NULL. @@ -1985,33 +2009,33 @@ Return Value: ULONG_PTR stackHigh; PFILE_OBJECT FileObject = Data->Iopb->TargetFileObject; AV_STREAMHANDLE_CONTEXT streamHandleContext; - - + + PAGED_CODE(); AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] AvPreCreate: Entered\n") ); streamHandleContext.Flags = 0; - + // // Stack file objects are never scanned. // IoGetStackLimits( &stackLow, &stackHigh ); - if (((ULONG_PTR)FileObject > stackLow) && + if (((ULONG_PTR)FileObject > stackLow) && ((ULONG_PTR)FileObject < stackHigh)) { return FLT_PREOP_SUCCESS_NO_CALLBACK; } - + // // Directory opens don't need to be scanned. // if (FlagOn( Data->Iopb->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { - + return FLT_PREOP_SUCCESS_NO_CALLBACK; } @@ -2020,27 +2044,27 @@ Return Value: // if ( FlagOn( Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY )) { - + return FLT_PREOP_SUCCESS_NO_CALLBACK; } - + // // Skip paging files. // if (FlagOn( Data->Iopb->OperationFlags, SL_OPEN_PAGING_FILE )) { - + return FLT_PREOP_SUCCESS_NO_CALLBACK; } // - // Skip scanning DASD opens + // Skip scanning DASD opens // - + if (FlagOn( FltObjects->FileObject->Flags, FO_VOLUME_OPEN )) { - return FLT_PREOP_SUCCESS_NO_CALLBACK; - } + return FLT_PREOP_SUCCESS_NO_CALLBACK; + } // // Skip scanning any files being opened by CSVFS for its downlevel @@ -2049,10 +2073,10 @@ Return Value: // if (AvIsCsvDlEcpPresent( FltObjects->Filter, Data ) ) { - return FLT_PREOP_SUCCESS_NO_CALLBACK; + return FLT_PREOP_SUCCESS_NO_CALLBACK; } - + // // Flag prefetch handles so they can be skipped. Performing IO // using a prefetch fileobject could lead to a deadlock. @@ -2060,7 +2084,7 @@ Return Value: if (AvIsPrefetchEcpPresent( FltObjects->Filter, Data )) { - SetFlag( streamHandleContext.Flags, AV_FLAG_PREFETCH ); + SetFlag( streamHandleContext.Flags, AV_FLAG_PREFETCH ); } *CompletionContext = (PVOID)streamHandleContext.Flags; @@ -2069,17 +2093,17 @@ Return Value: // Perform any CSVFS pre create processing // AvPreCreateCsvfs( Data, FltObjects ); - + // // return status can be safely ignored // - + // - // Return FLT_PREOP_SYNCHRONIZE at PreCreate to ensure PostCreate - // is in the same thread at passive level. + // Return FLT_PREOP_SYNCHRONIZE at PreCreate to ensure PostCreate + // is in the same thread at passive level. // EResource can't be acquired at DPC. // - + return FLT_PREOP_SYNCHRONIZE; } @@ -2093,8 +2117,8 @@ AvProcessPreviousTransaction ( Routine Description: - This routine is transaction related implementation, and is expected to be - invoked at post-create. Note that this function will enlist the newly + This routine is transaction related implementation, and is expected to be + invoked at post-create. Note that this function will enlist the newly allocated transaction context via FltEnlistInTransaction if it needs to. Arguments: @@ -2114,45 +2138,45 @@ Return Value: NTSTATUS status = STATUS_SUCCESS; PAV_TRANSACTION_CONTEXT oldTxCtx = NULL; PAV_TRANSACTION_CONTEXT transactionContext = NULL; - + PAGED_CODE(); - if (FltObjects->Transaction != NULL ) { - + if (FltObjects->Transaction != NULL ) { + // // Get transaction context // status = AvFindOrCreateTransactionContext( FltObjects, &transactionContext ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvProcessPreviousTransaction: AvFindOrCreateTransactionContext FAILED\n") ); transactionContext = NULL; goto Cleanup; } - + // // Enlist it if haven't. // - + if (! FlagOn(transactionContext->Flags, AV_TXCTX_ENLISTED) ) { // - // You can also consider to register TRANSACTION_NOTIFY_PREPARE, + // You can also consider to register TRANSACTION_NOTIFY_PREPARE, // and scan the file at TRANSACTION_NOTIFY_PREPARE callback if it was modified. // - + status = FltEnlistInTransaction( FltObjects->Instance, FltObjects->Transaction, transactionContext, TRANSACTION_NOTIFY_COMMIT_FINALIZE | TRANSACTION_NOTIFY_ROLLBACK ); - + if (!NT_SUCCESS( status ) && (status != STATUS_FLT_ALREADY_ENLISTED)) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvProcessPreviousTransaction: FltEnlistInTransaction FAILED!!!!\n") ); goto Cleanup; @@ -2181,113 +2205,113 @@ Return Value: // oldTxCtx : NULL // transCtx : NULL // - + // // Synchronize the replacement of StreamContext->TxContext with KTM callback. // - + oldTxCtx = InterlockedExchangePointer( &StreamContext->TxContext, transactionContext ); - + if (oldTxCtx != transactionContext) { // case 1,2,3 - + // - // txOutcome is by default set as committed because we are conservative about - // propagating the file state if AvQueryTransactionOutcome failed, it may cause + // txOutcome is by default set as committed because we are conservative about + // propagating the file state if AvQueryTransactionOutcome failed, it may cause // redundant scan but will not overlook infected file anyway. // - + ULONG txOutcome = TransactionOutcomeCommitted; if ( oldTxCtx == NULL ) { // case 1 - + // This file was not linked in a transaction context yet, and is about to. // // Increment TxContext's reference count because stream context has a reference to it. // - + FltReferenceContext ( transactionContext ); - + // // Before insertion into the FcList in transaction context, we increment stream context's ref count // - + AvAcquireResourceExclusive( transactionContext->Resource ); - + if (!FlagOn(transactionContext->Flags, AV_TXCTX_LISTDRAINED)) { - + FltReferenceContext ( StreamContext ); // Q InsertTailList( &transactionContext->ScListHead, &StreamContext->ListInTransaction ); } - + AvReleaseResource( transactionContext->Resource ); - + goto Cleanup; } // case 2,3 - + // - // We have to query transaction outcome in order to know how we + // We have to query transaction outcome in order to know how we // can process the previously outstanding transaction context. // - + status = AvQueryTransactionOutcome( oldTxCtx->Transaction, &txOutcome ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvProcessPreviousTransaction: AvQueryTransactionOutcome FAILED!!!!\n") ); - + // - // We have exchanged the pointer anyway, if we cannot query its outcome, + // We have exchanged the pointer anyway, if we cannot query its outcome, // we have to go through. // } - + AvAcquireResourceExclusive( oldTxCtx->Resource ); RemoveEntryList ( &StreamContext->ListInTransaction ); AvReleaseResource( oldTxCtx->Resource ); - + AvPropagateFileState ( StreamContext, txOutcome ); - + if ( transactionContext ) { // case 3 - + FltReferenceContext( transactionContext ); - + AvAcquireResourceExclusive( transactionContext->Resource ); if (!FlagOn(transactionContext->Flags, AV_TXCTX_LISTDRAINED)) { - + InsertTailList( &transactionContext->ScListHead, &StreamContext->ListInTransaction ); } else { - + FltReleaseContext( StreamContext ); } - + AvReleaseResource( transactionContext->Resource ); - + } else { // case 2 - + FltReleaseContext ( StreamContext ); // Release reference count at Q } - + // case 2,3 - + FltReleaseContext( oldTxCtx ); // Release reference count in stream context originally. - + } - + // // We don't care about case 4, 5. // - + Cleanup: if (transactionContext) { - + FltReleaseContext( transactionContext ); // Release the ref count grabbed at AvFindOrCreateTransactionContext(...) } @@ -2307,8 +2331,8 @@ Routine Description: This routine is the post-create completion routine. In this routine, stream context and/or transaction context shall be created if not exits. - - Note that we only allocate and set the stream context to filter manager + + Note that we only allocate and set the stream context to filter manager at post create. Arguments: @@ -2332,7 +2356,7 @@ Return Value: NTSTATUS status = Data->IoStatus.Status; BOOLEAN isDir = FALSE; BOOLEAN isTxWriter = FALSE; - + PAV_STREAM_CONTEXT streamContext = NULL; PAV_STREAM_CONTEXT oldStreamContext = NULL; PAV_STREAMHANDLE_CONTEXT streamHandleContext = NULL; @@ -2340,15 +2364,15 @@ Return Value: BOOLEAN updateRevisionNumbers; LONGLONG VolumeRevision, CacheRevision, FileRevision; - + UNREFERENCED_PARAMETER( CompletionContext ); UNREFERENCED_PARAMETER( Flags ); - + PAGED_CODE(); - + if (!NT_SUCCESS( status ) || (status == STATUS_REPARSE)) { - + // // File Creation may fail. // @@ -2358,7 +2382,7 @@ Return Value: return FLT_POSTOP_FINISHED_PROCESSING; } - + // // After creation, skip it if it is directory. // @@ -2366,29 +2390,29 @@ Return Value: status = FltIsDirectory( FltObjects->FileObject, FltObjects->Instance, &isDir ); - + // // If FltIsDirectory failed, we do not know if it is a directoy, // we let it go through because if it is a directory, it will fail // at section creation anyway. // - + if ( NT_SUCCESS( status ) && isDir ) { - + return FLT_POSTOP_FINISHED_PROCESSING; } // // We skip the encrypted file open without FILE_WRITE_DATA and FILE_READ_DATA - // This is because if application calls OpenEncryptedFileRaw(...) for backup, - // it won't have to decrypt the file. In such case, if we scan it, we will hit + // This is because if application calls OpenEncryptedFileRaw(...) for backup, + // it won't have to decrypt the file. In such case, if we scan it, we will hit // an assertion error in NTFS because it does not have the encryption context. // Thus, we have to skip the encrypted file not open for read/write. // - - if (!(FlagOn(desiredAccess, FILE_WRITE_DATA)) && + + if (!(FlagOn(desiredAccess, FILE_WRITE_DATA)) && !(FlagOn(desiredAccess, FILE_READ_DATA)) ) { - + BOOLEAN encrypted = FALSE; status = AvGetFileEncrypted( FltObjects->Instance, FltObjects->FileObject, @@ -2399,18 +2423,18 @@ Return Value: ("[AV] AvPostCreate: AvGetFileEncrypted FAILED!! \n0x%x\n", status) ); } if (encrypted) { - + return FLT_POSTOP_FINISHED_PROCESSING; } } - + // - // In this sample, we skip the alternate data stream. However, you may decide + // In this sample, we skip the alternate data stream. However, you may decide // to scan it and modify accordingly. // - + if (AvIsStreamAlternate( Data )) { - + return FLT_POSTOP_FINISHED_PROCESSING; } @@ -2422,20 +2446,20 @@ Return Value: if (FlagOn((ULONG_PTR)CompletionContext, AV_FLAG_PREFETCH)) { if (!FltSupportsStreamHandleContexts( FltObjects->FileObject )) { - + return FLT_POSTOP_FINISHED_PROCESSING; } - status = AvCreateStreamHandleContext( FltObjects->Filter, + status = AvCreateStreamHandleContext( FltObjects->Filter, &streamHandleContext ); if (!NT_SUCCESS(status)) { - - return FLT_POSTOP_FINISHED_PROCESSING; + + return FLT_POSTOP_FINISHED_PROCESSING; } SetFlag( streamHandleContext->Flags, AV_FLAG_PREFETCH ); - + status = FltSetStreamHandleContext( FltObjects->Instance, FltObjects->FileObject, FLT_SET_CONTEXT_KEEP_IF_EXISTS, @@ -2445,84 +2469,84 @@ Return Value: FltReleaseContext( streamHandleContext ); if (!NT_SUCCESS(status)) { - + // // Shouldn't find the handle already set // - + ASSERT( status != STATUS_FLT_CONTEXT_ALREADY_DEFINED ); } - return FLT_POSTOP_FINISHED_PROCESSING; + return FLT_POSTOP_FINISHED_PROCESSING; } - + // // Find or create a stream context // status = FltGetStreamContext( FltObjects->Instance, FltObjects->FileObject, - &streamContext ); + &streamContext ); if (status == STATUS_NOT_FOUND) { - + // // Create a stream context // - + status = AvCreateStreamContext( FltObjects->Filter, &streamContext ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[Av]: Failed to create stream context with status 0x%x. (FileObject = %p, Instance = %p)\n", status, FltObjects->FileObject, FltObjects->Instance) ); - + return FLT_POSTOP_FINISHED_PROCESSING; } - + // // Attempt to get the stream infected state from our cache - // - + // + status = AvGetFileId( FltObjects->Instance, FltObjects->FileObject, &streamContext->FileId ); - + if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[Av]: Failed to get file id with status 0x%x. (FileObject = %p, Instance = %p)\n", status, FltObjects->FileObject, FltObjects->Instance) ); - + // // File id is optional and therefore should not affect the scan logic. // - + AV_SET_INVALID_FILE_REFERENCE( streamContext->FileId ) - + } else { // - // This function will load the file infected state from the + // This function will load the file infected state from the // cache if the fileID is valid. Even if this function fails, // we still have to move on because the cache is optional. // - AvLoadFileStateFromCache( FltObjects->Instance, + AvLoadFileStateFromCache( FltObjects->Instance, &streamContext->FileId, &streamContext->State, &streamContext->VolumeRevision, &streamContext->CacheRevision, - &streamContext->FileRevision ); + &streamContext->FileRevision ); } - + // // Set the new context we just allocated on the file object // - + status = FltSetStreamContext( FltObjects->Instance, FltObjects->FileObject, FLT_SET_CONTEXT_KEEP_IF_EXISTS, @@ -2537,7 +2561,7 @@ Return Value: // Race condition. Someone has set a context after we queried it. // Use the already set context instead // - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[Av]: Race: Stream context already defined. Retaining old stream context %p (FileObject = %p, Instance = %p)\n", oldStreamContext, @@ -2558,50 +2582,50 @@ Return Value: goto Cleanup; } } - + } else if (!NT_SUCCESS(status)) { // // We will get here if stream contexts are not supported // - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[Av]: Failed to get stream context with status 0x%x. (FileObject = %p, Instance = %p)\n", status, FltObjects->FileObject, FltObjects->Instance) ); - + return FLT_POSTOP_FINISHED_PROCESSING; } - + // // If successfully opened a file with the desired access matching - // the "exclusive write" from a TxF point of view, we can guarantee that - // if previous transaction context exists, it must have been comitted + // the "exclusive write" from a TxF point of view, we can guarantee that + // if previous transaction context exists, it must have been comitted // or rollbacked. // - + if (FlagOn( Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess, FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY ) ) { - + // // Either this file is opened in a transaction context or not, // we need to process the previous transaction if it exists. // AvProcessPreviousTransaction(...) handles these cases. // - + status = AvProcessPreviousTransaction ( FltObjects, streamContext ); if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvPostCreate: AvProcessTransaction FAILED!! \n") ); goto Cleanup; } - + isTxWriter = (FltObjects->Transaction != NULL); } @@ -2620,9 +2644,9 @@ Return Value: // - + if (IS_FILE_NEED_SCAN( streamContext )) { - + status = AvScan( Data, FltObjects, AvUserMode, @@ -2631,7 +2655,7 @@ Return Value: streamContext ); if (!NT_SUCCESS( status ) || (STATUS_TIMEOUT == status)) { - + AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] AvPostCreate: AvScan FAILED!! \n") ); @@ -2648,7 +2672,7 @@ Return Value: streamContext->VolumeRevision = VolumeRevision; streamContext->CacheRevision = CacheRevision; streamContext->FileRevision = FileRevision; - + AV_DBG_PRINT( AVDBG_TRACE_DEBUG, ("[Av]: AvPostCreate: RevisionNumbers updated to %I64x:%I64x:%I64x\n", VolumeRevision, @@ -2656,30 +2680,30 @@ Return Value: FileRevision) ); } - + if (IS_FILE_INFECTED( streamContext )) { - + // // If the file is infected, deny the access. // AvCancelFileOpen(Data, FltObjects, STATUS_VIRUS_INFECTED); // - // If the scan timed-out or scan was failed, we let the create succeed, + // If the scan timed-out or scan was failed, we let the create succeed, // and it may cause security hole; // // Alternatively, you can add a state called AvFileScanFailure or equivalent, - // add a condition here and fail the create. This option will have better - // protection from viruses, but the apps will see the failures due to a + // add a condition here and fail the create. This option will have better + // protection from viruses, but the apps will see the failures due to a // lengthy scan or scan failure. It's a trade-off. // goto Cleanup; } - + Cleanup: - + FltReleaseContext( streamContext ); - + return FLT_POSTOP_FINISHED_PROCESSING; } @@ -2694,7 +2718,7 @@ AvPreCleanup ( Routine Description: Pre-cleanup callback. Make the stream context persistent in the volatile cache. - If the file is transacted, it will be synced at KTM notification callback + If the file is transacted, it will be synced at KTM notification callback if committed. Arguments: @@ -2705,7 +2729,7 @@ Routine Description: opaque handles to this filter, instance, its associated volume and file object. - CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or + CompletionContext - If this callback routine returns FLT_PREOP_SUCCESS_WITH_CALLBACK or FLT_PREOP_SYNCHRONIZE, this parameter is an optional context pointer to be passed to the corresponding post-operation callback routine. Otherwise, it must be NULL. @@ -2714,7 +2738,7 @@ Return Value: The return value is the status of the operation. --*/ -{ +{ NTSTATUS status; BOOLEAN encrypted = FALSE; PAV_STREAM_CONTEXT streamContext = NULL; @@ -2724,15 +2748,15 @@ Return Value: BOOLEAN updateRevisionNumbers; LONGLONG VolumeRevision, CacheRevision, FileRevision; - + UNREFERENCED_PARAMETER( CompletionContext ); - + PAGED_CODE(); // // Skip scan on prefetcher handles to avoid deadlocks // - + status = FltGetStreamHandleContext( FltObjects->Instance, FltObjects->FileObject, &streamHandleContext ); @@ -2743,8 +2767,8 @@ Return Value: // // Because the Memory Manager can cache the file object // and use it for other applications performing mapped I/O, - // whenever a Cleanup operation is seen on a prefetcher - // file object, that file object should no longer be + // whenever a Cleanup operation is seen on a prefetcher + // file object, that file object should no longer be // considered prefetcher-opened. // @@ -2756,7 +2780,7 @@ Return Value: NULL ); FltReleaseContext( streamHandleContext ); - + return FLT_PREOP_SUCCESS_NO_CALLBACK; } @@ -2769,7 +2793,7 @@ Return Value: IoGetStackLimits( &stackLow, &stackHigh ); - if (((ULONG_PTR)FltObjects->FileObject > stackLow) && + if (((ULONG_PTR)FltObjects->FileObject > stackLow) && ((ULONG_PTR)FltObjects->FileObject < stackHigh)) { return FLT_PREOP_SUCCESS_NO_CALLBACK; @@ -2797,7 +2821,7 @@ Return Value: FltObjects->FileObject, &encrypted ); if (!NT_SUCCESS( status )) { - + AV_DBG_PRINT( AVDBG_TRACE_ERROR, ("[AV] AvPreCleanup: AvGetFileEncrypted FAILED!! \n") ); @@ -2805,7 +2829,7 @@ Return Value: } if (encrypted) { - + goto Cleanup; } @@ -2819,16 +2843,16 @@ Return Value: // // For applications, the typical calling sequence is, close the file handle - // and commit/rollback the changes. We skip the scan here for - // transacted writer because we do not know if the change will be - // rollbacked or not. If it eventually commits, it will be scanned - // at next create anyway. However, if it rollbacks, the scan here will + // and commit/rollback the changes. We skip the scan here for + // transacted writer because we do not know if the change will be + // rollbacked or not. If it eventually commits, it will be scanned + // at next create anyway. However, if it rollbacks, the scan here will // be redundant. // - if ((streamContext->TxContext == NULL) && + if ((streamContext->TxContext == NULL) && IS_FILE_MODIFIED( streamContext )) { - + status = AvScan( Data, FltObjects, AvUserMode, @@ -2837,7 +2861,7 @@ Return Value: streamContext ); if (!NT_SUCCESS( status ) || STATUS_TIMEOUT == status) { - + AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] AvPreCleanup: AvScan FAILED!! \n") ); @@ -2870,7 +2894,7 @@ Return Value: // We only insert the entry when the file is clean or infected. // - if (!IS_FILE_MODIFIED( streamContext ) || + if (!IS_FILE_MODIFIED( streamContext ) || IS_FILE_INFECTED( streamContext )) { if (!NT_SUCCESS ( AvSyncCache( FltObjects->Instance, streamContext ))) { @@ -2897,7 +2921,7 @@ Routine Description: The registered routine of type PFLT_TRANSACTION_NOTIFICATION_CALLBACK in FLT_REGISTRATION structure. - + Arguments: FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing @@ -2906,17 +2930,17 @@ Routine Description: TransactionContext - Pointer to the minifilter driver's transaction context set at PostCreate. - - TransactionNotification - Specifies the type of notifications that the + + TransactionNotification - Specifies the type of notifications that the filter manager is sending to the minifilter driver. Return Value: - STATUS_SUCCESS - Returning this status value indicates that the minifilter + STATUS_SUCCESS - Returning this status value indicates that the minifilter driver is finished with the transaction. This is a success code. - - STATUS_PENDING - Returning this status value indicates that the minifilter - driver is not yet finished with the transaction. This is a success code. + + STATUS_PENDING - Returning this status value indicates that the minifilter + driver is not yet finished with the transaction. This is a success code. --*/ { @@ -2925,20 +2949,20 @@ Return Value: PAGED_CODE(); UNREFERENCED_PARAMETER( FltObjects ); - + FLT_ASSERTMSG("[AV] AvKtmNotificationCallback: The expected type of notifications registered at FltEnlistInTransaction(...).\n", FlagOn( TransactionNotification, (TRANSACTION_NOTIFY_COMMIT_FINALIZE | TRANSACTION_NOTIFY_ROLLBACK) ) ); AV_DBG_PRINT( AVDBG_TRACE_ROUTINES, ("[AV] AvKtmNotificationCallback: Entered\n") ); - + if (NULL != transactionContext) { if ( FlagOn( TransactionNotification, TRANSACTION_NOTIFY_COMMIT_FINALIZE ) ) { - + return AvProcessTransactionOutcome( TransactionContext, TransactionOutcomeCommitted ); - + } else { return AvProcessTransactionOutcome( TransactionContext, TransactionOutcomeAborted ); @@ -2959,8 +2983,8 @@ AvScanAbortCallbackAsync ( Routine Description: This routine is the registered cancel callback function in FLT_REGISTRATION. - It would be invoked by the file system if it decides to abort the scan. - As its name suggests, this function is asynchrounous, so the caller is not + It would be invoked by the file system if it decides to abort the scan. + As its name suggests, this function is asynchrounous, so the caller is not blocked. Note: This routine may be called before FltCreateSectionForDataScan returns. @@ -2971,9 +2995,9 @@ Routine Description: Arguments: Instance - Opaque filter pointer for the caller. This parameter is required and cannot be NULL. - + Context - The section context. - + Data - Pointer to the filter callbackData that is passed to us. Return Value: @@ -3003,34 +3027,173 @@ Return Value: sectionCtx->CancelableOnConflictingIo) ); // - // Send abort signal only when the scanning + // Send abort signal only when the scanning // happens in cancelable context (such as pre-cleanup). // if (sectionCtx->CancelableOnConflictingIo) { // - // The only reason of scan context being NULL is that + // The only reason of scan context being NULL is that // the section context is about to close anyway. // Please see AvCloseSectionForDataScan(...) // scanCtx = InterlockedExchangePointer( §ionCtx->ScanContext, NULL ); if (scanCtx == NULL) { - + return STATUS_SUCCESS; } - + sectionCtx->Aborted = TRUE; AvSendAbortToUser( scanCtx->ScanThreadId, scanCtx->ScanId ); - + } return STATUS_SUCCESS; } -NTSTATUS -AvSetConfiguration ( +PFN_IoOpenDriverRegistryKey +AvGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +AvOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS Status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible + // + + pIoOpenDriverRegistryKey = AvGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API + // + + Status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( Status )) { + + goto OpenServiceParametersKeyCleanup; + } + + } else { + + // + // Open specified service root key + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + Status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( Status )) { + + goto OpenServiceParametersKeyCleanup; + } + + // + // Open the parameters key relative to service key path + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + Status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( Status )) { + + goto OpenServiceParametersKeyCleanup; + } + } + + // + // Return value to caller + // + + *ServiceParametersKey = ParametersKey; + +OpenServiceParametersKeyCleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return Status; + +} + +NTSTATUS +AvSetConfiguration ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -3041,6 +3204,9 @@ Routine Descrition: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -3051,8 +3217,7 @@ Return Value: --*/ { NTSTATUS status; - OBJECT_ATTRIBUTES attributes; - HANDLE driverRegKey = NULL; + HANDLE settingsKey = NULL; UNICODE_STRING valueName; UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION)buffer; @@ -3060,25 +3225,18 @@ Return Value: ULONG resultLength; // - // Open the SimRep registry key. + // Open service parameters key to query values from // - InitializeObjectAttributes( &attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); - - status = ZwOpenKey( &driverRegKey, - KEY_READ, - &attributes ); + status = AvOpenServiceParametersKey( DriverObject, + RegistryPath, + &settingsKey ); if (!NT_SUCCESS( status )) { goto Cleanup; } - #if DBG // @@ -3086,8 +3244,8 @@ Return Value: // RtlInitUnicodeString( &valueName, L"DebugLevel" ); - - status = ZwQueryValueKey( driverRegKey, + + status = ZwQueryValueKey( settingsKey, &valueName, KeyValuePartialInformation, value, @@ -3107,16 +3265,16 @@ Return Value: RtlInitUnicodeString( &valueName, L"LocalScanTimeout" ); - status = ZwQueryValueKey( driverRegKey, + status = ZwQueryValueKey( settingsKey, &valueName, KeyValuePartialInformation, value, - valueLength, + valueLength, &resultLength ); if (NT_SUCCESS( status )) { - Globals.LocalScanTimeout = (LONGLONG)(*(PULONG)value->Data); + Globals.LocalScanTimeout = (LONGLONG)(*(PULONG)value->Data); } // @@ -3125,25 +3283,25 @@ Return Value: RtlInitUnicodeString( &valueName, L"NetworkScanTimeout" ); - status = ZwQueryValueKey( driverRegKey, + status = ZwQueryValueKey( settingsKey, &valueName, KeyValuePartialInformation, value, - valueLength, + valueLength, &resultLength ); if (NT_SUCCESS( status )) { - Globals.NetworkScanTimeout = (LONGLONG)(*(PULONG)value->Data); + Globals.NetworkScanTimeout = (LONGLONG)(*(PULONG)value->Data); } status = STATUS_SUCCESS; Cleanup: - if (driverRegKey != NULL) { + if (settingsKey != NULL) { - ZwClose( driverRegKey ); + ZwClose( settingsKey ); } return status; diff --git a/filesys/miniFilter/avscan/filter/avscan.vcxproj b/filesys/miniFilter/avscan/filter/avscan.vcxproj index 5552329cb..fa6122b52 100644 --- a/filesys/miniFilter/avscan/filter/avscan.vcxproj +++ b/filesys/miniFilter/avscan/filter/avscan.vcxproj @@ -188,6 +188,10 @@ + + true + Document + diff --git a/filesys/miniFilter/avscan/filter/avscan.vcxproj.Filters b/filesys/miniFilter/avscan/filter/avscan.vcxproj.Filters index 6254a2458..399cecc72 100644 --- a/filesys/miniFilter/avscan/filter/avscan.vcxproj.Filters +++ b/filesys/miniFilter/avscan/filter/avscan.vcxproj.Filters @@ -43,4 +43,38 @@ Resource Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Driver Files + + \ No newline at end of file diff --git a/filesys/miniFilter/avscan/user/userscan.c b/filesys/miniFilter/avscan/user/userscan.c index 715278236..5808c2ce1 100644 --- a/filesys/miniFilter/avscan/user/userscan.c +++ b/filesys/miniFilter/avscan/user/userscan.c @@ -759,7 +759,6 @@ Return Value: HRESULT hr = S_OK; ULONG bytesReturned = 0; HANDLE sectionHandle = NULL; - DWORD dwErrCode = 0; PVOID scanAddress = NULL; MEMORY_BASIC_INFORMATION memoryInfo; PAV_SCANNER_NOTIFICATION notification = &Message->Notification; @@ -847,7 +846,7 @@ Return Value: if (!CloseHandle(sectionHandle)) { fprintf(stderr, "[UserScanHandleStartScanMsg]: Failed to close the section handle.\n"); - DisplayError(HRESULT_FROM_WIN32(dwErrCode)); + DisplayError(HRESULT_FROM_WIN32(GetLastError())); } // diff --git a/filesys/miniFilter/cancelSafe/cancelSafe.c b/filesys/miniFilter/cancelSafe/cancelSafe.c index 4c9e76337..9942a3d31 100644 --- a/filesys/miniFilter/cancelSafe/cancelSafe.c +++ b/filesys/miniFilter/cancelSafe/cancelSafe.c @@ -185,8 +185,31 @@ InstanceTeardownComplete ( _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags ); +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +GetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +OpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + NTSTATUS SetConfiguration ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -269,6 +292,8 @@ PreReadEmptyQueueAndComplete( #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(INIT, GetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, OpenServiceParametersKey) #pragma alloc_text(INIT, SetConfiguration) #pragma alloc_text(PAGE, Unload) #pragma alloc_text(PAGE, FreeGlobals) @@ -394,7 +419,7 @@ Return Value: // Modify the configuration based on values in the registry // - Status = SetConfiguration( RegistryPath ); + Status = SetConfiguration( DriverObject, RegistryPath ); if (!NT_SUCCESS( Status )) { @@ -456,9 +481,147 @@ Return Value: return Status; } +PFN_IoOpenDriverRegistryKey +GetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +OpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS Status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible. + // + + pIoOpenDriverRegistryKey = GetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API. + // + + Status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( Status )) { + + goto OpenServiceParametersKeyCleanup; + } + + } else { + + // + // Open specified service root key. + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + Status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( Status )) { + + goto OpenServiceParametersKeyCleanup; + } + + // + // Open the parameters key relative to service key path. + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + Status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( Status )) { + + goto OpenServiceParametersKeyCleanup; + } + } + + // + // Return value to caller. + // + + *ServiceParametersKey = ParametersKey; + +OpenServiceParametersKeyCleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return Status; + +} NTSTATUS SetConfiguration ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -470,6 +633,9 @@ Routine Description: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -480,10 +646,8 @@ Return Value: --*/ { NTSTATUS Status; - OBJECT_ATTRIBUTES Attributes; HANDLE DriverRegKey = NULL; UNICODE_STRING ValueName; - BOOLEAN CloseHandle = FALSE; UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + CSQ_MAX_PATH_LENGTH * sizeof(WCHAR)]; PKEY_VALUE_PARTIAL_INFORMATION Value = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer; ULONG ValueLength = sizeof(Buffer); @@ -491,28 +655,21 @@ Return Value: ULONG Length; // - // Open the driver registry key. + // Open service parameters key to query values from. // - InitializeObjectAttributes( &Attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); - - Status = ZwOpenKey( &DriverRegKey, - KEY_READ, - &Attributes ); + Status = OpenServiceParametersKey( DriverObject, + RegistryPath, + &DriverRegKey ); if (!NT_SUCCESS( Status )) { + DriverRegKey = NULL; goto SetConfigurationCleanup; } - CloseHandle = TRUE; - // - // Query the debug level + // Query the debug level. // RtlInitUnicodeString( &ValueName, CSQ_KEY_NAME_DEBUG_LEVEL ); @@ -529,12 +686,10 @@ Return Value: Globals.DebugLevel = *(PULONG)(Value->Data); } - // - // Query the queue time delay + // Query the queue time delay. // - RtlInitUnicodeString( &ValueName, CSQ_KEY_NAME_DELAY ); Status = ZwQueryValueKey( DriverRegKey, @@ -557,7 +712,7 @@ Return Value: } // - // Query the mapping path + // Query the mapping path. // RtlInitUnicodeString( &ValueName, CSQ_KEY_NAME_PATH ); @@ -632,7 +787,7 @@ Return Value: SetConfigurationCleanup: - if (CloseHandle) { + if (DriverRegKey != NULL) { ZwClose( DriverRegKey ); } diff --git a/filesys/miniFilter/cancelSafe/cancelSafe.inf b/filesys/miniFilter/cancelSafe/cancelSafe.inf index 132eea1e5..69d0ccf10 100644 Binary files a/filesys/miniFilter/cancelSafe/cancelSafe.inf and b/filesys/miniFilter/cancelSafe/cancelSafe.inf differ diff --git a/filesys/miniFilter/cdo/CdoInit.c b/filesys/miniFilter/cdo/CdoInit.c index fa6e37aa8..f913f6fbb 100644 --- a/filesys/miniFilter/cdo/CdoInit.c +++ b/filesys/miniFilter/cdo/CdoInit.c @@ -48,8 +48,31 @@ CdoInstanceSetup ( #if DBG +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +CdoGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +CdoOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + VOID CdoInitializeDebugLevel ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -75,6 +98,8 @@ CDO_GLOBAL_DATA Globals; #pragma alloc_text(INIT, DriverEntry) #if DBG +#pragma alloc_text(INIT, CdoGetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, CdoOpenServiceParametersKey) #pragma alloc_text(INIT, CdoInitializeDebugLevel) #endif @@ -90,12 +115,12 @@ DriverEntry( ) { NTSTATUS status; - - + + // // This defines what we want to filter with FltMgr // - + CONST FLT_REGISTRATION filterRegistration = { sizeof( FLT_REGISTRATION ), // Size FLT_REGISTRATION_VERSION, // Version @@ -109,22 +134,22 @@ DriverEntry( NULL, // InstanceTeardownComplete NULL,NULL // NameProvider callbacks }; - + RtlZeroMemory( &Globals, sizeof( Globals ) ); #if DBG - + // // Initialize global debug level // - CdoInitializeDebugLevel( RegistryPath ); + CdoInitializeDebugLevel( DriverObject, RegistryPath ); #else UNREFERENCED_PARAMETER( RegistryPath ); - + #endif DebugTrace( DEBUG_TRACE_LOAD_UNLOAD, @@ -132,14 +157,14 @@ DriverEntry( // // Initialize the resource - // + // ExInitializeResourceLite( &Globals.Resource ); // // Record the driver object // - + Globals.FilterDriverObject = DriverObject; // @@ -167,7 +192,7 @@ DriverEntry( FltUnregisterFilter( Globals.Filter ); ExDeleteResourceLite( &Globals.Resource ); return status; - } + } // // Start filtering i/o @@ -188,30 +213,171 @@ DriverEntry( #if DBG +PFN_IoOpenDriverRegistryKey +CdoGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +CdoOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS Status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible. + // + + pIoOpenDriverRegistryKey = CdoGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API. + // + + Status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( Status )) { + + goto cleanup; + } + + } else { + + // + // Open specified service root key. + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + Status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( Status )) { + + goto cleanup; + } + + // + // Open the parameters key relative to service key path. + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + Status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( Status )) { + + goto cleanup; + } + } + + // + // Return value to caller. + // + + *ServiceParametersKey = ParametersKey; + +cleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return Status; + +} + VOID CdoInitializeDebugLevel ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ Routine Description: - This routine tries to read the filter DebugLevel parameter from + This routine tries to read the filter DebugLevel parameter from the registry. This value will be found in the registry location indicated by the RegistryPath passed in. Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. - + Return Value: None. --*/ { - OBJECT_ATTRIBUTES attributes; - HANDLE driverRegKey; + HANDLE driverRegKey = NULL; NTSTATUS status; ULONG resultLength; UNICODE_STRING valueName; @@ -220,45 +386,46 @@ Return Value: Globals.DebugLevel = DEBUG_TRACE_ERROR; // - // Open the desired registry key + // Open service parameters key to query values from. // - InitializeObjectAttributes( &attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); + status = CdoOpenServiceParametersKey( DriverObject, + RegistryPath, + &driverRegKey ); - status = ZwOpenKey( &driverRegKey, - KEY_READ, - &attributes ); + if (!NT_SUCCESS( status )) { - if (NT_SUCCESS( status )) { + driverRegKey = NULL; + goto cleanup; + } - // - // Read the DebugFlags value from the registry. - // + // + // Read the DebugFlags value from the registry. + // - RtlInitUnicodeString( &valueName, L"DebugLevel" ); - - status = ZwQueryValueKey( driverRegKey, - &valueName, - KeyValuePartialInformation, - buffer, - sizeof(buffer), - &resultLength ); + RtlInitUnicodeString( &valueName, L"DebugLevel" ); - if (NT_SUCCESS( status )) { + status = ZwQueryValueKey( driverRegKey, + &valueName, + KeyValuePartialInformation, + buffer, + sizeof(buffer), + &resultLength ); - Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data)); - } + if (NT_SUCCESS( status )) { + + Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data)); } +cleanup: + // // Close the registry entry // - ZwClose( driverRegKey ); + if (driverRegKey != NULL) { + ZwClose( driverRegKey ); + } } #endif @@ -274,7 +441,7 @@ Routine Description: This is the unload routine for this filter driver. This is called when the minifilter is about to be unloaded. We can fail this unload - request if this is not a mandatory unloaded indicated by the Flags + request if this is not a mandatory unloaded indicated by the Flags parameter. Arguments: @@ -299,7 +466,7 @@ Return Value: // If the CDO is still referenced and the unload is not mandatry // then fail the unload // - + CdoAcquireResourceShared( &Globals.Resource ); if (FlagOn( Globals.Flags, GLOBAL_DATA_F_CDO_OPEN_REF) && @@ -356,7 +523,7 @@ Routine Description: Return Value: - STATUS_FLT_DO_NOT_ATTACH - do not attach because we do not want to + STATUS_FLT_DO_NOT_ATTACH - do not attach because we do not want to attach to any volume --*/ diff --git a/filesys/miniFilter/cdo/cdo.inf b/filesys/miniFilter/cdo/cdo.inf index 52dc6c068..cdac24d9a 100644 Binary files a/filesys/miniFilter/cdo/cdo.inf and b/filesys/miniFilter/cdo/cdo.inf differ diff --git a/filesys/miniFilter/change/change.inf b/filesys/miniFilter/change/change.inf index 9a495e76c..e7da42501 100644 Binary files a/filesys/miniFilter/change/change.inf and b/filesys/miniFilter/change/change.inf differ diff --git a/filesys/miniFilter/ctx/CtxInit.c b/filesys/miniFilter/ctx/CtxInit.c index 2654b9f99..e1e2576ac 100644 --- a/filesys/miniFilter/ctx/CtxInit.c +++ b/filesys/miniFilter/ctx/CtxInit.c @@ -78,8 +78,31 @@ CtxInstanceTeardownComplete ( #if DBG +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +CtxGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +CtxOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + VOID CtxInitializeDebugLevel ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -93,6 +116,8 @@ CtxInitializeDebugLevel ( #pragma alloc_text(INIT, DriverEntry) #if DBG +#pragma alloc_text(INIT, CtxGetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, CtxOpenServiceParametersKey) #pragma alloc_text(INIT, CtxInitializeDebugLevel) #endif @@ -217,7 +242,7 @@ Return Value: // // Default to NonPagedPoolNx for non paged pool allocations where supported. // - + ExInitializeDriverRuntime( DrvRtPoolNxOptIn ); RtlZeroMemory( &Globals, sizeof( Globals ) ); @@ -228,7 +253,7 @@ Return Value: // Initialize global debug level // - CtxInitializeDebugLevel( RegistryPath ); + CtxInitializeDebugLevel( DriverObject, RegistryPath ); #else @@ -274,8 +299,147 @@ Return Value: #if DBG +PFN_IoOpenDriverRegistryKey +CtxGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +CtxOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible + // + + pIoOpenDriverRegistryKey = CtxGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API + // + + status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + + } else { + + // + // Open specified service root key + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + + // + // Open the parameters key relative to service key path + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto cleanup; + } + } + + // + // Return value to caller + // + + *ServiceParametersKey = ParametersKey; + +cleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return status; + +} + VOID CtxInitializeDebugLevel ( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -288,6 +452,9 @@ Routine Description: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -296,8 +463,7 @@ Return Value: --*/ { - OBJECT_ATTRIBUTES attributes; - HANDLE driverRegKey; + HANDLE driverRegKey = NULL; NTSTATUS status; ULONG resultLength; UNICODE_STRING valueName; @@ -306,47 +472,46 @@ Return Value: Globals.DebugLevel = DEBUG_TRACE_ERROR; // - // Open the desired registry key + // Open service parameters key to query values from. // - InitializeObjectAttributes( &attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); + status = CtxOpenServiceParametersKey( DriverObject, + RegistryPath, + &driverRegKey ); - status = ZwOpenKey( &driverRegKey, - KEY_READ, - &attributes ); + if (!NT_SUCCESS( status )) { - if (NT_SUCCESS( status )) { + driverRegKey = NULL; + goto cleanup; + } - // - // Read the DebugFlags value from the registry. - // + // + // Read the DebugFlags value from the registry. + // - RtlInitUnicodeString( &valueName, L"DebugLevel" ); + RtlInitUnicodeString( &valueName, L"DebugLevel" ); - status = ZwQueryValueKey( driverRegKey, - &valueName, - KeyValuePartialInformation, - buffer, - sizeof(buffer), - &resultLength ); + status = ZwQueryValueKey( driverRegKey, + &valueName, + KeyValuePartialInformation, + buffer, + sizeof(buffer), + &resultLength ); - if (NT_SUCCESS( status )) { + if (NT_SUCCESS( status )) { - Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data)); - } + Globals.DebugLevel = *((PULONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data)); + } - // - // Close the registry entry - // +cleanup: - ZwClose( driverRegKey ); + // + // Close the registry entry + // + if (driverRegKey != NULL) { + ZwClose( driverRegKey ); } - } #endif diff --git a/filesys/miniFilter/ctx/ctx.inf b/filesys/miniFilter/ctx/ctx.inf index 27a7f6742..8edaf764d 100644 Binary files a/filesys/miniFilter/ctx/ctx.inf and b/filesys/miniFilter/ctx/ctx.inf differ diff --git a/filesys/miniFilter/delete/delete.inf b/filesys/miniFilter/delete/delete.inf index aa974b472..da348874e 100644 Binary files a/filesys/miniFilter/delete/delete.inf and b/filesys/miniFilter/delete/delete.inf differ diff --git a/filesys/miniFilter/minispy/filter/minispy.vcxproj b/filesys/miniFilter/minispy/filter/minispy.vcxproj index 04cec7fef..ce4cb7375 100644 --- a/filesys/miniFilter/minispy/filter/minispy.vcxproj +++ b/filesys/miniFilter/minispy/filter/minispy.vcxproj @@ -196,6 +196,7 @@ + diff --git a/filesys/miniFilter/minispy/filter/minispy.vcxproj.Filters b/filesys/miniFilter/minispy/filter/minispy.vcxproj.Filters index e01847506..aaaa7c147 100644 --- a/filesys/miniFilter/minispy/filter/minispy.vcxproj.Filters +++ b/filesys/miniFilter/minispy/filter/minispy.vcxproj.Filters @@ -34,4 +34,14 @@ Resource Files + + + Header Files + + + + + Driver Files + + \ No newline at end of file diff --git a/filesys/miniFilter/minispy/minispy.inf b/filesys/miniFilter/minispy/minispy.inf index c5cc24bb5..60eb86840 100644 Binary files a/filesys/miniFilter/minispy/minispy.inf and b/filesys/miniFilter/minispy/minispy.inf differ diff --git a/filesys/miniFilter/nullFilter/nullFilter.c b/filesys/miniFilter/nullFilter/nullFilter.c index 9944db135..6b75c1f53 100644 --- a/filesys/miniFilter/nullFilter/nullFilter.c +++ b/filesys/miniFilter/nullFilter/nullFilter.c @@ -28,7 +28,6 @@ Module Name: // Global variables //--------------------------------------------------------------------------- -#define NULL_FILTER_FILTER_NAME L"NullFilter" typedef struct _NULL_FILTER_DATA { diff --git a/filesys/miniFilter/nullFilter/nullFilter.inf b/filesys/miniFilter/nullFilter/nullFilter.inf index 5f1c45c21..c04e9f062 100644 Binary files a/filesys/miniFilter/nullFilter/nullFilter.inf and b/filesys/miniFilter/nullFilter/nullFilter.inf differ diff --git a/filesys/miniFilter/passThrough/passThrough.inf b/filesys/miniFilter/passThrough/passThrough.inf index 91d59655e..129a2ab64 100644 Binary files a/filesys/miniFilter/passThrough/passThrough.inf and b/filesys/miniFilter/passThrough/passThrough.inf differ diff --git a/filesys/miniFilter/scanner/filter/scanner.c b/filesys/miniFilter/scanner/filter/scanner.c index 318941d1c..ec911f638 100644 --- a/filesys/miniFilter/scanner/filter/scanner.c +++ b/filesys/miniFilter/scanner/filter/scanner.c @@ -54,8 +54,31 @@ UNICODE_STRING ScannedExtensionDefault = RTL_CONSTANT_STRING( L"doc" ); // Function prototypes // +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +ScannerGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +ScannerOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + NTSTATUS ScannerInitializeScannedExtensions( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -105,6 +128,8 @@ ScannerpCheckExtension ( #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) + #pragma alloc_text(INIT, ScannerGetIoOpenDriverRegistryKey) + #pragma alloc_text(INIT, ScannerOpenServiceParametersKey) #pragma alloc_text(INIT, ScannerInitializeScannedExtensions) #pragma alloc_text(PAGE, ScannerInstanceSetup) #pragma alloc_text(PAGE, ScannerPreCreate) @@ -242,7 +267,7 @@ Return Value: // Obtain the extensions to scan from the registry // - status = ScannerInitializeScannedExtensions( RegistryPath ); + status = ScannerInitializeScannedExtensions( DriverObject, RegistryPath ); if (!NT_SUCCESS( status )) { @@ -312,8 +337,147 @@ Return Value: } +PFN_IoOpenDriverRegistryKey +ScannerGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +ScannerOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible + // + + pIoOpenDriverRegistryKey = ScannerGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API + // + + status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( status )) { + + goto ScannerOpenServiceParametersKeyCleanup; + } + + } else { + + // + // Open specified service root key + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto ScannerOpenServiceParametersKeyCleanup; + } + + // + // Open the parameters key relative to service key path + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto ScannerOpenServiceParametersKeyCleanup; + } + } + + // + // Return value to caller + // + + *ServiceParametersKey = ParametersKey; + +ScannerOpenServiceParametersKeyCleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return status; + +} + NTSTATUS ScannerInitializeScannedExtensions( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -325,6 +489,9 @@ Routine Descrition: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -335,12 +502,10 @@ Return Value: --*/ { NTSTATUS status; - OBJECT_ATTRIBUTES attributes; HANDLE driverRegKey = NULL; UNICODE_STRING valueName; PKEY_VALUE_PARTIAL_INFORMATION valueBuffer = NULL; ULONG valueLength = 0; - BOOLEAN closeHandle = FALSE; PWCHAR ch; SIZE_T length; ULONG count; @@ -352,26 +517,19 @@ Return Value: ScannedExtensionCount = 0; // - // Open the driver registry key. + // Open service parameters key to query values from. // - InitializeObjectAttributes( &attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); - - status = ZwOpenKey( &driverRegKey, - KEY_READ, - &attributes ); + status = ScannerOpenServiceParametersKey( DriverObject, + RegistryPath, + &driverRegKey ); if (!NT_SUCCESS( status )) { + driverRegKey = NULL; goto ScannerInitializeScannedExtensionsCleanup; } - closeHandle = TRUE; - // // Query the length of the reg value // @@ -480,7 +638,7 @@ Return Value: valueBuffer = NULL; } - if (closeHandle) { + if (driverRegKey != NULL) { ZwClose( driverRegKey ); } @@ -675,7 +833,7 @@ Return Value return STATUS_SUCCESS; } - + VOID ScannerPortDisconnect( _In_opt_ PVOID ConnectionCookie @@ -717,7 +875,7 @@ Return value ScannerData.UserProcess = NULL; } - + NTSTATUS ScannerUnload ( _In_ FLT_FILTER_UNLOAD_FLAGS Flags diff --git a/filesys/miniFilter/scanner/filter/scanner.vcxproj b/filesys/miniFilter/scanner/filter/scanner.vcxproj index a3eeebcb3..046447587 100644 --- a/filesys/miniFilter/scanner/filter/scanner.vcxproj +++ b/filesys/miniFilter/scanner/filter/scanner.vcxproj @@ -190,6 +190,7 @@ + diff --git a/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters b/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters index 043528f2f..fbf265f0b 100644 --- a/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters +++ b/filesys/miniFilter/scanner/filter/scanner.vcxproj.Filters @@ -28,4 +28,14 @@ Resource Files + + + Header Files + + + + + Driver Files + + \ No newline at end of file diff --git a/filesys/miniFilter/scanner/scanner.inf b/filesys/miniFilter/scanner/scanner.inf index df5cc857e..d7bf6256e 100644 Binary files a/filesys/miniFilter/scanner/scanner.inf and b/filesys/miniFilter/scanner/scanner.inf differ diff --git a/filesys/miniFilter/simrep/simrep.c b/filesys/miniFilter/simrep/simrep.c index 4d377ecbe..f23dddd66 100644 --- a/filesys/miniFilter/simrep/simrep.c +++ b/filesys/miniFilter/simrep/simrep.c @@ -243,8 +243,31 @@ DriverEntry ( _In_ PUNICODE_STRING RegistryPath ); +typedef +NTSTATUS +(*PFN_IoOpenDriverRegistryKey) ( + PDRIVER_OBJECT DriverObject, + DRIVER_REGKEY_TYPE RegKeyType, + ACCESS_MASK DesiredAccess, + ULONG Flags, + PHANDLE DriverRegKey + ); + +PFN_IoOpenDriverRegistryKey +SimRepGetIoOpenDriverRegistryKey ( + VOID + ); + +NTSTATUS +SimRepOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ); + NTSTATUS SimRepSetConfiguration( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ); @@ -506,6 +529,8 @@ SIMREP_GLOBAL_DATA Globals; #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(INIT, SimRepGetIoOpenDriverRegistryKey) +#pragma alloc_text(INIT, SimRepOpenServiceParametersKey) #pragma alloc_text(INIT, SimRepSetConfiguration) #pragma alloc_text(PAGE, SimRepUnload) #pragma alloc_text(PAGE, SimRepInstanceSetup) @@ -609,7 +634,7 @@ Return Value: // Set the filter configuration based on registry keys // - status = SimRepSetConfiguration( RegistryPath ); + status = SimRepSetConfiguration( DriverObject, RegistryPath ); DebugTrace( DEBUG_TRACE_LOAD_UNLOAD, ("[SimRep]: Driver being loaded\n") ); @@ -664,8 +689,147 @@ Return Value: } #pragma warning(pop) +PFN_IoOpenDriverRegistryKey +SimRepGetIoOpenDriverRegistryKey ( + VOID + ) +{ + static PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey = NULL; + UNICODE_STRING FunctionName = {0}; + + if (pIoOpenDriverRegistryKey == NULL) { + + RtlInitUnicodeString(&FunctionName, L"IoOpenDriverRegistryKey"); + + pIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&FunctionName); + } + + return pIoOpenDriverRegistryKey; +} + +NTSTATUS +SimRepOpenServiceParametersKey ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING ServiceRegistryPath, + _Out_ PHANDLE ServiceParametersKey + ) +/*++ + +Routine Description: + + This routine opens the service parameters key, using the isolation-compliant + APIs when possible. + +Arguments: + + DriverObject - Pointer to driver object created by the system to + represent this driver. + + RegistryPath - The path key passed to the driver during DriverEntry. + + ServiceParametersKey - Returns a handle to the service parameters subkey. + +Return Value: + + STATUS_SUCCESS if the function completes successfully. Otherwise a valid + NTSTATUS code is returned. + +--*/ +{ + NTSTATUS status; + PFN_IoOpenDriverRegistryKey pIoOpenDriverRegistryKey; + UNICODE_STRING Subkey; + HANDLE ParametersKey = NULL; + HANDLE ServiceRegKey = NULL; + OBJECT_ATTRIBUTES Attributes; + + // + // Open the parameters key to read values from the INF, using the API to + // open the key if possible + // + + pIoOpenDriverRegistryKey = SimRepGetIoOpenDriverRegistryKey(); + + if (pIoOpenDriverRegistryKey != NULL) { + + // + // Open the parameters key using the API + // + + status = pIoOpenDriverRegistryKey( DriverObject, + DriverRegKeyParameters, + KEY_READ, + 0, + &ParametersKey ); + + if (!NT_SUCCESS( status )) { + + goto SimRepOpenServiceParametersKeyCleanup; + } + + } else { + + // + // Open specified service root key + // + + InitializeObjectAttributes( &Attributes, + ServiceRegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL ); + + status = ZwOpenKey( &ServiceRegKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto SimRepOpenServiceParametersKeyCleanup; + } + + // + // Open the parameters key relative to service key path + // + + RtlInitUnicodeString( &Subkey, L"Parameters" ); + + InitializeObjectAttributes( &Attributes, + &Subkey, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + ServiceRegKey, + NULL ); + + status = ZwOpenKey( &ParametersKey, + KEY_READ, + &Attributes ); + + if (!NT_SUCCESS( status )) { + + goto SimRepOpenServiceParametersKeyCleanup; + } + } + + // + // Return value to caller + // + + *ServiceParametersKey = ParametersKey; + +SimRepOpenServiceParametersKeyCleanup: + + if (ServiceRegKey != NULL) { + + ZwClose( ServiceRegKey ); + } + + return status; + +} + NTSTATUS SimRepSetConfiguration( + _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ @@ -676,6 +840,9 @@ Routine Descrition: Arguments: + DriverObject - Pointer to driver object created by the system to + represent this driver. + RegistryPath - The path key passed to the driver during DriverEntry. Return Value: @@ -686,7 +853,6 @@ Return Value: --*/ { NTSTATUS status; - OBJECT_ATTRIBUTES attributes; HANDLE driverRegKey = NULL; UNICODE_STRING valueName; UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; @@ -701,25 +867,19 @@ Return Value: PAGED_CODE(); // - // Open the SimRep registry key. + // Open service parameters key to query values from // - InitializeObjectAttributes( &attributes, - RegistryPath, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL ); - - status = ZwOpenKey( &driverRegKey, - KEY_READ, - &attributes ); + status = SimRepOpenServiceParametersKey( DriverObject, + RegistryPath, + &driverRegKey ); if (!NT_SUCCESS( status )) { + driverRegKey = NULL; goto SimRepSetConfigurationCleanup; } - #if DBG // diff --git a/filesys/miniFilter/simrep/simrep.inf b/filesys/miniFilter/simrep/simrep.inf index 2d01803d2..8eea42ce5 100644 Binary files a/filesys/miniFilter/simrep/simrep.inf and b/filesys/miniFilter/simrep/simrep.inf differ diff --git a/filesys/miniFilter/swapBuffers/swapBuffers.inf b/filesys/miniFilter/swapBuffers/swapBuffers.inf index 34298e6ba..0aab9452e 100644 Binary files a/filesys/miniFilter/swapBuffers/swapBuffers.inf and b/filesys/miniFilter/swapBuffers/swapBuffers.inf differ diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx index 73b6d10e4..39bd54684 100644 Binary files a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx and b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx differ diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj index f78f16b44..aa7f3f536 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj @@ -26,7 +26,7 @@ Win32 {F915ED95-7BE9-4CDB-B09A-0D3F4C9657FE} osrfx2_DCHU_base - 10.0.17134.0 + $(LatestTargetPlatformVersion) @@ -136,12 +136,15 @@ %(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE - %(AdditionalDependencies);$(SDK_LIB_PATH)\onecore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib + %(AdditionalDependencies);onecore.lib 1.0.0.0 + + sha256 + @@ -162,12 +165,15 @@ %(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE - %(AdditionalDependencies);$(SDK_LIB_PATH)\onecore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib + %(AdditionalDependencies);onecore.lib 1.0.0.0 + + sha256 + @@ -188,12 +194,15 @@ %(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE - %(AdditionalDependencies);$(SDK_LIB_PATH)\onecore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib + %(AdditionalDependencies);onecore.lib 1.0.0.0 + + sha256 + @@ -214,12 +223,15 @@ %(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE - %(AdditionalDependencies);$(SDK_LIB_PATH)\onecore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib + %(AdditionalDependencies);onecore.lib 1.0.0.0 + + sha256 + diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj index 09724ba57..47fe694d4 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj @@ -27,7 +27,7 @@ Debug Win32 {1A4A32BA-1596-4F52-BC48-B85A6D8D5D12} - 10.0.17134.0 + $(LatestTargetPlatformVersion) osrfx2_DCHU_filter @@ -101,7 +101,7 @@ - %(AdditionalDependencies);$(SDK_LIB_PATH)onecore.lib + %(AdditionalDependencies);onecore.lib %(AdditionalIncludeDirectories);..\..\inc @@ -109,6 +109,9 @@ %(AdditionalIncludeDirectories);..\..\inc + + sha256 + @@ -119,7 +122,7 @@ - %(AdditionalDependencies);$(SDK_LIB_PATH)onecore.lib + %(AdditionalDependencies);onecore.lib %(AdditionalIncludeDirectories);..\..\inc @@ -127,6 +130,9 @@ %(AdditionalIncludeDirectories);..\..\inc + + sha256 + @@ -137,7 +143,7 @@ - %(AdditionalDependencies);$(SDK_LIB_PATH)onecore.lib + %(AdditionalDependencies);onecore.lib %(AdditionalIncludeDirectories);..\..\inc @@ -145,6 +151,9 @@ %(AdditionalIncludeDirectories);..\..\inc + + sha256 + @@ -155,7 +164,7 @@ - %(AdditionalDependencies);$(SDK_LIB_PATH)onecore.lib + %(AdditionalDependencies);onecore.lib %(AdditionalIncludeDirectories);..\..\inc @@ -163,6 +172,9 @@ %(AdditionalIncludeDirectories);..\..\inc + + sha256 + diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj index bc56feacf..e1450faf0 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj @@ -25,7 +25,7 @@ Win32 {F19E45AF-8B05-4204-A66B-9BDBFE333233} osrfx2_DCHU_testapp - 10.0.17134.0 + $(LatestTargetPlatformVersion) diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj index 60174c569..af9fe1c7c 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj @@ -23,30 +23,30 @@ osrfx2_DCHU_usersvc Win32Proj osrfx2_DCHU_usersvc - 10.0.17134.0 + $(LatestTargetPlatformVersion) Application Unicode true - v141 + $(DefaultPlatformToolset) Application Unicode - v141 + $(DefaultPlatformToolset) Application Unicode false - v141 + $(DefaultPlatformToolset) Application Unicode - v141 + $(DefaultPlatformToolset) diff --git a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.inx b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.inx index 8baab1a01..045fc91fe 100644 Binary files a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.inx and b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.inx differ diff --git a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.vcxproj b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.vcxproj index bc19d2878..3affd6bec 100644 --- a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.vcxproj +++ b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_component/osrfx2_DCHU_component.vcxproj @@ -35,35 +35,35 @@ - - - - + - + - + - + + {F90EFA96-B075-4531-B4E1-F406362D16BF} {4605da2c-74a5-4865-98e1-152ef136825f} - v4.5 + + 12.0 Debug Win32 osrfx2_DCHU_component osrfx2_DCHU_component + $(LatestTargetPlatformVersion) @@ -73,7 +73,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -82,7 +83,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -91,7 +93,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -100,7 +103,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -109,6 +113,8 @@ Utility Package true + Desktop + true Windows10 @@ -117,6 +123,8 @@ Utility Package true + Desktop + true Windows10 @@ -125,6 +133,8 @@ Utility Package true + Desktop + true Windows10 @@ -133,6 +143,8 @@ Utility Package true + Desktop + true @@ -152,6 +164,8 @@ True 133563 + $(SolutionDir)$(Platform)\$(ConfigurationName)\ + osrfx2_DCHU_component DbgengRemoteDebugger @@ -163,6 +177,8 @@ True 133563 + $(SolutionDir)$(Platform)\$(ConfigurationName)\ + osrfx2_DCHU_component DbgengRemoteDebugger @@ -174,6 +190,7 @@ True 133563 + osrfx2_DCHU_component DbgengRemoteDebugger @@ -185,6 +202,7 @@ True 133563 + osrfx2_DCHU_component DbgengRemoteDebugger @@ -196,6 +214,9 @@ True 133563 + osrfx2_DCHU_component + true + 10_$(DDKPlatform) DbgengRemoteDebugger @@ -207,6 +228,9 @@ True 133563 + osrfx2_DCHU_component + true + 10_$(DDKPlatform) DbgengRemoteDebugger @@ -218,6 +242,8 @@ True 133563 + osrfx2_DCHU_component + 10_$(DDKPlatform) DbgengRemoteDebugger @@ -229,6 +255,8 @@ True 133563 + osrfx2_DCHU_component + 10_$(DDKPlatform) @@ -244,11 +272,17 @@ 1.0.0.0 + + sha256 + 1.0.0.0 + + sha256 + @@ -264,11 +298,17 @@ 1.0.0.0 + + sha256 + 1.0.0.0 + + sha256 + diff --git a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj index 8cbf7180d..c0a78bea2 100644 --- a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj +++ b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj @@ -22,33 +22,33 @@ {26D91630-B8FF-4102-A258-32F7D1C84E20} Win32Proj osrfx2_DCHU_componentsoftware - 10.0.16299.0 + $(LatestTargetPlatformVersion) osrfx2_DCHU_componentsoftware Application true - v141 + $(DefaultPlatformToolset) Unicode Application false - v141 + $(DefaultPlatformToolset) false Unicode Application true - v141 + $(DefaultPlatformToolset) Unicode Application false - v141 + $(DefaultPlatformToolset) false Unicode @@ -72,18 +72,22 @@ true + $(SolutionDir)$(Platform)\$(Configuration)\ true $(ProjectName) + $(SolutionDir)$(Platform)\$(Configuration)\ false + $(SolutionDir)$(Platform)\$(Configuration)\ false $(ProjectName) .exe + $(SolutionDir)$(Platform)\$(Configuration)\ @@ -101,7 +105,8 @@ - Use + + Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) diff --git a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension.sln b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension.sln index db62aca0c..bf339b930 100644 --- a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension.sln +++ b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osrfx2_DCHU_extension", "osrfx2_DCHU_extension\osrfx2_DCHU_extension.vcxproj", "{0588DF70-3923-42E6-8DC9-13C2C0186F20}" EndProject @@ -14,40 +14,48 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osrfx2_DCHU_componentsoftwa EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|ARM.ActiveCfg = Debug|Win32 + {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|ARM64.ActiveCfg = Debug|Win32 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|x64.ActiveCfg = Debug|x64 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|x64.Build.0 = Debug|x64 - {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|x64.Deploy.0 = Debug|x64 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|x86.ActiveCfg = Debug|Win32 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|x86.Build.0 = Debug|Win32 - {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Debug|x86.Deploy.0 = Debug|Win32 + {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|ARM.ActiveCfg = Release|Win32 + {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|ARM64.ActiveCfg = Release|Win32 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|x64.ActiveCfg = Release|x64 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|x64.Build.0 = Release|x64 - {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|x64.Deploy.0 = Release|x64 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|x86.ActiveCfg = Release|Win32 {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|x86.Build.0 = Release|Win32 - {0588DF70-3923-42E6-8DC9-13C2C0186F20}.Release|x86.Deploy.0 = Release|Win32 + {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|ARM.ActiveCfg = Debug|Win32 + {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|ARM64.ActiveCfg = Debug|Win32 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|x64.ActiveCfg = Debug|x64 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|x64.Build.0 = Debug|x64 - {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|x64.Deploy.0 = Debug|x64 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|x86.ActiveCfg = Debug|Win32 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|x86.Build.0 = Debug|Win32 - {F90EFA96-B075-4531-B4E1-F406362D16BF}.Debug|x86.Deploy.0 = Debug|Win32 + {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|ARM.ActiveCfg = Release|Win32 + {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|ARM64.ActiveCfg = Release|Win32 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|x64.ActiveCfg = Release|x64 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|x64.Build.0 = Release|x64 - {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|x64.Deploy.0 = Release|x64 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|x86.ActiveCfg = Release|Win32 {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|x86.Build.0 = Release|Win32 - {F90EFA96-B075-4531-B4E1-F406362D16BF}.Release|x86.Deploy.0 = Release|Win32 + {26D91630-B8FF-4102-A258-32F7D1C84E20}.Debug|ARM.ActiveCfg = Debug|Win32 + {26D91630-B8FF-4102-A258-32F7D1C84E20}.Debug|ARM64.ActiveCfg = Debug|Win32 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Debug|x64.ActiveCfg = Debug|x64 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Debug|x64.Build.0 = Debug|x64 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Debug|x86.ActiveCfg = Debug|Win32 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Debug|x86.Build.0 = Debug|Win32 + {26D91630-B8FF-4102-A258-32F7D1C84E20}.Release|ARM.ActiveCfg = Release|Win32 + {26D91630-B8FF-4102-A258-32F7D1C84E20}.Release|ARM64.ActiveCfg = Release|Win32 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Release|x64.ActiveCfg = Release|x64 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Release|x64.Build.0 = Release|x64 {26D91630-B8FF-4102-A258-32F7D1C84E20}.Release|x86.ActiveCfg = Release|Win32 @@ -56,11 +64,6 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {0588DF70-3923-42E6-8DC9-13C2C0186F20} = {4577857A-CCAE-42EB-BDE2-16C1E3DC7B14} - {F90EFA96-B075-4531-B4E1-F406362D16BF} = {E148C50E-31A6-423E-A867-526FD51DA164} - {26D91630-B8FF-4102-A258-32F7D1C84E20} = {272BE7AA-9011-46FA-96C9-2051C9526476} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FA4B1275-A81F-4DE1-B6E2-930648D7E245} EndGlobalSection diff --git a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx index cb2e9177d..a762b235e 100644 Binary files a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx and b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx differ diff --git a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj index 770f6ebbc..b6a0ed578 100644 --- a/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj +++ b/general/DCHU/osrfx2_DCHU_extension_loose/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj @@ -24,12 +24,14 @@ {0588DF70-3923-42E6-8DC9-13C2C0186F20} {4605da2c-74a5-4865-98e1-152ef136825f} - v4.6.1 + + 12.0 Debug Win32 osrfx2_DCHU_extension osrfx2_DCHU_extension + $(LatestTargetPlatformVersion) @@ -40,6 +42,7 @@ Package true Universal + true Windows10 @@ -49,6 +52,7 @@ Package true Universal + true Windows10 @@ -58,6 +62,7 @@ Package true Universal + true Windows10 @@ -67,6 +72,7 @@ Package true Universal + true @@ -86,6 +92,8 @@ True 133563 + osrfx2_DCHU_extension + $(SolutionDir)$(Platform)\$(ConfigurationName)\ DbgengRemoteDebugger @@ -97,6 +105,8 @@ True 133563 + osrfx2_DCHU_extension + $(SolutionDir)$(Platform)\$(ConfigurationName)\ DbgengRemoteDebugger @@ -108,6 +118,8 @@ True 133563 + osrfx2_DCHU_extension + $(SolutionDir)$(Platform)\$(ConfigurationName)\ DbgengRemoteDebugger @@ -119,6 +131,8 @@ True 133563 + osrfx2_DCHU_extension + $(SolutionDir)$(Platform)\$(ConfigurationName)\ DbgengRemoteDebugger @@ -169,48 +183,72 @@ $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + diff --git a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_component/osrfx2_DCHU_component.inx b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_component/osrfx2_DCHU_component.inx index 8baab1a01..045fc91fe 100644 Binary files a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_component/osrfx2_DCHU_component.inx and b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_component/osrfx2_DCHU_component.inx differ diff --git a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj index e15ff8f9a..bb4047128 100644 --- a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj +++ b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_componentsoftware/osrfx2_DCHU_componentsoftware.vcxproj @@ -22,33 +22,33 @@ {26D91630-B8FF-4102-A258-32F7D1C84E20} Win32Proj osrfx2_DCHU_componentsoftware - 10.0.16299.0 + $(LatestTargetPlatformVersion) osrfx2_DCHU_componentsoftware Application true - v141 + $(DefaultPlatformToolset) Unicode Application false - v141 + $(DefaultPlatformToolset) false Unicode Application true - v141 + $(DefaultPlatformToolset) Unicode Application false - v141 + $(DefaultPlatformToolset) false Unicode @@ -71,11 +71,22 @@ - true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(ProjectName) + + false + + + false + + + true + + + true + Use diff --git a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx index ed4a3c87a..17670efae 100644 Binary files a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx and b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.inx differ diff --git a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj index 41d8a9c8e..99dc560bd 100644 --- a/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj +++ b/general/DCHU/osrfx2_DCHU_extension_tight/osrfx2_DCHU_extension/osrfx2_DCHU_extension.vcxproj @@ -31,7 +31,8 @@ {0588DF70-3923-42E6-8DC9-13C2C0186F20} {4605da2c-74a5-4865-98e1-152ef136825f} - v4.6.1 + + 12.0 osrfx2_DCHU_extension osrfx2_DCHU_extension @@ -45,7 +46,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -54,7 +56,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -63,7 +66,8 @@ Utility Package true - Universal + Desktop + true Windows10 @@ -72,7 +76,8 @@ Utility Package true - Universal + Desktop + true @@ -139,24 +144,36 @@ $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + $(InfArch) 1.0.0.0 + + sha256 + diff --git a/general/PLX9x5x/sys/Pci9x5x.vcxproj b/general/PLX9x5x/sys/Pci9x5x.vcxproj index de71cdb92..d319a2841 100644 --- a/general/PLX9x5x/sys/Pci9x5x.vcxproj +++ b/general/PLX9x5x/sys/Pci9x5x.vcxproj @@ -31,7 +31,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -39,7 +39,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -47,7 +47,7 @@ Windows10 False - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver @@ -55,7 +55,7 @@ Windows10 True - Desktop + Windows Driver KMDF WindowsKernelModeDriver10.0 Driver diff --git a/general/PLX9x5x/sys/pci9x5x.inx b/general/PLX9x5x/sys/pci9x5x.inx index 2446271e3..8fdb2eea1 100644 Binary files a/general/PLX9x5x/sys/pci9x5x.inx and b/general/PLX9x5x/sys/pci9x5x.inx differ diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj index 3c5ff0dec..3b2022d25 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -180,7 +180,7 @@ ..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories) - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def @@ -200,7 +200,7 @@ ..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories) - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def @@ -220,7 +220,7 @@ ..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories) - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib $(SolutionDir)MediaSource\module.def %(IgnoreSpecificDefaultLibraries) @@ -240,7 +240,7 @@ ..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories) - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib $(SolutionDir)MediaSource\module.def %(IgnoreSpecificDefaultLibraries) @@ -264,7 +264,7 @@ true true - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def @@ -289,7 +289,7 @@ true true - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def @@ -315,7 +315,7 @@ true true - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def @@ -339,7 +339,7 @@ true true - mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(AdditionalDependencies);mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def diff --git a/general/SimpleMediaSource/SimpleMediaSource.sln b/general/SimpleMediaSource/SimpleMediaSource.sln index f6bd620c2..95ba61dab 100644 --- a/general/SimpleMediaSource/SimpleMediaSource.sln +++ b/general/SimpleMediaSource/SimpleMediaSource.sln @@ -19,8 +19,10 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM.ActiveCfg = Debug|Win32 - {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM.ActiveCfg = Debug|ARM + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM.Build.0 = Debug|ARM + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM64.Build.0 = Debug|ARM64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.ActiveCfg = Debug|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.Build.0 = Debug|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.ActiveCfg = Debug|Win32 diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf index e2d228fe8..d9f054029 100644 Binary files a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf and b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf differ diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj index bb32647a4..8a53af293 100644 --- a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj @@ -204,7 +204,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib sha256 @@ -217,7 +217,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib sha256 @@ -230,7 +230,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib sha256 @@ -243,7 +243,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib sha256 @@ -256,7 +256,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib @@ -266,7 +266,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib @@ -276,7 +276,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib @@ -286,7 +286,7 @@ trace.h - %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + %(AdditionalDependencies);OneCoreUAP.lib diff --git a/general/SystemDma/wdm/exe/SystemDmaApp.vcxproj b/general/SystemDma/wdm/exe/SystemDmaApp.vcxproj index 636d5d5f9..eaf152f46 100644 --- a/general/SystemDma/wdm/exe/SystemDmaApp.vcxproj +++ b/general/SystemDma/wdm/exe/SystemDmaApp.vcxproj @@ -29,7 +29,7 @@ Windows10 False - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -37,7 +37,7 @@ Windows10 True - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -45,7 +45,7 @@ Windows10 False - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application @@ -53,7 +53,7 @@ Windows10 True - Desktop + Windows Driver WindowsApplicationForDrivers10.0 Application diff --git a/general/SystemDma/wdm/sys/SDma.vcxproj b/general/SystemDma/wdm/sys/SDma.vcxproj index 76c512c3f..57c4d115b 100644 --- a/general/SystemDma/wdm/sys/SDma.vcxproj +++ b/general/SystemDma/wdm/sys/SDma.vcxproj @@ -29,7 +29,7 @@ Windows10 False - Desktop + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -37,7 +37,7 @@ Windows10 True - Desktop + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -45,7 +45,7 @@ Windows10 False - Desktop + Windows Driver WDM WindowsKernelModeDriver10.0 Driver @@ -53,7 +53,7 @@ Windows10 True - Desktop + Windows Driver WDM WindowsKernelModeDriver10.0 Driver diff --git a/general/WinHEC 2017 Lab/PlugInToaster/devcon.exe b/general/WinHEC 2017 Lab/PlugInToaster/devcon.exe deleted file mode 100644 index 92f915052..000000000 Binary files a/general/WinHEC 2017 Lab/PlugInToaster/devcon.exe and /dev/null differ diff --git a/general/WinHEC 2017 Lab/PlugInToaster/plug.exe b/general/WinHEC 2017 Lab/PlugInToaster/plug.exe deleted file mode 100644 index d84aa38b9..000000000 Binary files a/general/WinHEC 2017 Lab/PlugInToaster/plug.exe and /dev/null differ diff --git a/general/WinHEC 2017 Lab/PlugInToaster/unplug.bat b/general/WinHEC 2017 Lab/PlugInToaster/unplug.bat deleted file mode 100644 index 324ae1cf0..000000000 --- a/general/WinHEC 2017 Lab/PlugInToaster/unplug.bat +++ /dev/null @@ -1,2 +0,0 @@ -@sc delete hsa_usersrv -@devcon remove TOASTER\BASIC_TOASTER \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/README.md b/general/WinHEC 2017 Lab/README.md deleted file mode 100644 index eda72f91d..000000000 --- a/general/WinHEC 2017 Lab/README.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -page_type: sample -description: "Toaster samples from the WinHEC 2017 Lab: Toaster Driver, PlugInToaster, and Toaster Support App." -languages: -- cpp -products: -- windows -- windows-wdk ---- - -# WinHEC 2017 Lab - -Toaster samples from the WinHEC 2017 Lab: Toaster Driver, PlugInToaster, and Toaster Support App. diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/HsaService.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/HsaService.cpp deleted file mode 100644 index d3f70fdfc..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/HsaService.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "stdafx.h" - -#pragma region Includes -#include -#include -#include "ServiceInstaller.h" -#include "ServiceBase.h" -#include "SampleService.h" -#pragma endregion - -// -// Settings of the service -// - -// Internal name of the service -#define SERVICE_NAME L"HsaService" - -// Displayed name of the service -#define SERVICE_DISPLAY_NAME L"Hsa Sample Service" - -// Service start options. -#define SERVICE_START_TYPE SERVICE_DEMAND_START - -// List of service dependencies - "dep1\0dep2\0\0" -#define SERVICE_DEPENDENCIES L"" - -// The name of the account under which the service should run - NULL uses LocalSystem account. -#define SERVICE_ACCOUNT NULL - -// The password to the service account name -#define SERVICE_PASSWORD NULL - - -// -// FUNCTION: wmain(int, wchar_t *[]) -// -// PURPOSE: entrypoint for the application. -// -// PARAMETERS: -// argc - number of command line arguments -// argv - array of command line arguments -// -// RETURN VALUE: -// none -// -// COMMENTS: -// wmain() either performs the command line task, or run the service. -// -int wmain(_In_ int argc, _In_ wchar_t *argv[]) -{ - bool invalidArgs = false; - - if ((argc > 1) && ((*argv[1] == L'-' || (*argv[1] == L'/')))) - { - if (_wcsicmp(L"install", argv[1] + 1) == 0) - { - // Install the service when the command is - // "-install" or "/install". - InstallService( - SERVICE_NAME, // Name of service - SERVICE_DISPLAY_NAME, // Name to display - SERVICE_START_TYPE, // Service start type - SERVICE_DEPENDENCIES, // Dependencies - SERVICE_ACCOUNT, // Service running account - SERVICE_PASSWORD // Password of the account - ); - } - else if (_wcsicmp(L"remove", argv[1] + 1) == 0) - { - // Uninstall the service when the command is - // "-remove" or "/remove". - UninstallService(SERVICE_NAME); - } - else if (_wcsicmp(L"console", argv[1] + 1) == 0) - { - // Uninstall the service when the command is - // "-remove" or "/remove". - CSampleService service(SERVICE_NAME); - service.ConsoleRun(); - } - else - { - invalidArgs = true; - } - } - else - { - invalidArgs = true; - CSampleService service(SERVICE_NAME); - if (!CServiceBase::Run(service)) - { - wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError()); - } - } - - if (invalidArgs) - { - wprintf(L"Parameters:\n"); - wprintf(L" -install to install the service.\n"); - wprintf(L" -remove to remove the service.\n"); - wprintf(L" -console to run in console mode.\n"); - } - - return 0; -} \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp deleted file mode 100644 index 1766b37cf..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.cpp +++ /dev/null @@ -1,148 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "stdafx.h" -#include "Metering.h" -#include -#include "RpcInterface_h.h" - -using namespace RpcServer; - -// -// Thread pool callback method for metering worker -// -void CALLBACK MeteringWorkerTpCallback( - _In_ PTP_CALLBACK_INSTANCE /*iTimerInstance*/, - _In_ PVOID pContext, - _In_ PTP_TIMER /*pTimer*/) -{ - Metering *metering = static_cast(pContext); - - if (metering != nullptr) - { - // Run the metering worker for this instance of metering - metering->MeteringWorker(); - } -} - -// -// ctor for Metering -// -Metering::Metering( - _In_ __int64 period) -{ - tpTimer = CreateThreadpoolTimer(::MeteringWorkerTpCallback, this, nullptr); - // TODO: Handle if CreateThreadpoolTimer fails i.e tpTimer == nullptr - - samplePeriod = period; - event = CreateEvent( - nullptr, // default security attributes - FALSE, // auto-reset event object - FALSE, // initial state is nonsignaled - nullptr); // unnamed object -} - -// -// dtor for Metering -// -Metering::~Metering() -{ - if (tpTimer != nullptr) - { - // How to close threadpool timer when there are outstanding callbacks: - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682040(v=vs.85).aspx - SetThreadpoolTimer(tpTimer, nullptr, 0, 0); - WaitForThreadpoolTimerCallbacks(tpTimer, true); - CloseThreadpoolTimer(tpTimer); - tpTimer = nullptr; - } - CloseHandle(event); -} - -// -// Set the lowest sample period -// -void Metering::SetSamplePeriod(_In_ __int64 period) -{ - if (period < 1) - { - // Don't allow 0 (too fast) or negative numbers. - period = 1; - } - if (period > 1000) - { - // Don't let the period be too long, or we will be - // slow to shut down. - period = 1000; - } - samplePeriod = period; -} - -// -// Get last known metering data -// -__int64 Metering::GetMeteringData() const -{ - return _data; -} - -// -// Metering worker that updates metering data -// -void Metering::MeteringWorker() -{ - // Get the value from the imaginary driver and update the data - _data = GetTickCount(); - SetEvent(event); -} - -// -// Set the thread poot timer and wait for metering data. -// -void Metering::WaitForMeteringData() const -{ - ULARGE_INTEGER ulDueTime; - FILETIME FileDueTime; - ulDueTime.QuadPart = static_cast(-(1 * 10 * 1000 * samplePeriod)); - FileDueTime.dwHighDateTime = ulDueTime.HighPart; - FileDueTime.dwLowDateTime = ulDueTime.LowPart; - - SetThreadpoolTimer(tpTimer, - &FileDueTime, - 0, - 0); - - WaitForSingleObject(event, INFINITE); -} - -void Metering::StartMetering( - _In_ __int64 samplePeriod, - _In_ __int64 context) -{ - stopMeteringRequested = false; - SetSamplePeriod(samplePeriod); - - while (true) - { - WaitForMeteringData(); - if (stopMeteringRequested || ShutdownRequested) - { - break; - } - MeteringDataEvent(GetMeteringData(), context); - } -} - -void Metering::StopMetering() -{ - stopMeteringRequested = true; -} - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.h deleted file mode 100644 index bfb48216f..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/Metering.h +++ /dev/null @@ -1,29 +0,0 @@ -#include "stdafx.h" -#include - -#include // std::cout -#include // std::thread -#include - -namespace RpcServer -{ - class Metering - { - public: - Metering(__int64 period); - void SetSamplePeriod(__int64 period); - __int64 GetMeteringData() const; - void MeteringWorker(); - void WaitForMeteringData() const; - void StartMetering(__int64 samplePeriod, __int64 context); - void StopMetering(); - ~Metering(); - - private: - volatile __int64 _data; - volatile __int64 samplePeriod; - PTP_TIMER tpTimer = nullptr; - HANDLE event; - volatile bool stopMeteringRequested = false; - }; -} diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface.Idl b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface.Idl deleted file mode 100644 index 1b4b74ccd..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface.Idl +++ /dev/null @@ -1,51 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -import "oaidl.idl"; -import "unknwn.idl"; - -[uuid (906B0CE0-C70B-1067-B317-00DD010662DA), -version(1.0), -pointer_default(unique), -] -interface RpcInterface -{ - - // context_handle_noserialize in acf for RPC to call rundown when the client goes away - typedef [context_handle] void* PCONTEXT_HANDLE_TYPE; - typedef [ref] PCONTEXT_HANDLE_TYPE * PPCONTEXT_HANDLE_TYPE; - - // - // RPC methods to retrieve/clean client context - // - void RemoteOpen([in] handle_t hBinding, - [out] PPCONTEXT_HANDLE_TYPE pphContext); - - void RemoteClose([in, out] PPCONTEXT_HANDLE_TYPE pphContext); - - // - // Metering Interface - // - void StartMetering( - [in] PCONTEXT_HANDLE_TYPE phContext, - [in] __int64 samplePeriod, - [in, optional] __int64 context); - - void SetSamplePeriod( - [in] PCONTEXT_HANDLE_TYPE phContext, - [in] __int64 samplePeriod); - - void StopMetering([in] PCONTEXT_HANDLE_TYPE phContext); - - [callback] void MeteringDataEvent( - [in] __int64 data, - [in, optional] __int64 context); -} diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface.acf b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface.acf deleted file mode 100644 index d00ed5afc..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface.acf +++ /dev/null @@ -1,17 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the Microsoft Public License. -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - - -interface RpcInterface -{ - // We need the RPC to call rundown when the client goes away - typedef [context_handle_noserialize] PCONTEXT_HANDLE_TYPE; -} diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_c.c b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_c.c deleted file mode 100644 index fbe0a799f..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_c.c +++ /dev/null @@ -1,476 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the RPC client stubs */ - - - /* File created by MIDL compiler version 8.01.0622 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for RpcInterface.Idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#if defined(_M_AMD64) - - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ -#if _MSC_VER >= 1200 -#pragma warning(push) -#endif - -#pragma warning( disable: 4211 ) /* redefine extern to static */ -#pragma warning( disable: 4232 ) /* dllimport identity*/ -#pragma warning( disable: 4024 ) /* array to pointer mapping*/ - -#include - -#include "RpcInterface_h.h" - -#define TYPE_FORMAT_STRING_SIZE 23 -#define PROC_FORMAT_STRING_SIZE 245 -#define EXPR_FORMAT_STRING_SIZE 1 -#define TRANSMIT_AS_TABLE_SIZE 0 -#define WIRE_MARSHAL_TABLE_SIZE 0 - -typedef struct _RpcInterface_MIDL_TYPE_FORMAT_STRING - { - short Pad; - unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_TYPE_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_PROC_FORMAT_STRING - { - short Pad; - unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_PROC_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_EXPR_FORMAT_STRING - { - long Pad; - unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_EXPR_FORMAT_STRING; - - -static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = -{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; - - -extern const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString; -extern const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString; -extern const RpcInterface_MIDL_EXPR_FORMAT_STRING RpcInterface__MIDL_ExprFormatString; - -#define GENERIC_BINDING_TABLE_SIZE 0 - - -/* Standard interface: RpcInterface, ver. 1.0, - GUID={0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}} */ - - -extern const MIDL_SERVER_INFO RpcInterface_ServerInfo; - - -extern const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable; - -static const RPC_CLIENT_INTERFACE RpcInterface___RpcClientInterface = - { - sizeof(RPC_CLIENT_INTERFACE), - {{0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}},{1,0}}, - {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, - (RPC_DISPATCH_TABLE*)&RpcInterface_v1_0_DispatchTable, - 0, - 0, - 0, - &RpcInterface_ServerInfo, - 0x04000000 - }; -RPC_IF_HANDLE RpcInterface_v1_0_c_ifspec = (RPC_IF_HANDLE)& RpcInterface___RpcClientInterface; - -extern const MIDL_STUB_DESC RpcInterface_StubDesc; - -static RPC_BINDING_HANDLE RpcInterface__MIDL_AutoBindHandle; - - -void RemoteOpen( - /* [in] */ handle_t hBinding, - /* [out] */ PPCONTEXT_HANDLE_TYPE pphContext) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[0], - hBinding, - pphContext); - -} - - -void RemoteClose( - /* [out][in] */ PPCONTEXT_HANDLE_TYPE pphContext) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[36], - pphContext); - -} - - -void StartMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod, - /* [optional][in] */ __int64 context) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[74], - phContext, - samplePeriod, - context); - -} - - -void SetSamplePeriod( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[124], - phContext, - samplePeriod); - -} - - -void StopMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[168], - phContext); - -} - - -#if !defined(__RPC_WIN64__) -#error Invalid build platform for this stub. -#endif - -static const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString = - { - 0, - { - - /* Procedure RemoteOpen */ - - 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 2 */ NdrFcLong( 0x0 ), /* 0 */ -/* 6 */ NdrFcShort( 0x0 ), /* 0 */ -/* 8 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ - 0x0, /* 0 */ -/* 12 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 14 */ NdrFcShort( 0x0 ), /* 0 */ -/* 16 */ NdrFcShort( 0x38 ), /* 56 */ -/* 18 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 20 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 22 */ NdrFcShort( 0x0 ), /* 0 */ -/* 24 */ NdrFcShort( 0x0 ), /* 0 */ -/* 26 */ NdrFcShort( 0x0 ), /* 0 */ -/* 28 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 30 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ -/* 32 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 34 */ NdrFcShort( 0x6 ), /* Type Offset=6 */ - - /* Procedure RemoteClose */ - -/* 36 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 38 */ NdrFcLong( 0x0 ), /* 0 */ -/* 42 */ NdrFcShort( 0x1 ), /* 1 */ -/* 44 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 46 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe4, /* Ctxt flags: via ptr, in, out, no serialize, */ -/* 48 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 50 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 52 */ NdrFcShort( 0x38 ), /* 56 */ -/* 54 */ NdrFcShort( 0x38 ), /* 56 */ -/* 56 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 58 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 60 */ NdrFcShort( 0x0 ), /* 0 */ -/* 62 */ NdrFcShort( 0x0 ), /* 0 */ -/* 64 */ NdrFcShort( 0x0 ), /* 0 */ -/* 66 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 68 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ -/* 70 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 72 */ NdrFcShort( 0xe ), /* Type Offset=14 */ - - /* Procedure StartMetering */ - -/* 74 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 76 */ NdrFcLong( 0x0 ), /* 0 */ -/* 80 */ NdrFcShort( 0x2 ), /* 2 */ -/* 82 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 84 */ 0x30, /* FC_BIND_CONTEXT */ - 0x44, /* Ctxt flags: in, no serialize, */ -/* 86 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 88 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 90 */ NdrFcShort( 0x44 ), /* 68 */ -/* 92 */ NdrFcShort( 0x0 ), /* 0 */ -/* 94 */ 0x40, /* Oi2 Flags: has ext, */ - 0x3, /* 3 */ -/* 96 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 98 */ NdrFcShort( 0x0 ), /* 0 */ -/* 100 */ NdrFcShort( 0x0 ), /* 0 */ -/* 102 */ NdrFcShort( 0x0 ), /* 0 */ -/* 104 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 106 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 108 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 110 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 112 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 114 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 116 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 118 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 120 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 122 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure SetSamplePeriod */ - -/* 124 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 126 */ NdrFcLong( 0x0 ), /* 0 */ -/* 130 */ NdrFcShort( 0x3 ), /* 3 */ -/* 132 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 134 */ 0x30, /* FC_BIND_CONTEXT */ - 0x44, /* Ctxt flags: in, no serialize, */ -/* 136 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 138 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 140 */ NdrFcShort( 0x34 ), /* 52 */ -/* 142 */ NdrFcShort( 0x0 ), /* 0 */ -/* 144 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 146 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 148 */ NdrFcShort( 0x0 ), /* 0 */ -/* 150 */ NdrFcShort( 0x0 ), /* 0 */ -/* 152 */ NdrFcShort( 0x0 ), /* 0 */ -/* 154 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 156 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 158 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 160 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 162 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 164 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 166 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure StopMetering */ - -/* 168 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 170 */ NdrFcLong( 0x0 ), /* 0 */ -/* 174 */ NdrFcShort( 0x4 ), /* 4 */ -/* 176 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 178 */ 0x30, /* FC_BIND_CONTEXT */ - 0x44, /* Ctxt flags: in, no serialize, */ -/* 180 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 182 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 184 */ NdrFcShort( 0x24 ), /* 36 */ -/* 186 */ NdrFcShort( 0x0 ), /* 0 */ -/* 188 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 190 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 192 */ NdrFcShort( 0x0 ), /* 0 */ -/* 194 */ NdrFcShort( 0x0 ), /* 0 */ -/* 196 */ NdrFcShort( 0x0 ), /* 0 */ -/* 198 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 200 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 202 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 204 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Procedure MeteringDataEvent */ - -/* 206 */ 0x34, /* FC_CALLBACK_HANDLE */ - 0x48, /* Old Flags: */ -/* 208 */ NdrFcLong( 0x0 ), /* 0 */ -/* 212 */ NdrFcShort( 0x0 ), /* 0 */ -/* 214 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 216 */ NdrFcShort( 0x20 ), /* 32 */ -/* 218 */ NdrFcShort( 0x0 ), /* 0 */ -/* 220 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 222 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 224 */ NdrFcShort( 0x0 ), /* 0 */ -/* 226 */ NdrFcShort( 0x0 ), /* 0 */ -/* 228 */ NdrFcShort( 0x0 ), /* 0 */ -/* 230 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter data */ - -/* 232 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 234 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 236 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 238 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 240 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 242 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString = - { - 0, - { - NdrFcShort( 0x0 ), /* 0 */ -/* 2 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ -/* 6 */ 0x30, /* FC_BIND_CONTEXT */ - 0xa4, /* Ctxt flags: via ptr, out, no serialize, */ -/* 8 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 10 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 12 */ NdrFcShort( 0x2 ), /* Offset= 2 (14) */ -/* 14 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe5, /* Ctxt flags: via ptr, in, out, no serialize, can't be null */ -/* 16 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 18 */ 0x30, /* FC_BIND_CONTEXT */ - 0x45, /* Ctxt flags: in, no serialize, can't be null */ -/* 20 */ 0x0, /* 0 */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const unsigned short RpcInterface_FormatStringOffsetTable[] = - { - 0, - 36, - 74, - 124, - 168, - }; - - -static const unsigned short _callbackRpcInterface_FormatStringOffsetTable[] = - { - 206 - }; - - -static const MIDL_STUB_DESC RpcInterface_StubDesc = - { - (void *)& RpcInterface___RpcClientInterface, - MIDL_user_allocate, - MIDL_user_free, - &RpcInterface__MIDL_AutoBindHandle, - 0, - 0, - 0, - 0, - RpcInterface__MIDL_TypeFormatString.Format, - 1, /* -error bounds_check flag */ - 0x50002, /* Ndr library version */ - 0, - 0x801026e, /* MIDL Version 8.1.622 */ - 0, - 0, - 0, /* notify & notify_flag routine table */ - 0x1, /* MIDL flag */ - 0, /* cs routines */ - 0, /* proxy/server info */ - 0 - }; - -static const RPC_DISPATCH_FUNCTION RpcInterface_table[] = - { - NdrServerCall2, - 0 - }; -static const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable = - { - 1, - (RPC_DISPATCH_FUNCTION*)RpcInterface_table - }; - -static const SERVER_ROUTINE RpcInterface_ServerRoutineTable[] = - { - (SERVER_ROUTINE)MeteringDataEvent - }; - -static const MIDL_SERVER_INFO RpcInterface_ServerInfo = - { - &RpcInterface_StubDesc, - RpcInterface_ServerRoutineTable, - RpcInterface__MIDL_ProcFormatString.Format, - _callbackRpcInterface_FormatStringOffsetTable, - 0, - 0, - 0, - 0}; -#if _MSC_VER >= 1200 -#pragma warning(pop) -#endif - - -#endif /* defined(_M_AMD64)*/ - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_h.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_h.h deleted file mode 100644 index 98544da79..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_h.h +++ /dev/null @@ -1,103 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 8.01.0622 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for RpcInterface.Idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif /* __RPCNDR_H_VERSION__ */ - - -#ifndef __RpcInterface_h_h__ -#define __RpcInterface_h_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -/* header files for imported files */ -#include "oaidl.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -#ifndef __RpcInterface_INTERFACE_DEFINED__ -#define __RpcInterface_INTERFACE_DEFINED__ - -/* interface RpcInterface */ -/* [unique][version][uuid] */ - -typedef /* [context_handle_noserialize][context_handle] */ void *PCONTEXT_HANDLE_TYPE; - -typedef /* [ref] */ PCONTEXT_HANDLE_TYPE *PPCONTEXT_HANDLE_TYPE; - -void RemoteOpen( - /* [in] */ handle_t hBinding, - /* [out] */ PPCONTEXT_HANDLE_TYPE pphContext); - -void RemoteClose( - /* [out][in] */ PPCONTEXT_HANDLE_TYPE pphContext); - -void StartMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod, - /* [optional][in] */ __int64 context); - -void SetSamplePeriod( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod); - -void StopMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext); - -/* [callback] */ void MeteringDataEvent( - /* [in] */ __int64 data, - /* [optional][in] */ __int64 context); - - - -extern RPC_IF_HANDLE RpcInterface_v1_0_c_ifspec; -extern RPC_IF_HANDLE RpcInterface_v1_0_s_ifspec; -#endif /* __RpcInterface_INTERFACE_DEFINED__ */ - -/* Additional Prototypes for ALL interfaces */ - -void __RPC_USER PCONTEXT_HANDLE_TYPE_rundown( PCONTEXT_HANDLE_TYPE ); - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_s.c b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_s.c deleted file mode 100644 index 89aa59bfc..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcInterface_s.c +++ /dev/null @@ -1,430 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the RPC server stubs */ - - - /* File created by MIDL compiler version 8.01.0622 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for RpcInterface.Idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#if defined(_M_AMD64) - - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ -#if _MSC_VER >= 1200 -#pragma warning(push) -#endif - -#pragma warning( disable: 4211 ) /* redefine extern to static */ -#pragma warning( disable: 4232 ) /* dllimport identity*/ -#pragma warning( disable: 4024 ) /* array to pointer mapping*/ - -#include -#include "RpcInterface_h.h" - -#define TYPE_FORMAT_STRING_SIZE 23 -#define PROC_FORMAT_STRING_SIZE 245 -#define EXPR_FORMAT_STRING_SIZE 1 -#define TRANSMIT_AS_TABLE_SIZE 0 -#define WIRE_MARSHAL_TABLE_SIZE 0 - -typedef struct _RpcInterface_MIDL_TYPE_FORMAT_STRING - { - short Pad; - unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_TYPE_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_PROC_FORMAT_STRING - { - short Pad; - unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_PROC_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_EXPR_FORMAT_STRING - { - long Pad; - unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_EXPR_FORMAT_STRING; - - -static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = -{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; - -extern const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString; -extern const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString; -extern const RpcInterface_MIDL_EXPR_FORMAT_STRING RpcInterface__MIDL_ExprFormatString; - -/* Standard interface: RpcInterface, ver. 1.0, - GUID={0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}} */ - - -extern const MIDL_SERVER_INFO RpcInterface_ServerInfo; - -extern const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable; - -static const RPC_SERVER_INTERFACE RpcInterface___RpcServerInterface = - { - sizeof(RPC_SERVER_INTERFACE), - {{0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}},{1,0}}, - {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, - (RPC_DISPATCH_TABLE*)&RpcInterface_v1_0_DispatchTable, - 0, - 0, - 0, - &RpcInterface_ServerInfo, - 0x04000000 - }; -RPC_IF_HANDLE RpcInterface_v1_0_s_ifspec = (RPC_IF_HANDLE)& RpcInterface___RpcServerInterface; - -extern const MIDL_STUB_DESC RpcInterface_StubDesc; - - extern const MIDL_STUBLESS_PROXY_INFO RpcInterface_ProxyInfo; - -/* [callback] */ void MeteringDataEvent( - /* [in] */ __int64 data, - /* [optional][in] */ __int64 context) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[206], - data, - context); - -} - -extern const NDR_RUNDOWN RundownRoutines[]; - -#if !defined(__RPC_WIN64__) -#error Invalid build platform for this stub. -#endif - -static const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString = - { - 0, - { - - /* Procedure RemoteOpen */ - - 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 2 */ NdrFcLong( 0x0 ), /* 0 */ -/* 6 */ NdrFcShort( 0x0 ), /* 0 */ -/* 8 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ - 0x0, /* 0 */ -/* 12 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 14 */ NdrFcShort( 0x0 ), /* 0 */ -/* 16 */ NdrFcShort( 0x38 ), /* 56 */ -/* 18 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 20 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 22 */ NdrFcShort( 0x0 ), /* 0 */ -/* 24 */ NdrFcShort( 0x0 ), /* 0 */ -/* 26 */ NdrFcShort( 0x0 ), /* 0 */ -/* 28 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 30 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ -/* 32 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 34 */ NdrFcShort( 0x6 ), /* Type Offset=6 */ - - /* Procedure RemoteClose */ - -/* 36 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 38 */ NdrFcLong( 0x0 ), /* 0 */ -/* 42 */ NdrFcShort( 0x1 ), /* 1 */ -/* 44 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 46 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe4, /* Ctxt flags: via ptr, in, out, no serialize, */ -/* 48 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 50 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 52 */ NdrFcShort( 0x38 ), /* 56 */ -/* 54 */ NdrFcShort( 0x38 ), /* 56 */ -/* 56 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 58 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 60 */ NdrFcShort( 0x0 ), /* 0 */ -/* 62 */ NdrFcShort( 0x0 ), /* 0 */ -/* 64 */ NdrFcShort( 0x0 ), /* 0 */ -/* 66 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 68 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ -/* 70 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 72 */ NdrFcShort( 0xe ), /* Type Offset=14 */ - - /* Procedure StartMetering */ - -/* 74 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 76 */ NdrFcLong( 0x0 ), /* 0 */ -/* 80 */ NdrFcShort( 0x2 ), /* 2 */ -/* 82 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 84 */ 0x30, /* FC_BIND_CONTEXT */ - 0x44, /* Ctxt flags: in, no serialize, */ -/* 86 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 88 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 90 */ NdrFcShort( 0x44 ), /* 68 */ -/* 92 */ NdrFcShort( 0x0 ), /* 0 */ -/* 94 */ 0x40, /* Oi2 Flags: has ext, */ - 0x3, /* 3 */ -/* 96 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 98 */ NdrFcShort( 0x0 ), /* 0 */ -/* 100 */ NdrFcShort( 0x0 ), /* 0 */ -/* 102 */ NdrFcShort( 0x0 ), /* 0 */ -/* 104 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 106 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 108 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 110 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 112 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 114 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 116 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 118 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 120 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 122 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure SetSamplePeriod */ - -/* 124 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 126 */ NdrFcLong( 0x0 ), /* 0 */ -/* 130 */ NdrFcShort( 0x3 ), /* 3 */ -/* 132 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 134 */ 0x30, /* FC_BIND_CONTEXT */ - 0x44, /* Ctxt flags: in, no serialize, */ -/* 136 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 138 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 140 */ NdrFcShort( 0x34 ), /* 52 */ -/* 142 */ NdrFcShort( 0x0 ), /* 0 */ -/* 144 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 146 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 148 */ NdrFcShort( 0x0 ), /* 0 */ -/* 150 */ NdrFcShort( 0x0 ), /* 0 */ -/* 152 */ NdrFcShort( 0x0 ), /* 0 */ -/* 154 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 156 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 158 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 160 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 162 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 164 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 166 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure StopMetering */ - -/* 168 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 170 */ NdrFcLong( 0x0 ), /* 0 */ -/* 174 */ NdrFcShort( 0x4 ), /* 4 */ -/* 176 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 178 */ 0x30, /* FC_BIND_CONTEXT */ - 0x44, /* Ctxt flags: in, no serialize, */ -/* 180 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 182 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 184 */ NdrFcShort( 0x24 ), /* 36 */ -/* 186 */ NdrFcShort( 0x0 ), /* 0 */ -/* 188 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 190 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 192 */ NdrFcShort( 0x0 ), /* 0 */ -/* 194 */ NdrFcShort( 0x0 ), /* 0 */ -/* 196 */ NdrFcShort( 0x0 ), /* 0 */ -/* 198 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 200 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 202 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 204 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Procedure MeteringDataEvent */ - -/* 206 */ 0x34, /* FC_CALLBACK_HANDLE */ - 0x48, /* Old Flags: */ -/* 208 */ NdrFcLong( 0x0 ), /* 0 */ -/* 212 */ NdrFcShort( 0x0 ), /* 0 */ -/* 214 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 216 */ NdrFcShort( 0x20 ), /* 32 */ -/* 218 */ NdrFcShort( 0x0 ), /* 0 */ -/* 220 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 222 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 224 */ NdrFcShort( 0x0 ), /* 0 */ -/* 226 */ NdrFcShort( 0x0 ), /* 0 */ -/* 228 */ NdrFcShort( 0x0 ), /* 0 */ -/* 230 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter data */ - -/* 232 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 234 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 236 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 238 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 240 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 242 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString = - { - 0, - { - NdrFcShort( 0x0 ), /* 0 */ -/* 2 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ -/* 6 */ 0x30, /* FC_BIND_CONTEXT */ - 0xa4, /* Ctxt flags: via ptr, out, no serialize, */ -/* 8 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 10 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 12 */ NdrFcShort( 0x2 ), /* Offset= 2 (14) */ -/* 14 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe5, /* Ctxt flags: via ptr, in, out, no serialize, can't be null */ -/* 16 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 18 */ 0x30, /* FC_BIND_CONTEXT */ - 0x45, /* Ctxt flags: in, no serialize, can't be null */ -/* 20 */ 0x0, /* 0 */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const NDR_RUNDOWN RundownRoutines[] = - { - PCONTEXT_HANDLE_TYPE_rundown - }; - - -static const unsigned short RpcInterface_FormatStringOffsetTable[] = - { - 0, - 36, - 74, - 124, - 168, - }; - - -static const unsigned short _callbackRpcInterface_FormatStringOffsetTable[] = - { - 206 - }; - - -static const MIDL_STUB_DESC RpcInterface_StubDesc = - { - (void *)& RpcInterface___RpcServerInterface, - MIDL_user_allocate, - MIDL_user_free, - 0, - RundownRoutines, - 0, - 0, - 0, - RpcInterface__MIDL_TypeFormatString.Format, - 1, /* -error bounds_check flag */ - 0x50002, /* Ndr library version */ - 0, - 0x801026e, /* MIDL Version 8.1.622 */ - 0, - 0, - 0, /* notify & notify_flag routine table */ - 0x1, /* MIDL flag */ - 0, /* cs routines */ - 0, /* proxy/server info */ - 0 - }; - -static const RPC_DISPATCH_FUNCTION RpcInterface_table[] = - { - NdrServerCall2, - NdrServerCall2, - NdrServerCall2, - NdrServerCall2, - NdrServerCall2, - 0 - }; -static const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable = - { - 5, - (RPC_DISPATCH_FUNCTION*)RpcInterface_table - }; - -static const SERVER_ROUTINE RpcInterface_ServerRoutineTable[] = - { - (SERVER_ROUTINE)RemoteOpen, - (SERVER_ROUTINE)RemoteClose, - (SERVER_ROUTINE)StartMetering, - (SERVER_ROUTINE)SetSamplePeriod, - (SERVER_ROUTINE)StopMetering, - }; - -static const MIDL_SERVER_INFO RpcInterface_ServerInfo = - { - &RpcInterface_StubDesc, - RpcInterface_ServerRoutineTable, - RpcInterface__MIDL_ProcFormatString.Format, - RpcInterface_FormatStringOffsetTable, - 0, - 0, - 0, - 0}; -#if _MSC_VER >= 1200 -#pragma warning(pop) -#endif - - -#endif /* defined(_M_AMD64)*/ - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.cpp deleted file mode 100644 index 0cad35783..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.cpp +++ /dev/null @@ -1,320 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "stdafx.h" -#include -#include -#include -#include "RpcInterface_h.h" -#include - -#include -#include -#include -#include "RpcServer.h" - -using namespace RpcServer; - -#define DEFAULT_METERING_PERIOD 100 - -bool ShutdownRequested; -static RPC_BINDING_VECTOR* BindingVector = nullptr; - -void FreeSidArray(__inout_ecount(cSIDs) PSID* pSIDs, ULONG cSIDs) -{ - if (pSIDs != nullptr) - { - for (ULONG i = 0; i < cSIDs; i++) - { - LocalFree(pSIDs[i]); - - pSIDs[i] = nullptr; - } - - LocalFree(pSIDs); - - pSIDs = nullptr; - cSIDs = 0; - } -} - -// -// Routine to create RPC server and listen to incoming RPC calls -// -DWORD RpcServerStart() -{ - DWORD hResult = S_OK; - WCHAR* protocolSequence = L"ncalrpc"; - unsigned int minCalls = 1; - unsigned int dontWait = false; - ShutdownRequested = false; - - SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; - PSID everyoneSid = nullptr; - PSID* capabilitySids = nullptr; - DWORD capabilitySidCount = 0; - PSID* capabilityGroupSids = nullptr; - DWORD capabilityGroupSidCount = 0; - EXPLICIT_ACCESS ea[2] = {}; - PACL acl = nullptr; - SECURITY_DESCRIPTOR rpcSecurityDescriptor = {}; - - // When creating the RPC endpoint we want it to allow connections from any UWA that contains - // the custom capability SID in its process token. When a UWA declares the custom capability - // in its app manifest, it will later contain the SID form of that custom capability in its - // process token at runtime. By default, RPC endpoints don't allow UWAs (AppContainer processes) - // to connect to them, so we need to set the security on the endpoint to allow access to UWAs with the - // custom capability. - // - // To do this we'll perform the following steps: - // 1) Convert the custom capability name to a SID - // 2) Create a security descriptor using that SID, as well as other needed SIDs. This sample shows how to allow - // all 'non UWAs' access as well as UWAs containing the custom capability SID. - // 3) Create the RPC endpoint using that security descriptor - // - // To create the security descriptor we're roughly following this MSDN sample: - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa446595(v=vs.85).aspx - - // Get the SID form of the custom capability. In this case we only expect one SID and - // we don't care about the capability group. - //INSERT DERIVE CAPABILTY SIDS FROM NAME HERE - - // Get the SID that represents 'everyone' (this doesn't include AppContainers) - if (!AllocateAndInitializeSid( - &SIDAuthWorld, 1, - SECURITY_WORLD_RID, - 0, 0, 0, 0, 0, 0, 0, - &everyoneSid)) - { - hResult = GetLastError(); - goto end; - } - - // Now create the Access Control List (ACL) for the Security descriptor - - // Everyone GENERIC_ALL access - ea[0].grfAccessMode = SET_ACCESS; - ea[0].grfAccessPermissions = GENERIC_ALL; - ea[0].grfInheritance = NO_INHERITANCE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - ea[0].Trustee.ptstrName = static_cast(everyoneSid); - - // Custom capability GENERIC_ALL access - ea[1].grfAccessMode = SET_ACCESS; - ea[1].grfAccessPermissions = GENERIC_ALL; - ea[1].grfInheritance = NO_INHERITANCE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[1].Trustee.ptstrName = static_cast(everyoneSid); - - hResult = SetEntriesInAcl(ARRAYSIZE(ea), ea, nullptr, &acl); - - if (hResult != ERROR_SUCCESS) - { - goto end; - } - - // Initialize an empty security descriptor - if (!InitializeSecurityDescriptor(&rpcSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) - { - hResult = GetLastError(); - goto end; - } - - // Assign the ACL to the security descriptor - if (!SetSecurityDescriptorDacl(&rpcSecurityDescriptor, TRUE, acl, FALSE)) - { - hResult = GetLastError(); - goto end; - } - - // - // Bind to LRPC using dynamic endpoints - // - hResult = RpcServerUseProtseqEp( - reinterpret_cast(protocolSequence), - RPC_C_PROTSEQ_MAX_REQS_DEFAULT, - reinterpret_cast(RPC_STATIC_ENDPOINT), - &rpcSecurityDescriptor); - - if (hResult != S_OK) - { - goto end; - } - - hResult = RpcServerRegisterIf3( - RpcInterface_v1_0_s_ifspec, - nullptr, - nullptr, - RPC_IF_AUTOLISTEN | RPC_IF_ALLOW_LOCAL_ONLY, - RPC_C_LISTEN_MAX_CALLS_DEFAULT, - 0, - nullptr, - &rpcSecurityDescriptor); - - if (hResult != S_OK) - { - goto end; - } - - hResult = RpcServerInqBindings(&BindingVector); - - if (hResult != S_OK) - { - goto end; - } - - hResult = RpcEpRegister( - RpcInterface_v1_0_s_ifspec, - BindingVector, - nullptr, - nullptr); - - if (hResult != S_OK) - { - goto end; - } - - hResult = RpcServerListen( - minCalls, - RPC_C_LISTEN_MAX_CALLS_DEFAULT, - dontWait); - - if (hResult == RPC_S_ALREADY_LISTENING) - { - hResult = RPC_S_OK; - } - -end: - - // Cleanup sids - FreeSidArray(capabilityGroupSids, capabilityGroupSidCount); - FreeSidArray(capabilitySids, capabilitySidCount); - - if (everyoneSid != nullptr) - { - FreeSid(everyoneSid); - } - - // cleanup acl - if (acl != nullptr) - { - LocalFree(acl); - } - - return hResult; -} - -// -// Notify rpc server to stop listening to incoming rpc calls -// -void RpcServerDisconnect() -{ - DWORD hResult = S_OK; - ShutdownRequested = true; - hResult = RpcServerUnregisterIf(RpcInterface_v1_0_s_ifspec, nullptr, 0); - - RpcEpUnregister(RpcInterface_v1_0_s_ifspec, BindingVector, nullptr); - - if (BindingVector != nullptr) - { - RpcBindingVectorFree(&BindingVector); - BindingVector = nullptr; - } -} - -// -// Rpc method to retrieve client context handle -// -void RemoteOpen( - _In_ handle_t hBinding, - _Out_ PPCONTEXT_HANDLE_TYPE pphContext) -{ - *pphContext = static_cast(midl_user_allocate(sizeof(METERING_CONTEXT))); - METERING_CONTEXT* meteringContext = static_cast(*pphContext); - meteringContext->metering = new Metering(DEFAULT_METERING_PERIOD); -} - -// -// Rpc method to close the client context handle -// -void RemoteClose(_Inout_ PPCONTEXT_HANDLE_TYPE pphContext) -{ - if (*pphContext == nullptr) - { - //Log error, client tried to close a NULL handle. - return; - } - - METERING_CONTEXT* meteringContext = static_cast(*pphContext); - delete meteringContext->metering; - MIDL_user_free(meteringContext); - - // This tells the run-time, when it is marshalling the out - // parameters, that the context handle has been closed normally. - *pphContext = nullptr; -} - -// -// Routine to cleanup client context when client has died with active -// connection with server -// -void __RPC_USER PCONTEXT_HANDLE_TYPE_rundown( - _In_ PCONTEXT_HANDLE_TYPE phContext) -{ - StopMetering(phContext); - RemoteClose(&phContext); -} - -#pragma region METERING_RPCROUTINES - -void StartMetering( - _In_ PCONTEXT_HANDLE_TYPE phContext, - _In_ __int64 period, - _In_ __int64 context) -{ - std::cout << "start metering" << std::endl; - METERING_CONTEXT* meteringContext = static_cast(phContext); - meteringContext->metering->StartMetering(period, context); - std::cout << "done metering" << std::endl; -} - -void SetSamplePeriod( - _In_ PCONTEXT_HANDLE_TYPE phContext, - _In_ __int64 period) -{ - METERING_CONTEXT* meteringContext = static_cast(phContext); - meteringContext->metering->SetSamplePeriod(period); -} - - -void StopMetering(_In_ PCONTEXT_HANDLE_TYPE phContext) -{ - METERING_CONTEXT* meteringContext = static_cast(phContext); - meteringContext->metering->StopMetering(); -} - -#pragma endregion METERING_RPCROUTINES - -/******************************************************/ -/* MIDL allocate and free */ -/******************************************************/ - -void __RPC_FAR * __RPC_USER midl_user_allocate(_In_ size_t len) -{ - return(malloc(len)); -} - -void __RPC_USER midl_user_free(_In_ void __RPC_FAR* ptr) -{ - free(ptr); -} diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.h deleted file mode 100644 index bc7294dbf..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "metering.h" - -#define RPC_STATIC_ENDPOINT L"HsaSampleRpcEndpoint" - -// Client context used for making rpc calls using context handle -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa378674(v=vs.85).aspx -typedef struct -{ - RpcServer::Metering* metering; -} METERING_CONTEXT; - -// Create a rpc server endpoint and listen to incoming rpc calls -DWORD RpcServerStart(); - -// Signal the rpc server to stop listening to incoming rpc calls -void RpcServerDisconnect(); diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.vcxproj b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.vcxproj deleted file mode 100644 index b5c043dc6..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.vcxproj +++ /dev/null @@ -1,284 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Release - ARM - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {ADFC4322-5F0E-5BFD-83DA-19B35EFD513B} - Win32Proj - RpcServer - 10.0.16299.0 - - - - Application - true - v141 - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - Application - false - v141 - true - Unicode - - - Application - true - v141 - Unicode - - - Application - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - true - - - true - $(SolutionDir)$(Platform)\$(Configuration)\ - - - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - false - - - false - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories);$(OutDir) - - - Console - true - onecoreuap.lib;%(AdditionalDependencies);rpcrt4.lib - false - %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib;shell32.lib;gdi32.lib - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories);$(OutDir) - - - Console - true - onecoreuap.lib;%(AdditionalDependencies);rpcrt4.lib - false - %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib;shell32.lib;gdi32.lib - - - - - Use - Level3 - Disabled - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories);$(OutDir) - - - Console - true - onecoreuap.lib;%(AdditionalDependencies);rpcrt4.lib - false - %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib;shell32.lib;gdi32.lib - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories);$(OutDir) - MultiThreaded - - - Console - true - true - true - onecoreuap.lib;%(AdditionalDependencies);ucrt.lib;rpcrt4.lib;libcmt.lib;libvcruntime.lib - true - %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib;shell32.lib;gdi32.lib - /VERBOSE %(AdditionalOptions) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions); - true - %(AdditionalIncludeDirectories);$(OutDir) - MultiThreaded - - - Console - true - true - true - onecoreuap.lib;%(AdditionalDependencies);ucrt.lib;rpcrt4.lib;libcmt.lib;libvcruntime.lib - true - %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib;shell32.lib;gdi32.lib - /VERBOSE %(AdditionalOptions) - - - - - Level3 - Use - MaxSpeed - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories);$(OutDir) - MultiThreaded - - - Console - true - true - true - onecoreuap.lib;%(AdditionalDependencies);ucrt.lib;rpcrt4.lib;libcmt.lib;libvcruntime.lib - true - %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib;shell32.lib;gdi32.lib - /VERBOSE %(AdditionalOptions) - - - - - - - - - - - - - - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.vcxproj.filters b/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.vcxproj.filters deleted file mode 100644 index 9644ad4ed..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/RpcServer.vcxproj.filters +++ /dev/null @@ -1,76 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/SampleService.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/SampleService.cpp deleted file mode 100644 index 793a7009e..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/SampleService.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "stdafx.h" - -#pragma region Includes -#include "SampleService.h" -#include "RpcServer.h" -#include -#pragma endregion - -CSampleService::CSampleService( - PWSTR pszServiceName, - BOOL fCanStop, - BOOL fCanShutdown, - BOOL fCanPauseContinue) - : CServiceBase(pszServiceName, fCanStop, fCanShutdown, fCanPauseContinue) -{ -} - -void CSampleService::WriteEventLogEntry(PWSTR pszMessage, BYTE bLevel) -{ - if (IsConsoleRun()) - { - wprintf(L"%d: %ls\n", bLevel, pszMessage); - } - __super::WriteEventLogEntry(pszMessage, bLevel); -} - -CSampleService::~CSampleService(void) -{ -} - -// -// This is the thread pool work callback function. -// -VOID CALLBACK ServiceWorkerThread( - _In_ PTP_CALLBACK_INSTANCE /*Instance*/, - _In_ PVOID Parameter, - _In_ PTP_WORK /*Work*/) -{ - // - // Do something when the work callback is invoked. - // - { - _int64 status = RpcServerStart(); - if (status) - { - CSampleService* sampleService = static_cast(Parameter); - sampleService->Stop(); - } - } - - return; -} - -// -// FUNCTION: CSampleService::OnStart(DWORD, LPWSTR *) -// -// PURPOSE: The function is executed when a Start command is sent to the -// service by the SCM or when the operating system starts (for a service -// that starts automatically). It specifies actions to take when the -// service starts. In this code sample, OnStart logs a service-start -// message to the Application log, and queues the main service function for -// execution in a thread pool worker thread. -// -// PARAMETERS: -// * dwArgc - number of command line arguments -// * lpszArgv - array of command line arguments -// -// NOTE: A service application is designed to be long running. Therefore, -// it usually polls or monitors something in the system. The monitoring is -// set up in the OnStart method. However, OnStart does not actually do the -// monitoring. The OnStart method must return to the operating system after -// the service's operation has begun. It must not loop forever or block. To -// set up a simple monitoring mechanism, one general solution is to create -// a timer in OnStart. The timer would then raise events in your code -// periodically, at which time your service could do its monitoring. The -// other solution is to spawn a new thread to perform the main service -// functions, which is demonstrated in this code sample. -// -void CSampleService::OnStart( - _In_ DWORD dwArgc, - _In_ LPWSTR *lpszArgv) -{ - // Log a service start message to the Application log. - WriteEventLogEntry(L"CppWindowsService in OnStart", TRACE_LEVEL_INFORMATION); - - // Queue the main service function for execution in a worker thread. - PTP_WORK_CALLBACK workcallback = ServiceWorkerThread; - m_work = CreateThreadpoolWork(workcallback, this, nullptr); - - if (NULL == m_work) - { - // TODO: Capture get last error - WriteEventLogEntry(L"CreateThreadpoolWork failed", TRACE_LEVEL_ERROR); - } - - // - // Submit the work to the pool. Because this was a pre-allocated - // work item (using CreateThreadpoolWork), it is guaranteed to execute. - // - SubmitThreadpoolWork(m_work); -} - -// -// FUNCTION: CSampleService::ConsoleRun() -// -// PURPOSE: The function is executed to simulate OnStart in -// console mode. -// -void CSampleService::ConsoleRun() -{ - m_runningInConsole = true; - - WriteEventLogEntry(L"Starting Rpc Server..", TRACE_LEVEL_INFORMATION); - long status = RpcServerStart(); - - if (status) - { - printf_s("RpcServerConnect returned: 0x%x\n", status); - WriteEventLogEntry(L"Starting Rpc Server..", TRACE_LEVEL_INFORMATION); - exit(static_cast(status)); - } -} - -// -// FUNCTION: CSampleService::OnStop() -// -// PURPOSE: The function is executed when a Stop command is sent to the -// service by SCM. It specifies actions to take when a service stops -// running. In this code sample, OnStop logs a service-stop message to the -// Application log, and waits for the finish of the main service function. -// -// COMMENTS: -// Be sure to periodically call ReportServiceStatus() with -// SERVICE_STOP_PENDING if the procedure is going to take long time. -// -void CSampleService::OnStop() -{ - // Log a service stop message to the Application log. - WriteEventLogEntry(L"CppWindowsService in OnStop", TRACE_LEVEL_INFORMATION); - - // Instruct server to stop listening to remote procedure calls and - // unregister rpc interface - RpcServerDisconnect(); -} \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/SampleService.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/SampleService.h deleted file mode 100644 index 04621b3ef..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/SampleService.h +++ /dev/null @@ -1,46 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -// Provides a sample service class that derives from the service base class - -// CServiceBase. The sample service logs the service start and stop -// information to the Application event log, and shows how to run the main -// function of the service in a thread pool worker thread. - -#pragma once - -#include "ServiceBase.h" - -class CSampleService : public CServiceBase -{ -public: - - CSampleService(PWSTR pszServiceName, - BOOL fCanStop = TRUE, - BOOL fCanShutdown = TRUE, - BOOL fCanPauseContinue = FALSE); - void ConsoleRun(); - bool IsConsoleRun() - { - return m_runningInConsole; - } - void WriteEventLogEntry(PWSTR pszMessage, BYTE bLevel) override; - virtual ~CSampleService(void); - -protected: - - virtual void OnStart(DWORD dwArgc, PWSTR *pszArgv) override; - virtual void OnStop() override; - - -private: - PTP_WORK m_work = nullptr; - bool m_runningInConsole = false; -}; \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceBase.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceBase.cpp deleted file mode 100644 index 117d740ce..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceBase.cpp +++ /dev/null @@ -1,566 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "stdafx.h" -#pragma region Includes - -#include "ServiceBase.h" -#include -#include -#include -#include -#pragma endregion - -// -// HSA Service trace event provider -// {BE2E880E-F79F-4C30-9C95-09F003A0A7EA} -// -EXTERN_C __declspec(selectany) const GUID HSA_SERVICE_PROVIDER_GUID = { 0xbe2e880e, 0xf79f, 0x4c30,{ 0x9c, 0x95, 0x9, 0xf0, 0x3, 0xa0, 0xa7, 0xea } }; - -#pragma region Static Members - -// Initialize the singleton service instance. -CServiceBase *CServiceBase::s_service = nullptr; - - -// -// FUNCTION: CServiceBase::Run(CServiceBase &) -// -// PURPOSE: Register the executable for a service with the Service Control -// Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start -// command, which results in a call to the OnStart method in the service. -// This method blocks until the service has stopped. -// -// PARAMETERS: -// * service - the reference to a CServiceBase object. It will become the -// singleton service instance of this service application. -// -// RETURN VALUE: If the function succeeds, the return value is TRUE. If the -// function fails, the return value is FALSE. To get extended error -// information, call GetLastError. -// -BOOL CServiceBase::Run(CServiceBase &service) -{ - s_service = &service; - - SERVICE_TABLE_ENTRY serviceTable[] = - { - { service.m_name, ServiceMain }, - { nullptr, nullptr } - }; - - // Connects the main thread of a service process to the service control - // manager, which causes the thread to be the service control dispatcher - // thread for the calling process. This call returns when the service has - // stopped. The process should simply terminate when the call returns. - return StartServiceCtrlDispatcher(serviceTable); -} - - -// -// FUNCTION: CServiceBase::ServiceMain(DWORD, PWSTR *) -// -// PURPOSE: Entry point for the service. It registers the handler function -// for the service and starts the service. -// -// PARAMETERS: -// * dwArgc - number of command line arguments -// * lpszArgv - array of command line arguments -// -void WINAPI CServiceBase::ServiceMain(DWORD dwArgc, PWSTR *pszArgv) -{ - assert(s_service != NULL); - - // Register the handler function for the service - s_service->m_statusHandle = RegisterServiceCtrlHandler( - s_service->m_name, ServiceCtrlHandler); - - if (s_service->m_statusHandle == NULL) - { - throw GetLastError(); - } - - // Start the service. - s_service->Start(dwArgc, pszArgv); -} - - -// -// FUNCTION: CServiceBase::ServiceCtrlHandler(DWORD) -// -// PURPOSE: The function is called by the SCM whenever a control code is -// sent to the service. -// -// PARAMETERS: -// * dwCtrlCode - the control code. This parameter can be one of the -// following values: -// -// SERVICE_CONTROL_CONTINUE -// SERVICE_CONTROL_INTERROGATE -// SERVICE_CONTROL_NETBINDADD -// SERVICE_CONTROL_NETBINDDISABLE -// SERVICE_CONTROL_NETBINDREMOVE -// SERVICE_CONTROL_PARAMCHANGE -// SERVICE_CONTROL_PAUSE -// SERVICE_CONTROL_SHUTDOWN -// SERVICE_CONTROL_STOP -// -// This parameter can also be a user-defined control code ranges from 128 -// to 255. -// -void WINAPI CServiceBase::ServiceCtrlHandler(DWORD dwCtrl) -{ - switch (dwCtrl) - { - case SERVICE_CONTROL_STOP: s_service->Stop(); break; - case SERVICE_CONTROL_PAUSE: s_service->Pause(); break; - case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break; - case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break; - case SERVICE_CONTROL_INTERROGATE: break; - default: break; - } -} - -#pragma endregion - - -#pragma region Service Constructor and Destructor - -// -// FUNCTION: CServiceBase::CServiceBase(PWSTR, BOOL, BOOL, BOOL) -// -// PURPOSE: The constructor of CServiceBase. It initializes a new instance -// of the CServiceBase class. The optional parameters (fCanStop, -/// fCanShutdown and fCanPauseContinue) allow you to specify whether the -// service can be stopped, paused and continued, or be notified when system -// shutdown occurs. -// -// PARAMETERS: -// * pszServiceName - the name of the service -// * fCanStop - the service can be stopped -// * fCanShutdown - the service is notified when system shutdown occurs -// * fCanPauseContinue - the service can be paused and continued -// -CServiceBase::CServiceBase( - PWSTR pszServiceName, - BOOL fCanStop, - BOOL fCanShutdown, - BOOL fCanPauseContinue) -{ - // Service name must be a valid string and cannot be NULL. - m_name = (pszServiceName == nullptr) ? L"" : pszServiceName; - - m_statusHandle = nullptr; - - // The service runs in its own process. - m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - - // The service is starting. - m_status.dwCurrentState = SERVICE_START_PENDING; - - // The accepted commands of the service. - DWORD dwControlsAccepted = 0; - if (fCanStop) - dwControlsAccepted |= SERVICE_ACCEPT_STOP; - if (fCanShutdown) - dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN; - if (fCanPauseContinue) - dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; - m_status.dwControlsAccepted = dwControlsAccepted; - - m_status.dwWin32ExitCode = NO_ERROR; - m_status.dwServiceSpecificExitCode = 0; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - - NTSTATUS status = EventRegister(&HSA_SERVICE_PROVIDER_GUID, - nullptr, - nullptr, - &m_etwRegHandle); - if (ERROR_SUCCESS != status) - { - wprintf(L"Provider not registered. EventRegister failed with %d\n", status); - } -} - - -// -// FUNCTION: CServiceBase::~CServiceBase() -// -// PURPOSE: The virtual destructor of CServiceBase. -// -CServiceBase::~CServiceBase(void) -{ - if (m_etwRegHandle != NULL) - { - EventUnregister(m_etwRegHandle); - } -} - -#pragma endregion - - -#pragma region Service Start, Stop, Pause, Continue, and Shutdown - -// -// FUNCTION: CServiceBase::Start(DWORD, PWSTR *) -// -// PURPOSE: The function starts the service. It calls the OnStart virtual -// function in which you can specify the actions to take when the service -// starts. If an error occurs during the startup, the error will be logged -// in the Application event log, and the service will be stopped. -// -// PARAMETERS: -// * dwArgc - number of command line arguments -// * lpszArgv - array of command line arguments -// -void CServiceBase::Start(DWORD dwArgc, PWSTR *pszArgv) -{ - WriteEventLogEntry(L"Service trying to start.", TRACE_LEVEL_ERROR); - try - { - // Tell SCM that the service is starting. - SetServiceStatus(SERVICE_START_PENDING); - - // Perform service-specific initialization. - OnStart(dwArgc, pszArgv); - - // Tell SCM that the service is started. - SetServiceStatus(SERVICE_RUNNING); - } - catch (DWORD dwError) - { - // Log the error. - WriteErrorLogEntry(L"Service Start", dwError); - - // Set the service status to be stopped. - SetServiceStatus(SERVICE_STOPPED, dwError); - } - catch (...) - { - // Log the error. - WriteEventLogEntry(L"Service failed to start.", TRACE_LEVEL_ERROR); - - // Set the service status to be stopped. - SetServiceStatus(SERVICE_STOPPED); - } -} - - -// -// FUNCTION: CServiceBase::OnStart(DWORD, PWSTR *) -// -// PURPOSE: When implemented in a derived class, executes when a Start -// command is sent to the service by the SCM or when the operating system -// starts (for a service that starts automatically). Specifies actions to -// take when the service starts. Be sure to periodically call -// CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the -// procedure is going to take long time. You may also consider spawning a -// new thread in OnStart to perform time-consuming initialization tasks. -// -// PARAMETERS: -// * dwArgc - number of command line arguments -// * lpszArgv - array of command line arguments -// -void CServiceBase::OnStart(DWORD dwArgc, PWSTR *pszArgv) -{ -} - - -// -// FUNCTION: CServiceBase::Stop() -// -// PURPOSE: The function stops the service. It calls the OnStop virtual -// function in which you can specify the actions to take when the service -// stops. If an error occurs, the error will be logged in the Application -// event log, and the service will be restored to the original state. -// -void CServiceBase::Stop() -{ - DWORD dwOriginalState = m_status.dwCurrentState; - try - { - // Tell SCM that the service is stopping. - SetServiceStatus(SERVICE_STOP_PENDING); - - // Perform service-specific stop operations. - OnStop(); - - // Tell SCM that the service is stopped. - SetServiceStatus(SERVICE_STOPPED); - } - catch (DWORD dwError) - { - // Log the error. - WriteErrorLogEntry(L"Service Stop", dwError); - - // Set the orginal service status. - SetServiceStatus(dwOriginalState); - } - catch (...) - { - // Log the error. - WriteEventLogEntry(L"Service failed to stop.", TRACE_LEVEL_ERROR); - - // Set the orginal service status. - SetServiceStatus(dwOriginalState); - } -} - - -// -// FUNCTION: CServiceBase::OnStop() -// -// PURPOSE: When implemented in a derived class, executes when a Stop -// command is sent to the service by the SCM. Specifies actions to take -// when a service stops running. Be sure to periodically call -// CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the -// procedure is going to take long time. -// -void CServiceBase::OnStop() -{ -} - - -// -// FUNCTION: CServiceBase::Pause() -// -// PURPOSE: The function pauses the service if the service supports pause -// and continue. It calls the OnPause virtual function in which you can -// specify the actions to take when the service pauses. If an error occurs, -// the error will be logged in the Application event log, and the service -// will become running. -// -void CServiceBase::Pause() -{ - try - { - // Tell SCM that the service is pausing. - SetServiceStatus(SERVICE_PAUSE_PENDING); - - // Perform service-specific pause operations. - OnPause(); - - // Tell SCM that the service is paused. - SetServiceStatus(SERVICE_PAUSED); - } - catch (DWORD dwError) - { - // Log the error. - WriteErrorLogEntry(L"Service Pause", dwError); - - // Tell SCM that the service is still running. - SetServiceStatus(SERVICE_RUNNING); - } - catch (...) - { - // Log the error. - WriteEventLogEntry(L"Service failed to pause.", TRACE_LEVEL_ERROR); - - // Tell SCM that the service is still running. - SetServiceStatus(SERVICE_RUNNING); - } -} - - -// -// FUNCTION: CServiceBase::OnPause() -// -// PURPOSE: When implemented in a derived class, executes when a Pause -// command is sent to the service by the SCM. Specifies actions to take -// when a service pauses. -// -void CServiceBase::OnPause() -{ -} - - -// -// FUNCTION: CServiceBase::Continue() -// -// PURPOSE: The function resumes normal functioning after being paused if -// the service supports pause and continue. It calls the OnContinue virtual -// function in which you can specify the actions to take when the service -// continues. If an error occurs, the error will be logged in the -// Application event log, and the service will still be paused. -// -void CServiceBase::Continue() -{ - try - { - // Tell SCM that the service is resuming. - SetServiceStatus(SERVICE_CONTINUE_PENDING); - - // Perform service-specific continue operations. - OnContinue(); - - // Tell SCM that the service is running. - SetServiceStatus(SERVICE_RUNNING); - } - catch (DWORD dwError) - { - // Log the error. - WriteErrorLogEntry(L"Service Continue", dwError); - - // Tell SCM that the service is still paused. - SetServiceStatus(SERVICE_PAUSED); - } - catch (...) - { - // Log the error. - WriteEventLogEntry(L"Service failed to resume.", TRACE_LEVEL_ERROR); - - // Tell SCM that the service is still paused. - SetServiceStatus(SERVICE_PAUSED); - } -} - - -// -// FUNCTION: CServiceBase::OnContinue() -// -// PURPOSE: When implemented in a derived class, OnContinue runs when a -// Continue command is sent to the service by the SCM. Specifies actions to -// take when a service resumes normal functioning after being paused. -// -void CServiceBase::OnContinue() -{ -} - - -// -// FUNCTION: CServiceBase::Shutdown() -// -// PURPOSE: The function executes when the system is shutting down. It -// calls the OnShutdown virtual function in which you can specify what -// should occur immediately prior to the system shutting down. If an error -// occurs, the error will be logged in the Application event log. -// -void CServiceBase::Shutdown() -{ - try - { - // Perform service-specific shutdown operations. - OnShutdown(); - - // Tell SCM that the service is stopped. - SetServiceStatus(SERVICE_STOPPED); - } - catch (DWORD dwError) - { - // Log the error. - WriteErrorLogEntry(L"Service Shutdown", dwError); - } - catch (...) - { - // Log the error. - WriteEventLogEntry(L"Service failed to shut down.", TRACE_LEVEL_ERROR); - } -} - - -// -// FUNCTION: CServiceBase::OnShutdown() -// -// PURPOSE: When implemented in a derived class, executes when the system -// is shutting down. Specifies what should occur immediately prior to the -// system shutting down. -// -void CServiceBase::OnShutdown() -{ -} - -#pragma endregion - - -#pragma region Helper Functions - -// -// FUNCTION: CServiceBase::SetServiceStatus(DWORD, DWORD, DWORD) -// -// PURPOSE: The function sets the service status and reports the status to -// the SCM. -// -// PARAMETERS: -// * dwCurrentState - the state of the service -// * dwWin32ExitCode - error code to report -// * dwWaitHint - estimated time for pending operation, in milliseconds -// -void CServiceBase::SetServiceStatus( - _In_ DWORD dwCurrentState, - _In_ DWORD dwWin32ExitCode, - _In_ DWORD dwWaitHint) -{ - static DWORD dwCheckPoint = 1; - - // Fill in the SERVICE_STATUS structure of the service. - - m_status.dwCurrentState = dwCurrentState; - m_status.dwWin32ExitCode = dwWin32ExitCode; - m_status.dwWaitHint = dwWaitHint; - - m_status.dwCheckPoint = - ((dwCurrentState == SERVICE_RUNNING) || - (dwCurrentState == SERVICE_STOPPED)) ? - 0 : dwCheckPoint++; - - // Report the status of the service to the SCM. - ::SetServiceStatus(m_statusHandle, &m_status); -} - - -// -// FUNCTION: CServiceBase::WriteEventLogEntry(PWSTR, WORD) -// -// PURPOSE: Log an event. -// -// PARAMETERS: -// * pszMessage - string message to be logged. -// * wType - the type of event to be logged. The parameter can be one of -// the following values. -// -// EVENTLOG_SUCCESS -// EVENTLOG_AUDIT_FAILURE -// EVENTLOG_AUDIT_SUCCESS -// EVENTLOG_ERROR_TYPE -// EVENTLOG_INFORMATION_TYPE -// EVENTLOG_WARNING_TYPE -// -void CServiceBase::WriteEventLogEntry( - _In_ PWSTR pszMessage, - _In_ BYTE bLevel) -{ - if (m_etwRegHandle != NULL) - { - EventWriteString(m_etwRegHandle, bLevel, 0, pszMessage); - } -} - -// -// FUNCTION: CServiceBase::WriteErrorLogEntry(PWSTR, DWORD) -// -// PURPOSE: Log an event. -// -// PARAMETERS: -// * pszFunction - the function that gives the error -// * dwError - the error code -// -void CServiceBase::WriteErrorLogEntry( - _In_ PWSTR pszFunction, - _In_ DWORD dwError) -{ - wchar_t szMessage[260]; - StringCchPrintf(szMessage, ARRAYSIZE(szMessage), - L"%s failed w/err 0x%08lx", pszFunction, dwError); - WriteEventLogEntry(szMessage, TRACE_LEVEL_ERROR); -} - -#pragma endregion \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceBase.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceBase.h deleted file mode 100644 index ebae808e0..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceBase.h +++ /dev/null @@ -1,121 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -// Provides a base class for a service that will exist as part of a service -// application. CServiceBase must be derived from when creating a new service -// class. - -#pragma once - -#include -#include - -class CServiceBase -{ -public: - - // Register the executable for a service with the Service Control Manager - // (SCM). After you call Run(ServiceBase), the SCM issues a Start command, - // which results in a call to the OnStart method in the service. This - // method blocks until the service has stopped. - static BOOL Run(CServiceBase& service); - - // Service object constructor. The optional parameters (fCanStop, - // fCanShutdown and fCanPauseContinue) allow you to specify whether the - // service can be stopped, paused and continued, or be notified when - // system shutdown occurs. - CServiceBase(PWSTR pszServiceName, - BOOL fCanStop = TRUE, - BOOL fCanShutdown = TRUE, - BOOL fCanPauseContinue = FALSE); - - // Service object destructor. - virtual ~CServiceBase(void); - - // Stop the service. - void Stop(); - -protected: - - // When implemented in a derived class, executes when a Start command is - // sent to the service by the SCM or when the operating system starts - // (for a service that starts automatically). Specifies actions to take - // when the service starts. - virtual void OnStart(DWORD dwArgc, PWSTR *pszArgv); - - // When implemented in a derived class, executes when a Stop command is - // sent to the service by the SCM. Specifies actions to take when a - // service stops running. - virtual void OnStop(); - - // When implemented in a derived class, executes when a Pause command is - // sent to the service by the SCM. Specifies actions to take when a - // service pauses. - virtual void OnPause(); - - // When implemented in a derived class, OnContinue runs when a Continue - // command is sent to the service by the SCM. Specifies actions to take - // when a service resumes normal functioning after being paused. - virtual void OnContinue(); - - // When implemented in a derived class, executes when the system is - // shutting down. Specifies what should occur immediately prior to the - // system shutting down. - virtual void OnShutdown(); - - // Set the service status and report the status to the SCM. - void SetServiceStatus(DWORD dwCurrentState, - DWORD dwWin32ExitCode = NO_ERROR, - DWORD dwWaitHint = 0); - - // Log an event. - virtual void WriteEventLogEntry(PWSTR pszMessage, BYTE bLevel); - - // Log an event. - void WriteErrorLogEntry(PWSTR pszFunction, - DWORD dwError = GetLastError()); - -private: - - // Entry point for the service. It registers the handler function for the - // service and starts the service. - static void WINAPI ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv); - - // The function is called by the SCM whenever a control code is sent to - // the service. - static void WINAPI ServiceCtrlHandler(DWORD dwCtrl); - - // Start the service. - void Start(DWORD dwArgc, PWSTR *pszArgv); - - // Pause the service. - void Pause(); - - // Resume the service after being paused. - void Continue(); - - // Execute when the system is shutting down. - void Shutdown(); - - // The singleton service instance. - static CServiceBase *s_service; - - // The name of the service - PWSTR m_name; - - // The status of the service - SERVICE_STATUS m_status; - - // The service status handle - SERVICE_STATUS_HANDLE m_statusHandle; - - REGHANDLE m_etwRegHandle; -}; \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceInstaller.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceInstaller.cpp deleted file mode 100644 index 27b107a91..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceInstaller.cpp +++ /dev/null @@ -1,191 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "stdafx.h" -#pragma region "Includes" - -#include -#include -#include "ServiceInstaller.h" -#pragma endregion - - -// -// FUNCTION: InstallService -// -// PURPOSE: Install the current application as a service to the local -// service control manager database. -// -// PARAMETERS: -// * pszServiceName - the name of the service to be installed -// * pszDisplayName - the display name of the service -// * dwStartType - the service start option. This parameter can be one of -// the following values: SERVICE_AUTO_START, SERVICE_BOOT_START, -// SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START. -// * pszDependencies - a pointer to a double null-terminated array of null- -// separated names of services or load ordering groups that the system -// must start before this service. -// * pszAccount - the name of the account under which the service runs. -// * pszPassword - the password to the account name. -// -// NOTE: If the function fails to install the service, it prints the error -// in the standard output stream for users to diagnose the problem. -// -void InstallService( - _In_ PWSTR pszServiceName, - _In_ PWSTR pszDisplayName, - _In_ DWORD dwStartType, - _In_ PWSTR pszDependencies, - _In_ PWSTR pszAccount, - _In_ PWSTR pszPassword) -{ - wchar_t szPath[MAX_PATH]; - SC_HANDLE schSCManager = nullptr; - SC_HANDLE schService = nullptr; - - if (GetModuleFileName(nullptr, szPath, ARRAYSIZE(szPath)) == 0) - { - wprintf(L"GetModuleFileName failed w/err 0x%08lx\n", GetLastError()); - goto Cleanup; - } - - // Open the local default service control manager database - schSCManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT | - SC_MANAGER_CREATE_SERVICE); - if (schSCManager == nullptr) - { - wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError()); - goto Cleanup; - } - - // Install the service into SCM by calling CreateService - schService = CreateService( - schSCManager, // SCManager database - pszServiceName, // Name of service - pszDisplayName, // Name to display - SERVICE_QUERY_STATUS, // Desired access - SERVICE_WIN32_OWN_PROCESS, // Service type - dwStartType, // Service start type - SERVICE_ERROR_NORMAL, // Error control type - szPath, // Service's binary - nullptr, // No load ordering group - nullptr, // No tag identifier - pszDependencies, // Dependencies - pszAccount, // Service running account - pszPassword // Password of the account - ); - - if (schService == nullptr) - { - wprintf(L"CreateService failed w/err 0x%08lx\n", GetLastError()); - goto Cleanup; - } - - wprintf(L"%s is installed.\n", pszServiceName); - -Cleanup: - // Centralized cleanup for all allocated resources. - if (schSCManager) - { - CloseServiceHandle(schSCManager); - schSCManager = nullptr; - } - if (schService) - { - CloseServiceHandle(schService); - schService = nullptr; - } -} - - -// -// FUNCTION: UninstallService -// -// PURPOSE: Stop and remove the service from the local service control -// manager database. -// -// PARAMETERS: -// * pszServiceName - the name of the service to be removed. -// -// NOTE: If the function fails to uninstall the service, it prints the -// error in the standard output stream for users to diagnose the problem. -// -void UninstallService(_In_ PWSTR pszServiceName) -{ - SC_HANDLE schSCManager = nullptr; - SC_HANDLE schService = nullptr; - SERVICE_STATUS ssSvcStatus = {}; - - // Open the local default service control manager database - schSCManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT); - if (schSCManager == nullptr) - { - wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError()); - goto Cleanup; - } - - // Open the service with delete, stop, and query status permissions - schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP | - SERVICE_QUERY_STATUS | DELETE); - if (schService == nullptr) - { - wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError()); - goto Cleanup; - } - - // Try to stop the service - if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus)) - { - wprintf(L"Stopping %s.", pszServiceName); - Sleep(1000); - - while (QueryServiceStatus(schService, &ssSvcStatus)) - { - if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING) - { - wprintf(L"."); - Sleep(1000); - } - else break; - } - - if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED) - { - wprintf(L"\n%s is stopped.\n", pszServiceName); - } - else - { - wprintf(L"\n%s failed to stop.\n", pszServiceName); - } - } - - // Now remove the service by calling DeleteService. - if (!DeleteService(schService)) - { - wprintf(L"DeleteService failed w/err 0x%08lx\n", GetLastError()); - goto Cleanup; - } - - wprintf(L"%s is removed.\n", pszServiceName); - -Cleanup: - // Centralized cleanup for all allocated resources. - if (schSCManager) - { - CloseServiceHandle(schSCManager); - schSCManager = nullptr; - } - if (schService) - { - CloseServiceHandle(schService); - schService = nullptr; - } -} \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceInstaller.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceInstaller.h deleted file mode 100644 index af6507e61..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/ServiceInstaller.h +++ /dev/null @@ -1,57 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -// The file declares functions that install and uninstall the service. - -#pragma once - -// -// FUNCTION: InstallService -// -// PURPOSE: Install the current application as a service to the local -// service control manager database. -// -// PARAMETERS: -// * pszServiceName - the name of the service to be installed -// * pszDisplayName - the display name of the service -// * dwStartType - the service start option. This parameter can be one of -// the following values: SERVICE_AUTO_START, SERVICE_BOOT_START, -// SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START. -// * pszDependencies - a pointer to a double null-terminated array of null- -// separated names of services or load ordering groups that the system -// must start before this service. -// * pszAccount - the name of the account under which the service runs. -// * pszPassword - the password to the account name. -// -// NOTE: If the function fails to install the service, it prints the error -// in the standard output stream for users to diagnose the problem. -// -void InstallService(PWSTR pszServiceName, - PWSTR pszDisplayName, - DWORD dwStartType, - PWSTR pszDependencies, - PWSTR pszAccount, - PWSTR pszPassword); - - -// -// FUNCTION: UninstallService -// -// PURPOSE: Stop and remove the service from the local service control -// manager database. -// -// PARAMETERS: -// * pszServiceName - the name of the service to be removed. -// -// NOTE: If the function fails to uninstall the service, it prints the -// error in the standard output stream for users to diagnose the problem. -// -void UninstallService(PWSTR pszServiceName); diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/stdafx.cpp b/general/WinHEC 2017 Lab/Toaster Driver/Service/stdafx.cpp deleted file mode 100644 index ce19a949d..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// RpcServer.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/stdafx.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/stdafx.h deleted file mode 100644 index 306c43301..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/stdafx.h +++ /dev/null @@ -1,15 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#include -#include - -#define NOMINMAX // disable min and max macros in windows.h - -extern bool ShutdownRequested; diff --git a/general/WinHEC 2017 Lab/Toaster Driver/Service/targetver.h b/general/WinHEC 2017 Lab/Toaster Driver/Service/targetver.h deleted file mode 100644 index 87c0086de..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/Service/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster.sln b/general/WinHEC 2017 Lab/Toaster Driver/toaster.sln deleted file mode 100644 index 35e5dcbc0..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster.sln +++ /dev/null @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.12 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "toaster", "toaster\toaster.vcxproj", "{2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|ARM.ActiveCfg = Debug|ARM - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|ARM.Build.0 = Debug|ARM - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|ARM64.Build.0 = Debug|ARM64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|x64.ActiveCfg = Debug|x64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|x64.Build.0 = Debug|x64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|x86.ActiveCfg = Debug|Win32 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Debug|x86.Build.0 = Debug|Win32 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|ARM.ActiveCfg = Release|ARM - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|ARM.Build.0 = Release|ARM - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|ARM64.ActiveCfg = Release|ARM64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|ARM64.Build.0 = Release|ARM64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|x64.ActiveCfg = Release|x64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|x64.Build.0 = Release|x64 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|x86.ActiveCfg = Release|Win32 - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/driver.h b/general/WinHEC 2017 Lab/Toaster Driver/toaster/driver.h deleted file mode 100644 index 8e7ade01e..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/driver.h +++ /dev/null @@ -1,80 +0,0 @@ -/*++ -Copyright (c) 1990-2000 Microsoft Corporation All Rights Reserved - -Module Name: - - driver.h - -Abstract: - - This module contains the common declarations for the - bus, function and filter drivers. - -Environment: - - kernel mode only - ---*/ - -//#include "public.h" - -// -// Define an Interface Guid to access the proprietary toaster interface. -// This guid is used to identify a specific interface in IRP_MN_QUERY_INTERFACE -// handler. -// - -DEFINE_GUID(GUID_TOASTER_INTERFACE_STANDARD, - 0xe0b27630, 0x5434, 0x11d3, 0xb8, 0x90, 0x0, 0xc0, 0x4f, 0xad, 0x51, 0x71); -// {E0B27630-5434-11d3-B890-00C04FAD5171} - - -// -// GUID definition are required to be outside of header inclusion pragma to avoid -// error during precompiled headers. -// - -#ifndef __DRIVER_H -#define __DRIVER_H - -// -// Define Interface reference/dereference routines for -// Interfaces exported by IRP_MN_QUERY_INTERFACE -// - -typedef VOID (*PINTERFACE_REFERENCE)(PVOID Context); -typedef VOID (*PINTERFACE_DEREFERENCE)(PVOID Context); - -typedef -BOOLEAN -(*PTOASTER_GET_CRISPINESS_LEVEL)( - IN PVOID Context, - OUT PUCHAR Level - ); - -typedef -BOOLEAN -(*PTOASTER_SET_CRISPINESS_LEVEL)( - IN PVOID Context, - OUT UCHAR Level - ); - -typedef -BOOLEAN -(*PTOASTER_IS_CHILD_PROTECTED)( - IN PVOID Context - ); - -// -// Interface for getting and setting power level etc., -// -typedef struct _TOASTER_INTERFACE_STANDARD { - INTERFACE InterfaceHeader; - PTOASTER_GET_CRISPINESS_LEVEL GetCrispinessLevel; - PTOASTER_SET_CRISPINESS_LEVEL SetCrispinessLevel; - PTOASTER_IS_CHILD_PROTECTED IsSafetyLockEnabled; //): -} TOASTER_INTERFACE_STANDARD, *PTOASTER_INTERFACE_STANDARD; - - -#endif - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/public.h b/general/WinHEC 2017 Lab/Toaster Driver/toaster/public.h deleted file mode 100644 index 0628f95f9..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/public.h +++ /dev/null @@ -1,167 +0,0 @@ -/*++ -Copyright (c) 1990-2000 Microsoft Corporation All Rights Reserved - -Module Name: - - public.h - -Abstract: - - This module contains the common declarations shared by driver - and user applications. - -Environment: - - user and kernel - ---*/ - -// -// Define an Interface Guid for bus enumerator class. -// This GUID is used to register (IoRegisterDeviceInterface) -// an instance of an interface so that enumerator application -// can send an ioctl to the bus driver. -// - -DEFINE_GUID (GUID_DEVINTERFACE_BUSENUM_TOASTER, - 0xD35F7840, 0x6A0C, 0x11d2, 0xB8, 0x41, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71); -// {D35F7840-6A0C-11d2-B841-00C04FAD5171} - -// -// Define an Interface Guid for toaster device class. -// This GUID is used to register (IoRegisterDeviceInterface) -// an instance of an interface so that user application -// can control the toaster device. -// - -DEFINE_GUID (GUID_DEVINTERFACE_TOASTER, - 0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71); -//{781EF630-72B2-11d2-B852-00C04FAD5171} - -// -// Define a Setup Class GUID for Toaster Class. This is same -// as the TOASTSER CLASS guid in the INF files. -// - -DEFINE_GUID (GUID_DEVCLASS_TOASTER, - 0xB85B7C50, 0x6A01, 0x11d2, 0xB8, 0x41, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71); -//{B85B7C50-6A01-11d2-B841-00C04FAD5171} - -// -// Define a WMI GUID to get busenum info. -// - -DEFINE_GUID (TOASTER_BUS_WMI_STD_DATA_GUID, - 0x0006A660, 0x8F12, 0x11d2, 0xB8, 0x54, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71); -//{0006A660-8F12-11d2-B854-00C04FAD5171} - -// -// Define a WMI GUID to get toaster device info. -// - -DEFINE_GUID (TOASTER_WMI_STD_DATA_GUID, - 0xBBA21300L, 0x6DD3, 0x11d2, 0xB8, 0x44, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71); - -// -// Define a WMI GUID to represent device arrival notification WMIEvent class. -// - -DEFINE_GUID (TOASTER_NOTIFY_DEVICE_ARRIVAL_EVENT, - 0x1cdaff1, 0xc901, 0x45b4, 0xb3, 0x59, 0xb5, 0x54, 0x27, 0x25, 0xe2, 0x9c); -// {01CDAFF1-C901-45b4-B359-B5542725E29C} - - -// -// GUID definition are required to be outside of header inclusion pragma to avoid -// error during precompiled headers. -// - -#ifndef __PUBLIC_H -#define __PUBLIC_H - -#define BUS_HARDWARE_IDS L"{B85B7C50-6A01-11d2-B841-00C04FAD5171}\\MsToaster\0" -#define BUS_HARDWARE_IDS_LENGTH sizeof (BUS_HARDWARE_IDS) - -#define BUSENUM_COMPATIBLE_IDS L"{B85B7C50-6A01-11d2-B841-00C04FAD5171}\\MsCompatibleToaster\0" -#define BUSENUM_COMPATIBLE_IDS_LENGTH sizeof(BUSENUM_COMPATIBLE_IDS) - - -#define FILE_DEVICE_BUSENUM FILE_DEVICE_BUS_EXTENDER - -#define BUSENUM_IOCTL(_index_) \ - CTL_CODE (FILE_DEVICE_BUSENUM, _index_, METHOD_BUFFERED, FILE_READ_DATA) - -#define IOCTL_BUSENUM_PLUGIN_HARDWARE BUSENUM_IOCTL (0x0) -#define IOCTL_BUSENUM_UNPLUG_HARDWARE BUSENUM_IOCTL (0x1) -#define IOCTL_BUSENUM_EJECT_HARDWARE BUSENUM_IOCTL (0x2) -#define IOCTL_TOASTER_DONT_DISPLAY_IN_UI_DEVICE BUSENUM_IOCTL (0x3) - -// -// Data structure used in PlugIn and UnPlug ioctls -// - -typedef struct _BUSENUM_PLUGIN_HARDWARE -{ - // - // sizeof (struct _BUSENUM_HARDWARE) - // - IN ULONG Size; - - // - // Unique serial number of the device to be enumerated. - // Enumeration will be failed if another device on the - // bus has the same serail number. - // - - IN ULONG SerialNo; - - // - // An array of (zero terminated wide character strings). The array itself - // also null terminated (ie, MULTI_SZ) - // - #pragma warning(disable:4200) // nonstandard extension used - - IN WCHAR HardwareIDs[]; - - #pragma warning(default:4200) - -} BUSENUM_PLUGIN_HARDWARE, *PBUSENUM_PLUGIN_HARDWARE; - -typedef struct _BUSENUM_UNPLUG_HARDWARE -{ - // - // sizeof (struct _REMOVE_HARDWARE) - // - - IN ULONG Size; - - // - // Serial number of the device to be plugged out - // - - ULONG SerialNo; - - ULONG Reserved[2]; - -} BUSENUM_UNPLUG_HARDWARE, *PBUSENUM_UNPLUG_HARDWARE; - -typedef struct _BUSENUM_EJECT_HARDWARE -{ - // - // sizeof (struct _EJECT_HARDWARE) - // - - IN ULONG Size; - - // - // Serial number of the device to be ejected - // - - ULONG SerialNo; - - ULONG Reserved[2]; - -} BUSENUM_EJECT_HARDWARE, *PBUSENUM_EJECT_HARDWARE; - -#endif - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c deleted file mode 100644 index 7b1172405..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c +++ /dev/null @@ -1,418 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Toaster.c - -Abstract: - - This is a simple form of function driver for toaster device. The driver - doesn't handle any PnP and Power events because the framework provides - default behavior for those events. This driver has enough support to - allow an user application (toast/notify.exe) to open the device - interface registered by the driver and send read, write or ioctl requests. - -Environment: - - Kernel mode - ---*/ - -#include "toaster.h" - -#ifdef ALLOC_PRAGMA -#pragma alloc_text (INIT, DriverEntry) -#pragma alloc_text (PAGE, ToasterEvtDeviceAdd) -#pragma alloc_text (PAGE, ToasterEvtIoRead) -#pragma alloc_text (PAGE, ToasterEvtIoWrite) -#pragma alloc_text (PAGE, ToasterEvtIoDeviceControl) -#endif - - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - DriverEntry initializes the driver and is the first routine called by the - system after the driver is loaded. DriverEntry configures and creates a WDF driver - object. - . -Parameters Description: - - DriverObject - represents the instance of the function driver that is loaded - into memory. DriverObject is allocated by the system before the - driver is loaded, and it is released by the system after the system unloads - the function driver from memory. - - RegistryPath - represents the driver specific path in the Registry. - The function driver can use the path to store driver related data between - reboots. The path does not store hardware instance specific data. - -Return Value: - - STATUS_SUCCESS if successful, - STATUS_UNSUCCESSFUL otherwise. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDF_DRIVER_CONFIG config; - - KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n")); - - // - // Initialize driver config to control the attributes that - // are global to the driver. Note that framework by default - // provides a driver unload routine. If DriverEntry creates any resources - // that require clean-up in driver unload, - // you can manually override the default by supplying a pointer to the EvtDriverUnload - // callback in the config structure. In general xxx_CONFIG_INIT macros are provided to - // initialize most commonly used members. - // - - WDF_DRIVER_CONFIG_INIT( - &config, - ToasterEvtDeviceAdd - ); - - - // - // Create a framework driver object to represent our driver. - // - status = WdfDriverCreate( - DriverObject, - RegistryPath, - WDF_NO_OBJECT_ATTRIBUTES, // Driver Attributes - &config, // Driver Config Info - WDF_NO_HANDLE - ); - - if (!NT_SUCCESS(status)) { - KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status)); - } - - return status; -} - - -NTSTATUS -ToasterEvtDeviceAdd( - IN WDFDRIVER Driver, - IN PWDFDEVICE_INIT DeviceInit - ) -/*++ -Routine Description: - - ToasterEvtDeviceAdd is called by the framework in response to AddDevice - call from the PnP manager. We create and initialize a WDF device object to - represent a new instance of toaster device. - -Arguments: - - Driver - Handle to a framework driver object created in DriverEntry - - DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PFDO_DATA fdoData; - WDF_IO_QUEUE_CONFIG queueConfig; - WDF_OBJECT_ATTRIBUTES fdoAttributes; - WDFDEVICE hDevice; - WDFQUEUE queue; - - UNREFERENCED_PARAMETER(Driver); - - PAGED_CODE(); - - KdPrint(("ToasterEvtDeviceAdd called\n")); - - // - // Initialize attributes and a context area for the device object. - // - // - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DATA); - - // - // Create a framework device object.This call will in turn create - // a WDM device object, attach to the lower stack, and set the - // appropriate flags and attributes. - // - status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &hDevice); - if (!NT_SUCCESS(status)) { - KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status)); - return status; - } - - // - // Get the device context by using the accessor function specified in - // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for FDO_DATA. - // - fdoData = ToasterFdoGetData(hDevice); - - // - // Tell the Framework that this device will need an interface - // - status = WdfDeviceCreateDeviceInterface( - hDevice, - (LPGUID) &GUID_DEVINTERFACE_TOASTER, - NULL // ReferenceString - ); - - if (!NT_SUCCESS (status)) { - KdPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); - return status; - } - - // - // Register I/O callbacks to tell the framework that you are interested - // in handling IRP_MJ_READ, IRP_MJ_WRITE, and IRP_MJ_DEVICE_CONTROL requests. - // If a specific callback function is not specified for one ofthese, - // the request will be dispatched to the EvtIoDefault handler, if any. - // If there is no EvtIoDefault handler, the request will be failed with - // STATUS_INVALID_DEVICE_REQUEST. - // WdfIoQueueDispatchParallel means that we are capable of handling - // all the I/O requests simultaneously and we are responsible for protecting - // data that could be accessed by these callbacks simultaneously. - // A default queue gets all the requests that are not - // configured for forwarding using WdfDeviceConfigureRequestDispatching. - // - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); - - queueConfig.EvtIoRead = ToasterEvtIoRead; - queueConfig.EvtIoWrite = ToasterEvtIoWrite; - queueConfig.EvtIoDeviceControl = ToasterEvtIoDeviceControl; - - // - // By default, Static Driver Verifier (SDV) displays a warning if it - // doesn't find the EvtIoStop callback on a power-managed queue. - // The 'assume' below causes SDV to suppress this warning. If the driver - // has not explicitly set PowerManaged to WdfFalse, the framework creates - // power-managed queues when the device is not a filter driver. Normally - // the EvtIoStop is required for power-managed queues, but for this driver - // it is not needed b/c the driver doesn't hold on to the requests or - // forward them to other drivers. This driver completes the requests - // directly in the queue's handlers. If the EvtIoStop callback is not - // implemented, the framework waits for all driver-owned requests to be - // done before moving in the Dx/sleep states or before removing the - // device, which is the correct behavior for this type of driver. - // If the requests were taking an indeterminate amount of time to complete, - // or if the driver forwarded the requests to a lower driver/another stack, - // the queue should have an EvtIoStop/EvtIoResume. - // - __analysis_assume(queueConfig.EvtIoStop != 0); - status = WdfIoQueueCreate( - hDevice, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &queue - ); - __analysis_assume(queueConfig.EvtIoStop == 0); - - if (!NT_SUCCESS (status)) { - - KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); - return status; - } - - return status; -} - -VOID -ToasterEvtIoRead ( - WDFQUEUE Queue, - WDFREQUEST Request, - size_t Length - ) -/*++ - -Routine Description: - - Performs read from the toaster device. This event is called when the - framework receives IRP_MJ_READ requests. - -Arguments: - - Queue - Handle to the framework queue object that is associated with the - I/O request. - Request - Handle to a framework request object. - - Lenght - Length of the data buffer associated with the request. - By default, the queue does not dispatch - zero length read & write requests to the driver and instead to - complete such requests with status success. So we will never get - a zero length request. - -Return Value: - - None. - ---*/ -{ - NTSTATUS status; - ULONG_PTR bytesCopied =0; - WDFMEMORY memory; - - UNREFERENCED_PARAMETER(Queue); - UNREFERENCED_PARAMETER(Length); - - PAGED_CODE(); - - KdPrint(( "ToasterEvtIoRead: Request: 0x%p, Queue: 0x%p\n", - Request, Queue)); - - // - // Get the request memory and perform read operation here - // - status = WdfRequestRetrieveOutputMemory(Request, &memory); - if(NT_SUCCESS(status) ) { - // - // Copy data into the memory buffer using WdfMemoryCopyFromBuffer - // - } - - WdfRequestCompleteWithInformation(Request, status, bytesCopied); -} - -VOID -ToasterEvtIoWrite ( - WDFQUEUE Queue, - WDFREQUEST Request, - size_t Length - ) -/*++ - -Routine Description: - - Performs write to the toaster device. This event is called when the - framework receives IRP_MJ_WRITE requests. - -Arguments: - - Queue - Handle to the framework queue object that is associated with the - I/O request. - Request - Handle to a framework request object. - - Lenght - Length of the data buffer associated with the request. - The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get - a zero length request. - -Return Value: - - None ---*/ - -{ - NTSTATUS status; - ULONG_PTR bytesWritten =0; - WDFMEMORY memory; - - UNREFERENCED_PARAMETER(Queue); - UNREFERENCED_PARAMETER(Length); - - KdPrint(("ToasterEvtIoWrite. Request: 0x%p, Queue: 0x%p\n", - Request, Queue)); - - PAGED_CODE(); - - // - // Get the request buffer and perform write operation here - // - status = WdfRequestRetrieveInputMemory(Request, &memory); - if(NT_SUCCESS(status) ) { - // - // 1) Use WdfMemoryCopyToBuffer to copy data from the request - // to driver buffer. - // 2) Or get the buffer pointer from the request by calling - // WdfRequestRetrieveInputBuffer - // 3) Or you can get the buffer pointer from the memory handle - // by calling WdfMemoryGetBuffer. - // - bytesWritten = Length; - } - - WdfRequestCompleteWithInformation(Request, status, bytesWritten); - -} - - -VOID -ToasterEvtIoDeviceControl( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t OutputBufferLength, - IN size_t InputBufferLength, - IN ULONG IoControlCode - ) -/*++ -Routine Description: - - This event is called when the framework receives IRP_MJ_DEVICE_CONTROL - requests from the system. - -Arguments: - - Queue - Handle to the framework queue object that is associated - with the I/O request. - Request - Handle to a framework request object. - - OutputBufferLength - length of the request's output buffer, - if an output buffer is available. - InputBufferLength - length of the request's input buffer, - if an input buffer is available. - - IoControlCode - the driver-defined or system-defined I/O control code - (IOCTL) that is associated with the request. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS status= STATUS_SUCCESS; - - UNREFERENCED_PARAMETER(Queue); - UNREFERENCED_PARAMETER(OutputBufferLength); - UNREFERENCED_PARAMETER(InputBufferLength); - - KdPrint(("ToasterEvtIoDeviceControl called\n")); - - PAGED_CODE(); - - // - // Use WdfRequestRetrieveInputBuffer and WdfRequestRetrieveOutputBuffer - // to get the request buffers. - // - - switch (IoControlCode) { - - default: - status = STATUS_INVALID_DEVICE_REQUEST; - } - - // - // Complete the Request. - // - WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR) 0); -} - - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.h b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.h deleted file mode 100644 index fc847d2d1..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.h +++ /dev/null @@ -1,134 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation All Rights Reserved - -Module Name: - - Toaster.h - -Abstract: - - Header file for the toaster driver modules. - -Environment: - - Kernel mode - ---*/ - - -#if !defined(_TOASTER_H_) -#define _TOASTER_H_ - -#include -#include - -#define NTSTRSAFE_LIB -#include - -#include "wmilib.h" -#include -#include "driver.h" -#include "public.h" - -// For Featured driver only -#ifdef TOASTER_FUNC_FEATURED -#include -#endif // TOASTER_FUNC_FEATURED - -#define TOASTER_POOL_TAG (ULONG) 'saoT' - -#define MOFRESOURCENAME L"ToasterWMI" - -#define TOASTER_FUNC_DEVICE_LOG_ID "ToasterDevice" -// -// The device extension for the device object -// -typedef struct _FDO_DATA -{ - - WDFWMIINSTANCE WmiDeviceArrivalEvent; - - BOOLEAN WmiPowerDeviceEnableRegistered; - - TOASTER_INTERFACE_STANDARD BusInterface; - -// For Featured driver only -#ifdef TOASTER_FUNC_FEATURED - RECORDER_LOG WppRecorderLog; -#endif // TOASTER_FUNC_FEATURED - -} FDO_DATA, *PFDO_DATA; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DATA, ToasterFdoGetData) - - -// -// Connector Types -// - -#define TOASTER_WMI_STD_I8042 0 -#define TOASTER_WMI_STD_SERIAL 1 -#define TOASTER_WMI_STD_PARALEL 2 -#define TOASTER_WMI_STD_USB 3 - -DRIVER_INITIALIZE DriverEntry; -EVT_WDF_DRIVER_UNLOAD ToasterEvtDriverUnload; - -EVT_WDF_DRIVER_DEVICE_ADD ToasterEvtDeviceAdd; - -EVT_WDF_DEVICE_CONTEXT_CLEANUP ToasterEvtDeviceContextCleanup; -EVT_WDF_DEVICE_D0_ENTRY ToasterEvtDeviceD0Entry; -EVT_WDF_DEVICE_D0_EXIT ToasterEvtDeviceD0Exit; -EVT_WDF_DEVICE_PREPARE_HARDWARE ToasterEvtDevicePrepareHardware; -EVT_WDF_DEVICE_RELEASE_HARDWARE ToasterEvtDeviceReleaseHardware; - -EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT ToasterEvtDeviceSelfManagedIoInit; - -// -// Io events callbacks. -// -EVT_WDF_IO_QUEUE_IO_READ ToasterEvtIoRead; -EVT_WDF_IO_QUEUE_IO_WRITE ToasterEvtIoWrite; -EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL ToasterEvtIoDeviceControl; -EVT_WDF_DEVICE_FILE_CREATE ToasterEvtDeviceFileCreate; -EVT_WDF_FILE_CLOSE ToasterEvtFileClose; - -NTSTATUS -ToasterWmiRegistration( - _In_ WDFDEVICE Device - ); - -// -// Power events callbacks -// -EVT_WDF_DEVICE_ARM_WAKE_FROM_S0 ToasterEvtDeviceArmWakeFromS0; -EVT_WDF_DEVICE_ARM_WAKE_FROM_SX ToasterEvtDeviceArmWakeFromSx; -EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0 ToasterEvtDeviceDisarmWakeFromS0; -EVT_WDF_DEVICE_DISARM_WAKE_FROM_SX ToasterEvtDeviceDisarmWakeFromSx; -EVT_WDF_DEVICE_WAKE_FROM_S0_TRIGGERED ToasterEvtDeviceWakeFromS0Triggered; -EVT_WDF_DEVICE_WAKE_FROM_SX_TRIGGERED ToasterEvtDeviceWakeFromSxTriggered; - -PCHAR -DbgDevicePowerString( - IN WDF_POWER_DEVICE_STATE Type - ); - -// -// WMI event callbacks -// -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceStdDeviceDataQueryInstance; -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceToasterControlQueryInstance; -EVT_WDF_WMI_INSTANCE_SET_INSTANCE EvtWmiInstanceStdDeviceDataSetInstance; -EVT_WDF_WMI_INSTANCE_SET_INSTANCE EvtWmiInstanceToasterControlSetInstance; -EVT_WDF_WMI_INSTANCE_SET_ITEM EvtWmiInstanceToasterControlSetItem; -EVT_WDF_WMI_INSTANCE_SET_ITEM EvtWmiInstanceStdDeviceDataSetItem; -EVT_WDF_WMI_INSTANCE_EXECUTE_METHOD EvtWmiInstanceToasterControlExecuteMethod; - -NTSTATUS -ToasterFireArrivalEvent( - _In_ WDFDEVICE Device - ); - -#endif // _TOASTER_H_ - diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.inx b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.inx deleted file mode 100644 index 2217039df..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.inx +++ /dev/null @@ -1,25 +0,0 @@ -;Copyright (c) Microsoft Corporation. All rights reserved. - -[Version] -Signature = "$WINDOWS NT$" -Class = System -ClassGuid = {4D36E97D-E325-11CE-BFC1-08002BE10318} -Provider = Contoso -DriverVer = 06/16/1999, 5.00.2064 -CatalogFile = toaster.cat - -[Manufacturer] -Contoso = Contoso, NT$ARCH$ - -[Contoso.NT$ARCH$] -"Basic Toaster" = Toaster_Device, TOASTER\BASIC_TOASTER - -[Toaster_Device.NT] -CopyFiles = Toaster_Device.NT.Copy - -[Toaster_Device.NT.Copy] - -[SourceDisksNames] -1 = "Toaster Device Installation Disk #1",,,"" - -[SourceDisksFiles] \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.vcxproj b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.vcxproj deleted file mode 100644 index cfdfd574a..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.vcxproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - - - - {2D4FC000-01E2-4FDD-B01A-4FD3C59D245D} - {497e31cb-056b-4f31-abb8-447fd55ee5a5} - v4.5 - 12.0 - Debug - Win32 - toaster - $(LatestTargetPlatformVersion) - - - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - true - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - - - - - - - - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - DbgengKernelDebugger - true - $(SolutionDir)$(Platform)\$(ConfigurationName)\ - - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - true - true - trace.h - true - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/trace.h b/general/WinHEC 2017 Lab/Toaster Driver/toaster/trace.h deleted file mode 100644 index 820df2ea3..000000000 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/trace.h +++ /dev/null @@ -1,62 +0,0 @@ -/*++ - -Module Name: - - Trace.h - -Abstract: - - Header file for the debug tracing related function defintions and macros. - -Environment: - - Kernel mode - ---*/ - -// -// Define the tracing flags. -// -// Tracing GUID - f1f5e659-1217-48bd-9c69-6d9cb3a147d5 -// - -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID( \ - KMDFDriver1TraceGuid, (f1f5e659,1217,48bd,9c69,6d9cb3a147d5), \ - \ - WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ - WPP_DEFINE_BIT(TRACE_DRIVER) \ - WPP_DEFINE_BIT(TRACE_DEVICE) \ - WPP_DEFINE_BIT(TRACE_QUEUE) \ - ) - -#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) - -// -// WPP orders static parameters before dynamic parameters. To support the Trace function -// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to -// reorder the arguments to what the .tpl configuration file expects. -// -#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags) -#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags) - -// -// This comment block is scanned by the trace preprocessor to define our -// Trace function. -// -// begin_wpp config -// FUNC Trace{FLAGS=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); -// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); -// end_wpp -// diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App.sln b/general/WinHEC 2017 Lab/Toaster Support App/App.sln deleted file mode 100644 index 8d28827e7..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App.sln +++ /dev/null @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.12 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomCapability", "App\CustomCapability\cpp\CustomCapability.vcxproj", "{0213712B-62E6-5546-8D25-79B90244FFA9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|ARM.ActiveCfg = Debug|ARM - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|ARM.Build.0 = Debug|ARM - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|ARM.Deploy.0 = Debug|ARM - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|x64.ActiveCfg = Debug|x64 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|x64.Build.0 = Debug|x64 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|x64.Deploy.0 = Debug|x64 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|x86.ActiveCfg = Debug|Win32 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|x86.Build.0 = Debug|Win32 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Debug|x86.Deploy.0 = Debug|Win32 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|ARM.ActiveCfg = Release|ARM - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|ARM.Build.0 = Release|ARM - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|ARM.Deploy.0 = Release|ARM - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|x64.ActiveCfg = Release|x64 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|x64.Build.0 = Release|x64 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|x64.Deploy.0 = Release|x64 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|x86.ActiveCfg = Release|Win32 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|x86.Build.0 = Release|Win32 - {0213712B-62E6-5546-8D25-79B90244FFA9}.Release|x86.Deploy.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.SCCD b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.SCCD deleted file mode 100644 index cad58db24..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.SCCD +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - xxxx - diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.vcxproj b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.vcxproj deleted file mode 100644 index 8efaa78d5..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.vcxproj +++ /dev/null @@ -1,287 +0,0 @@ - - - - {0213712b-62e6-5546-8d25-79b90244ffa9} - SDKTemplate - en-US - 14.0 - true - Windows Store - 10.0.15063.0 - 10.0.15063.0 - 10.0 - CustomCapability - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - Application - true - v141 - - - Application - true - v141 - - - Application - true - v141 - - - Application - false - true - v141 - true - - - Application - false - true - v141 - true - - - Application - false - true - v141 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(IncludePath);..\..\..\SharedContent\cpp - - - $(SolutionDir)$(Platform)\$(Configuration)\$(MSBuildProjectName)\ - $(Platform)\$(Configuration)\ - - - - /bigobj %(AdditionalOptions) - 4453;28204 - $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(OutDir).. - false - - - vccorlib.lib;WindowsApp.lib;%(AdditionalDependencies);rpcrt4.lib - false - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(OutDir).. - false - - - vccorlib.lib;WindowsApp.lib;%(AdditionalDependencies);rpcrt4.lib - false - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(OutDir).. - false - - - vccorlib.lib;WindowsApp.lib;%(AdditionalDependencies);rpcrt4.lib - true - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(OutDir).. - false - - - vccorlib.lib;WindowsApp.lib;%(AdditionalDependencies);rpcrt4.lib - true - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(OutDir).. - false - - - vccorlib.lib;WindowsApp.lib;%(AdditionalDependencies);rpcrt4.lib - false - - - - - /bigobj %(AdditionalOptions) - 4453;28204 - $(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(OutDir).. - false - - - vccorlib.lib;WindowsApp.lib;%(AdditionalDependencies);rpcrt4.lib - true - - - - - - - ..\..\..\SharedContent\xaml\App.xaml - - - ..\..\..\SharedContent\cpp\MainPage.xaml - - - Scenario1_MeteringData.xaml - - - - - - - Designer - - - Styles\Styles.xaml - - - Designer - - - Designer - - - - - Designer - - - - - Assets\microsoft-sdk.png - - - Assets\smalltile-sdk.png - - - Assets\splash-sdk.png - - - Assets\squaretile-sdk.png - - - Assets\storelogo-sdk.png - - - Assets\tile-sdk.png - - - Assets\windows-sdk.png - - - - - false - NotUsing - - - ..\..\..\SharedContent\xaml\App.xaml - - - ..\..\..\SharedContent\cpp\MainPage.xaml - - - - Scenario1_MeteringData.xaml - - - - Create - Create - Create - Create - Create - Create - - - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.vcxproj.filters b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.vcxproj.filters deleted file mode 100644 index af84bc38b..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/CustomCapability.vcxproj.filters +++ /dev/null @@ -1,89 +0,0 @@ - - - - - 81d95eea-286c-4a5e-98f1-eef612020bf0 - - - 85b464d3-9e56-4242-b58b-1f226dd034b4 - bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png - - - {1c0f2943-52c2-4a54-93a2-971c14e7c8ec} - - - {33085be2-4c37-4eab-8f6e-6add0cffe2d4} - - - - - - - - - Model - - - Common - - - - - - ViewModel - - - - - - - Model - - - Common - - - - - - ViewModel - - - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/DeviceList.cpp b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/DeviceList.cpp deleted file mode 100644 index cb3a7a8ec..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/DeviceList.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "pch.h" -#include "DeviceList.h" -#include "MainPage.xaml.h" -#include "App.xaml.h" - -using namespace SDKTemplate; - -using namespace Platform; -using namespace Platform::Collections; -using namespace Windows::ApplicationModel; -using namespace Windows::Devices::Enumeration; -using namespace Windows::Devices::Custom; -using namespace Windows::Foundation; -using namespace Windows::UI::Core; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Documents; - -DeviceList^ DeviceList::_Current = nullptr; - -DeviceList^ DeviceList::Current::get() -{ - if (DeviceList::_Current == nullptr) - { - DeviceList::_Current = ref new DeviceList(); - } - return DeviceList::_Current; -} - -DeviceList::DeviceList() : m_WatcherStarted(false), m_WatcherSuspended(false) -{ - m_Fx2Watcher = nullptr; - m_List = ref new Vector(); - InitDeviceWatcher(); - - // Register for app suspend/resume handlers - App::Current->Suspending += ref new SuspendingEventHandler(this, &DeviceList::SuspendDeviceWatcher); - App::Current->Resuming += ref new EventHandler(this, &DeviceList::ResumeDeviceWatcher); -} - -void DeviceList::InitDeviceWatcher() -{ - // Define the selector to enumerate all of the fx2 device interface class instances. - // Use the DeviceInterfaceGuid provided by the driver (Fx2Driver, in this case). - auto selector = CustomDevice::GetDeviceSelector(Fx2Driver::DeviceInterfaceGuid); - - // Set of properties to retrieve - auto properties = ref new Vector({ "System.Devices.DeviceInstanceId" }); - - // Create a device watcher to look for instances of the fx2 device interface. - m_Fx2Watcher = DeviceInformation::CreateWatcher(selector, properties); - - m_Fx2Watcher->Added += ref new TypedEventHandler(this, &DeviceList::OnFx2Added); - m_Fx2Watcher->Removed += ref new TypedEventHandler(this, &DeviceList::OnFx2Removed); - m_Fx2Watcher->EnumerationCompleted += ref new TypedEventHandler(this, &DeviceList::OnFx2EnumerationComplete); -} - -void DeviceList::StartFx2Watcher() -{ - MainPage::Current->NotifyUser("starting device watcher", NotifyType::StatusMessage); - - std::for_each( - begin(m_List), - end(m_List), - [](DeviceListEntry^ Entry) { - Entry->Matched = false; - }); - - WatcherStarted = true; - m_Fx2Watcher->Start(); -} - -void DeviceList::StopFx2Watcher() -{ - MainPage::Current->NotifyUser("stopping fx2 watcher", NotifyType::StatusMessage); - m_Fx2Watcher->Stop(); - WatcherStarted = false; -} - -void DeviceList::CreateBooleanTable( - InlineCollection^ Table, - const Platform::Array^ NewValues, - const Platform::Array^ OldValues, - String^ /* IndexTitle */, - String^ /* ValueTitle */, - String^ TrueValue, - String^ FalseValue) -{ - Table->Clear(); - - for (int i = 0; i < (int)NewValues->Length; i += 1) - { - auto line = ref new Span(); - auto block = ref new Run(); - block->Text = (i + 1).ToString(); - line->Inlines->Append(block); - - block = ref new Run(); - block->Text = " "; - line->Inlines->Append(block); - - block = ref new Run(); - block->Text = NewValues[i] ? TrueValue : FalseValue; - - if ((OldValues != nullptr) && (OldValues[i] != NewValues[i])) - { - auto bold = ref new Bold(); - bold->Inlines->Append(block); - line->Inlines->Append(bold); - } - else - { - line->Inlines->Append(block); - } - - line->Inlines->Append(ref new LineBreak()); - - Table->Append(line); - } -} - -DeviceListEntry^ DeviceList::FindDevice(String^ Id) -{ - auto i = std::find_if( - begin(m_List), - end(m_List), - [Id](DeviceListEntry^ e) {return e->Id == Id; }); - - if (i == end(m_List)) - { - return nullptr; - } - else - { - return *i; - } -} - -void DeviceList::OnFx2Added(DeviceWatcher ^ /* Sender */, DeviceInformation^ DevInterface) -{ - MainPage::Current->Dispatcher->RunAsync( - CoreDispatcherPriority::Normal, - ref new DispatchedHandler( - [this, DevInterface]()->void - { - MainPage::Current->NotifyUser("OnFx2Added: " + DevInterface->Id, NotifyType::StatusMessage); - - // search the device list for a device with a matching interface ID - auto match = FindDevice(DevInterface->Id); - - // If we found a match then mark it as verified and return - if (match != nullptr) - { - match->Matched = true; - return; - } - - // Create a new elemetn for this device interface, and queue up the query of its - // device information - match = ref new DeviceListEntry(DevInterface); - - // Add the new element to the end of the list of devices - m_List->Append(match); - })); -} - -void DeviceList::OnFx2Removed(DeviceWatcher ^ /* Sender */, DeviceInformationUpdate^ DevInterface) -{ - auto deviceId = DevInterface->Id; - - MainPage::Current->Dispatcher->RunAsync( - CoreDispatcherPriority::Normal, - ref new DispatchedHandler( - [this, deviceId]() - { - MainPage::Current->NotifyUser("OnFx2Removed: " + deviceId, NotifyType::StatusMessage); - - // Search the list of devices for one with a matching ID. Move the matched - // item to the end of the list. - auto i = std::remove_if( - begin(m_List), - end(m_List), - [deviceId](DeviceListEntry^ e) {return e->Id == deviceId; }); - - // if there's no match return. - if (i == end(m_List)) - { - return; - } - - // Remove the last item from the list. - MainPage::Current->NotifyUser("OnFx2Removed: " + deviceId + " removed", NotifyType::StatusMessage); - m_List->RemoveAtEnd(); - })); -} - -void DeviceList::OnFx2EnumerationComplete(DeviceWatcher ^ /* Sender */, Object ^ /* o */) -{ - MainPage::Current->Dispatcher->RunAsync( - CoreDispatcherPriority::Normal, - ref new DispatchedHandler( - [this]() - { - MainPage::Current->NotifyUser("OnFx2EnumerationComplete", NotifyType::StatusMessage); - - DeviceList^ me = this; - - // Move all the unmatched elements to the end of the list - auto i = std::remove_if( - begin(m_List), - end(m_List), - [](DeviceListEntry^ e) { return e->Matched == false; }); - - // Determine the number of unmatched entries - auto unmatchedCount = end(m_List) - i; - - while (unmatchedCount > 0) - { - m_List->RemoveAtEnd(); - unmatchedCount -= 1; - } - })); -} - -void DeviceList::SuspendDeviceWatcher(Object^, SuspendingEventArgs^) -{ - if (WatcherStarted) - { - m_WatcherSuspended = true; - StopFx2Watcher(); - } - else - { - m_WatcherSuspended = false; - } -} - -void DeviceList::ResumeDeviceWatcher(Object^, Object^) -{ - if (m_WatcherSuspended) - { - m_WatcherSuspended = false; - StartFx2Watcher(); - } -} diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/Package.appxmanifest b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/Package.appxmanifest deleted file mode 100644 index 0ec45a072..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/Package.appxmanifest +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - Custom Capability C++ Sample - Microsoft Corporation - Assets\StoreLogo-sdk.png - - - - - - - - - - - - - - - - - - - - - diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcClient.cpp b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcClient.cpp deleted file mode 100644 index 870d63067..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcClient.cpp +++ /dev/null @@ -1,177 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -// There is an error in the system header files that incorrectly -// places RpcStringBindingCompose in the app partition. -// Work around it by changing the WINAPI_FAMILY to desktop temporarily. -#pragma push_macro("WINAPI_FAMILY") -#undef WINAPI_FAMILY -#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP -#include "RpcClient.h" -#pragma pop_macro("WINAPI_FAMILY") - -using namespace SDKTemplate; - -__int64 RpcClient::Initialize() -{ - RPC_STATUS status; - RPC_WSTR pszStringBinding = nullptr; - - status = RpcStringBindingCompose( - NULL, - reinterpret_cast(L"ncalrpc"), - NULL, - reinterpret_cast(RPC_STATIC_ENDPOINT), - NULL, - &pszStringBinding); - - if (status) - { - goto error_status; - } - - status = RpcBindingFromStringBinding( - pszStringBinding, - &hRpcBinding); - - if (status) - { - goto error_status; - } - - status = RpcStringFree(&pszStringBinding); - - if (status) - { - goto error_status; - } - - RpcTryExcept - { - ::RemoteOpen(hRpcBinding, &phContext); - } - RpcExcept(1) - { - status = RpcExceptionCode(); - } - RpcEndExcept - -error_status: - - return status; -} - -// -// Make RPC call to start metering. This is a blocking call and -// will return only after StopMetering is called. -// -__int64 RpcClient::StartMeteringAndWaitForStop(__int64 samplePeriod) -{ - __int64 ulCode = 0; - CallbackCount = 0; - MeteringData = 0; - - RpcTryExcept - { - ::StartMetering(phContext, samplePeriod, (__int64)this); - } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - } - RpcEndExcept - - return ulCode; -} - - -// -// Make rpc call SetSampleRate -// -__int64 RpcClient::SetSampleRate(int rate) -{ - __int64 ulCode = 0; - RpcTryExcept - { - ::SetSamplePeriod(phContext, rate); - } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - } - RpcEndExcept - return ulCode; -} - -// -// Make rpc call StopMetering -// -__int64 RpcClient::StopMetering() -{ - __int64 ulCode = 0; - RpcTryExcept - { - ::StopMetering(phContext); - } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - } - RpcEndExcept - return ulCode; -} - -RpcClient::~RpcClient() -{ - RPC_STATUS status; - - if (hRpcBinding != NULL) - { - RpcTryExcept - { - ::RemoteClose(&phContext); - } - RpcExcept(1) - { - // Ignoring the result of RemoteClose as nothing can be - // done on the client side with this return code - status = RpcExceptionCode(); - } - RpcEndExcept - - status = RpcBindingFree(&hRpcBinding); - hRpcBinding = NULL; - } -} - -// -// Metering rpc callback -// -void MeteringDataEvent(__int64 data, __int64 context) -{ - RpcClient* client = static_cast((PVOID)context); - client->MeteringData = data; - ++client->CallbackCount; -} - -///******************************************************/ -///* MIDL allocate and free */ -///******************************************************/ - -void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) -{ - return(malloc(len)); -} - -void __RPC_USER midl_user_free(void __RPC_FAR * ptr) -{ - free(ptr); -} \ No newline at end of file diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcClient.h b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcClient.h deleted file mode 100644 index 0ee5ff787..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcClient.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// RpcClient.h -// - -#pragma once - -#define RPC_STATIC_ENDPOINT L"HsaSampleRpcEndpoint" - -#include "RpcInterface_h.h" - -namespace SDKTemplate -{ - /// - /// Client side RPC implementation - /// - private class RpcClient sealed - { - public: - ~RpcClient(); - __int64 Initialize(); - __int64 StartMeteringAndWaitForStop(__int64 samplePeriod); - __int64 StopMetering(); - __int64 SetSampleRate(int rate); - int CallbackCount; - __int64 MeteringData; - private: - handle_t hRpcBinding; - PCONTEXT_HANDLE_TYPE phContext; - }; -} diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface.c b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface.c deleted file mode 100644 index 0f9885333..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface.c +++ /dev/null @@ -1,6 +0,0 @@ -// RpcInterface_c.c expects _ARM_ to be set when building for ARM. -#ifdef _M_ARM -#define _ARM_ 1 -#endif - -#include "RpcInterface_c.c" diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_c.c b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_c.c deleted file mode 100644 index 8b05c1eaf..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_c.c +++ /dev/null @@ -1,476 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the RPC client stubs */ - - - /* File created by MIDL compiler version 8.01.0622 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for C:\WinHEC 2017 Lab\Toaster Driver\Service\RpcInterface.Idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#if defined(_M_AMD64) - - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ -#if _MSC_VER >= 1200 -#pragma warning(push) -#endif - -#pragma warning( disable: 4211 ) /* redefine extern to static */ -#pragma warning( disable: 4232 ) /* dllimport identity*/ -#pragma warning( disable: 4024 ) /* array to pointer mapping*/ - -#include - -#include "RpcInterface_h.h" - -#define TYPE_FORMAT_STRING_SIZE 23 -#define PROC_FORMAT_STRING_SIZE 245 -#define EXPR_FORMAT_STRING_SIZE 1 -#define TRANSMIT_AS_TABLE_SIZE 0 -#define WIRE_MARSHAL_TABLE_SIZE 0 - -typedef struct _RpcInterface_MIDL_TYPE_FORMAT_STRING - { - short Pad; - unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_TYPE_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_PROC_FORMAT_STRING - { - short Pad; - unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_PROC_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_EXPR_FORMAT_STRING - { - long Pad; - unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_EXPR_FORMAT_STRING; - - -static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = -{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; - - -extern const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString; -extern const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString; -extern const RpcInterface_MIDL_EXPR_FORMAT_STRING RpcInterface__MIDL_ExprFormatString; - -#define GENERIC_BINDING_TABLE_SIZE 0 - - -/* Standard interface: RpcInterface, ver. 1.0, - GUID={0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}} */ - - -extern const MIDL_SERVER_INFO RpcInterface_ServerInfo; - - -extern const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable; - -static const RPC_CLIENT_INTERFACE RpcInterface___RpcClientInterface = - { - sizeof(RPC_CLIENT_INTERFACE), - {{0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}},{1,0}}, - {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, - (RPC_DISPATCH_TABLE*)&RpcInterface_v1_0_DispatchTable, - 0, - 0, - 0, - &RpcInterface_ServerInfo, - 0x04000000 - }; -RPC_IF_HANDLE RpcInterface_v1_0_c_ifspec = (RPC_IF_HANDLE)& RpcInterface___RpcClientInterface; - -extern const MIDL_STUB_DESC RpcInterface_StubDesc; - -static RPC_BINDING_HANDLE RpcInterface__MIDL_AutoBindHandle; - - -void RemoteOpen( - /* [in] */ handle_t hBinding, - /* [out] */ PPCONTEXT_HANDLE_TYPE pphContext) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[0], - hBinding, - pphContext); - -} - - -void RemoteClose( - /* [out][in] */ PPCONTEXT_HANDLE_TYPE pphContext) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[36], - pphContext); - -} - - -void StartMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod, - /* [optional][in] */ __int64 context) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[74], - phContext, - samplePeriod, - context); - -} - - -void SetSamplePeriod( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[124], - phContext, - samplePeriod); - -} - - -void StopMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[168], - phContext); - -} - - -#if !defined(__RPC_WIN64__) -#error Invalid build platform for this stub. -#endif - -static const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString = - { - 0, - { - - /* Procedure RemoteOpen */ - - 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 2 */ NdrFcLong( 0x0 ), /* 0 */ -/* 6 */ NdrFcShort( 0x0 ), /* 0 */ -/* 8 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ - 0x0, /* 0 */ -/* 12 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 14 */ NdrFcShort( 0x0 ), /* 0 */ -/* 16 */ NdrFcShort( 0x38 ), /* 56 */ -/* 18 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 20 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 22 */ NdrFcShort( 0x0 ), /* 0 */ -/* 24 */ NdrFcShort( 0x0 ), /* 0 */ -/* 26 */ NdrFcShort( 0x0 ), /* 0 */ -/* 28 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 30 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ -/* 32 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 34 */ NdrFcShort( 0x6 ), /* Type Offset=6 */ - - /* Procedure RemoteClose */ - -/* 36 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 38 */ NdrFcLong( 0x0 ), /* 0 */ -/* 42 */ NdrFcShort( 0x1 ), /* 1 */ -/* 44 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 46 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe0, /* Ctxt flags: via ptr, in, out, */ -/* 48 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 50 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 52 */ NdrFcShort( 0x38 ), /* 56 */ -/* 54 */ NdrFcShort( 0x38 ), /* 56 */ -/* 56 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 58 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 60 */ NdrFcShort( 0x0 ), /* 0 */ -/* 62 */ NdrFcShort( 0x0 ), /* 0 */ -/* 64 */ NdrFcShort( 0x0 ), /* 0 */ -/* 66 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 68 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ -/* 70 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 72 */ NdrFcShort( 0xe ), /* Type Offset=14 */ - - /* Procedure StartMetering */ - -/* 74 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 76 */ NdrFcLong( 0x0 ), /* 0 */ -/* 80 */ NdrFcShort( 0x2 ), /* 2 */ -/* 82 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 84 */ 0x30, /* FC_BIND_CONTEXT */ - 0x40, /* Ctxt flags: in, */ -/* 86 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 88 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 90 */ NdrFcShort( 0x44 ), /* 68 */ -/* 92 */ NdrFcShort( 0x0 ), /* 0 */ -/* 94 */ 0x40, /* Oi2 Flags: has ext, */ - 0x3, /* 3 */ -/* 96 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 98 */ NdrFcShort( 0x0 ), /* 0 */ -/* 100 */ NdrFcShort( 0x0 ), /* 0 */ -/* 102 */ NdrFcShort( 0x0 ), /* 0 */ -/* 104 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 106 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 108 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 110 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 112 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 114 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 116 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 118 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 120 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 122 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure SetSamplePeriod */ - -/* 124 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 126 */ NdrFcLong( 0x0 ), /* 0 */ -/* 130 */ NdrFcShort( 0x3 ), /* 3 */ -/* 132 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 134 */ 0x30, /* FC_BIND_CONTEXT */ - 0x40, /* Ctxt flags: in, */ -/* 136 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 138 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 140 */ NdrFcShort( 0x34 ), /* 52 */ -/* 142 */ NdrFcShort( 0x0 ), /* 0 */ -/* 144 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 146 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 148 */ NdrFcShort( 0x0 ), /* 0 */ -/* 150 */ NdrFcShort( 0x0 ), /* 0 */ -/* 152 */ NdrFcShort( 0x0 ), /* 0 */ -/* 154 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 156 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 158 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 160 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 162 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 164 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 166 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure StopMetering */ - -/* 168 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 170 */ NdrFcLong( 0x0 ), /* 0 */ -/* 174 */ NdrFcShort( 0x4 ), /* 4 */ -/* 176 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 178 */ 0x30, /* FC_BIND_CONTEXT */ - 0x40, /* Ctxt flags: in, */ -/* 180 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 182 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 184 */ NdrFcShort( 0x24 ), /* 36 */ -/* 186 */ NdrFcShort( 0x0 ), /* 0 */ -/* 188 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 190 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 192 */ NdrFcShort( 0x0 ), /* 0 */ -/* 194 */ NdrFcShort( 0x0 ), /* 0 */ -/* 196 */ NdrFcShort( 0x0 ), /* 0 */ -/* 198 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 200 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 202 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 204 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Procedure MeteringDataEvent */ - -/* 206 */ 0x34, /* FC_CALLBACK_HANDLE */ - 0x48, /* Old Flags: */ -/* 208 */ NdrFcLong( 0x0 ), /* 0 */ -/* 212 */ NdrFcShort( 0x0 ), /* 0 */ -/* 214 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 216 */ NdrFcShort( 0x20 ), /* 32 */ -/* 218 */ NdrFcShort( 0x0 ), /* 0 */ -/* 220 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 222 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 224 */ NdrFcShort( 0x0 ), /* 0 */ -/* 226 */ NdrFcShort( 0x0 ), /* 0 */ -/* 228 */ NdrFcShort( 0x0 ), /* 0 */ -/* 230 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter data */ - -/* 232 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 234 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 236 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 238 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 240 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 242 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString = - { - 0, - { - NdrFcShort( 0x0 ), /* 0 */ -/* 2 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ -/* 6 */ 0x30, /* FC_BIND_CONTEXT */ - 0xa0, /* Ctxt flags: via ptr, out, */ -/* 8 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 10 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 12 */ NdrFcShort( 0x2 ), /* Offset= 2 (14) */ -/* 14 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe1, /* Ctxt flags: via ptr, in, out, can't be null */ -/* 16 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 18 */ 0x30, /* FC_BIND_CONTEXT */ - 0x41, /* Ctxt flags: in, can't be null */ -/* 20 */ 0x0, /* 0 */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const unsigned short RpcInterface_FormatStringOffsetTable[] = - { - 0, - 36, - 74, - 124, - 168, - }; - - -static const unsigned short _callbackRpcInterface_FormatStringOffsetTable[] = - { - 206 - }; - - -static const MIDL_STUB_DESC RpcInterface_StubDesc = - { - (void *)& RpcInterface___RpcClientInterface, - MIDL_user_allocate, - MIDL_user_free, - &RpcInterface__MIDL_AutoBindHandle, - 0, - 0, - 0, - 0, - RpcInterface__MIDL_TypeFormatString.Format, - 1, /* -error bounds_check flag */ - 0x50002, /* Ndr library version */ - 0, - 0x801026e, /* MIDL Version 8.1.622 */ - 0, - 0, - 0, /* notify & notify_flag routine table */ - 0x1, /* MIDL flag */ - 0, /* cs routines */ - 0, /* proxy/server info */ - 0 - }; - -static const RPC_DISPATCH_FUNCTION RpcInterface_table[] = - { - NdrServerCall2, - 0 - }; -static const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable = - { - 1, - (RPC_DISPATCH_FUNCTION*)RpcInterface_table - }; - -static const SERVER_ROUTINE RpcInterface_ServerRoutineTable[] = - { - (SERVER_ROUTINE)MeteringDataEvent - }; - -static const MIDL_SERVER_INFO RpcInterface_ServerInfo = - { - &RpcInterface_StubDesc, - RpcInterface_ServerRoutineTable, - RpcInterface__MIDL_ProcFormatString.Format, - _callbackRpcInterface_FormatStringOffsetTable, - 0, - 0, - 0, - 0}; -#if _MSC_VER >= 1200 -#pragma warning(pop) -#endif - - -#endif /* defined(_M_AMD64)*/ - diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_h.h b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_h.h deleted file mode 100644 index a0e2dcacf..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_h.h +++ /dev/null @@ -1,112 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 8.01.0622 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for C:\WinHEC 2017 Lab\Toaster Driver\Service\RpcInterface.Idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif /* __RPCNDR_H_VERSION__ */ - - -#ifndef __RpcInterface_h_h__ -#define __RpcInterface_h_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -#if defined(__cplusplus) -#if defined(__MIDL_USE_C_ENUM) -#define MIDL_ENUM enum -#else -#define MIDL_ENUM enum class -#endif -#endif - - -/* Forward Declarations */ - -/* header files for imported files */ -#include "oaidl.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -#ifndef __RpcInterface_INTERFACE_DEFINED__ -#define __RpcInterface_INTERFACE_DEFINED__ - -/* interface RpcInterface */ -/* [unique][version][uuid] */ - -typedef /* [context_handle] */ void *PCONTEXT_HANDLE_TYPE; - -typedef /* [ref] */ PCONTEXT_HANDLE_TYPE *PPCONTEXT_HANDLE_TYPE; - -void RemoteOpen( - /* [in] */ handle_t hBinding, - /* [out] */ PPCONTEXT_HANDLE_TYPE pphContext); - -void RemoteClose( - /* [out][in] */ PPCONTEXT_HANDLE_TYPE pphContext); - -void StartMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod, - /* [optional][in] */ __int64 context); - -void SetSamplePeriod( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext, - /* [in] */ __int64 samplePeriod); - -void StopMetering( - /* [in] */ PCONTEXT_HANDLE_TYPE phContext); - -/* [callback] */ void MeteringDataEvent( - /* [in] */ __int64 data, - /* [optional][in] */ __int64 context); - - - -extern RPC_IF_HANDLE RpcInterface_v1_0_c_ifspec; -extern RPC_IF_HANDLE RpcInterface_v1_0_s_ifspec; -#endif /* __RpcInterface_INTERFACE_DEFINED__ */ - -/* Additional Prototypes for ALL interfaces */ - -void __RPC_USER PCONTEXT_HANDLE_TYPE_rundown( PCONTEXT_HANDLE_TYPE ); - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_s.c b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_s.c deleted file mode 100644 index ec58170d4..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/RpcInterface_s.c +++ /dev/null @@ -1,430 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the RPC server stubs */ - - - /* File created by MIDL compiler version 8.01.0622 */ -/* at Mon Jan 18 19:14:07 2038 - */ -/* Compiler settings for C:\WinHEC 2017 Lab\Toaster Driver\Service\RpcInterface.Idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -/* @@MIDL_FILE_HEADING( ) */ - -#if defined(_M_AMD64) - - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ -#if _MSC_VER >= 1200 -#pragma warning(push) -#endif - -#pragma warning( disable: 4211 ) /* redefine extern to static */ -#pragma warning( disable: 4232 ) /* dllimport identity*/ -#pragma warning( disable: 4024 ) /* array to pointer mapping*/ - -#include -#include "RpcInterface_h.h" - -#define TYPE_FORMAT_STRING_SIZE 23 -#define PROC_FORMAT_STRING_SIZE 245 -#define EXPR_FORMAT_STRING_SIZE 1 -#define TRANSMIT_AS_TABLE_SIZE 0 -#define WIRE_MARSHAL_TABLE_SIZE 0 - -typedef struct _RpcInterface_MIDL_TYPE_FORMAT_STRING - { - short Pad; - unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_TYPE_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_PROC_FORMAT_STRING - { - short Pad; - unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_PROC_FORMAT_STRING; - -typedef struct _RpcInterface_MIDL_EXPR_FORMAT_STRING - { - long Pad; - unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; - } RpcInterface_MIDL_EXPR_FORMAT_STRING; - - -static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = -{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; - -extern const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString; -extern const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString; -extern const RpcInterface_MIDL_EXPR_FORMAT_STRING RpcInterface__MIDL_ExprFormatString; - -/* Standard interface: RpcInterface, ver. 1.0, - GUID={0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}} */ - - -extern const MIDL_SERVER_INFO RpcInterface_ServerInfo; - -extern const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable; - -static const RPC_SERVER_INTERFACE RpcInterface___RpcServerInterface = - { - sizeof(RPC_SERVER_INTERFACE), - {{0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}},{1,0}}, - {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, - (RPC_DISPATCH_TABLE*)&RpcInterface_v1_0_DispatchTable, - 0, - 0, - 0, - &RpcInterface_ServerInfo, - 0x04000000 - }; -RPC_IF_HANDLE RpcInterface_v1_0_s_ifspec = (RPC_IF_HANDLE)& RpcInterface___RpcServerInterface; - -extern const MIDL_STUB_DESC RpcInterface_StubDesc; - - extern const MIDL_STUBLESS_PROXY_INFO RpcInterface_ProxyInfo; - -/* [callback] */ void MeteringDataEvent( - /* [in] */ __int64 data, - /* [optional][in] */ __int64 context) -{ - - NdrClientCall2( - ( PMIDL_STUB_DESC )&RpcInterface_StubDesc, - (PFORMAT_STRING) &RpcInterface__MIDL_ProcFormatString.Format[206], - data, - context); - -} - -extern const NDR_RUNDOWN RundownRoutines[]; - -#if !defined(__RPC_WIN64__) -#error Invalid build platform for this stub. -#endif - -static const RpcInterface_MIDL_PROC_FORMAT_STRING RpcInterface__MIDL_ProcFormatString = - { - 0, - { - - /* Procedure RemoteOpen */ - - 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 2 */ NdrFcLong( 0x0 ), /* 0 */ -/* 6 */ NdrFcShort( 0x0 ), /* 0 */ -/* 8 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ - 0x0, /* 0 */ -/* 12 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 14 */ NdrFcShort( 0x0 ), /* 0 */ -/* 16 */ NdrFcShort( 0x38 ), /* 56 */ -/* 18 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 20 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 22 */ NdrFcShort( 0x0 ), /* 0 */ -/* 24 */ NdrFcShort( 0x0 ), /* 0 */ -/* 26 */ NdrFcShort( 0x0 ), /* 0 */ -/* 28 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 30 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ -/* 32 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 34 */ NdrFcShort( 0x6 ), /* Type Offset=6 */ - - /* Procedure RemoteClose */ - -/* 36 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 38 */ NdrFcLong( 0x0 ), /* 0 */ -/* 42 */ NdrFcShort( 0x1 ), /* 1 */ -/* 44 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 46 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe0, /* Ctxt flags: via ptr, in, out, */ -/* 48 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 50 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 52 */ NdrFcShort( 0x38 ), /* 56 */ -/* 54 */ NdrFcShort( 0x38 ), /* 56 */ -/* 56 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 58 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 60 */ NdrFcShort( 0x0 ), /* 0 */ -/* 62 */ NdrFcShort( 0x0 ), /* 0 */ -/* 64 */ NdrFcShort( 0x0 ), /* 0 */ -/* 66 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter pphContext */ - -/* 68 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ -/* 70 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 72 */ NdrFcShort( 0xe ), /* Type Offset=14 */ - - /* Procedure StartMetering */ - -/* 74 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 76 */ NdrFcLong( 0x0 ), /* 0 */ -/* 80 */ NdrFcShort( 0x2 ), /* 2 */ -/* 82 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 84 */ 0x30, /* FC_BIND_CONTEXT */ - 0x40, /* Ctxt flags: in, */ -/* 86 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 88 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 90 */ NdrFcShort( 0x44 ), /* 68 */ -/* 92 */ NdrFcShort( 0x0 ), /* 0 */ -/* 94 */ 0x40, /* Oi2 Flags: has ext, */ - 0x3, /* 3 */ -/* 96 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 98 */ NdrFcShort( 0x0 ), /* 0 */ -/* 100 */ NdrFcShort( 0x0 ), /* 0 */ -/* 102 */ NdrFcShort( 0x0 ), /* 0 */ -/* 104 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 106 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 108 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 110 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 112 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 114 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 116 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 118 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 120 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 122 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure SetSamplePeriod */ - -/* 124 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 126 */ NdrFcLong( 0x0 ), /* 0 */ -/* 130 */ NdrFcShort( 0x3 ), /* 3 */ -/* 132 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 134 */ 0x30, /* FC_BIND_CONTEXT */ - 0x40, /* Ctxt flags: in, */ -/* 136 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 138 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 140 */ NdrFcShort( 0x34 ), /* 52 */ -/* 142 */ NdrFcShort( 0x0 ), /* 0 */ -/* 144 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 146 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 148 */ NdrFcShort( 0x0 ), /* 0 */ -/* 150 */ NdrFcShort( 0x0 ), /* 0 */ -/* 152 */ NdrFcShort( 0x0 ), /* 0 */ -/* 154 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 156 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 158 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 160 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Parameter samplePeriod */ - -/* 162 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 164 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 166 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Procedure StopMetering */ - -/* 168 */ 0x0, /* 0 */ - 0x48, /* Old Flags: */ -/* 170 */ NdrFcLong( 0x0 ), /* 0 */ -/* 174 */ NdrFcShort( 0x4 ), /* 4 */ -/* 176 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 178 */ 0x30, /* FC_BIND_CONTEXT */ - 0x40, /* Ctxt flags: in, */ -/* 180 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 182 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 184 */ NdrFcShort( 0x24 ), /* 36 */ -/* 186 */ NdrFcShort( 0x0 ), /* 0 */ -/* 188 */ 0x40, /* Oi2 Flags: has ext, */ - 0x1, /* 1 */ -/* 190 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 192 */ NdrFcShort( 0x0 ), /* 0 */ -/* 194 */ NdrFcShort( 0x0 ), /* 0 */ -/* 196 */ NdrFcShort( 0x0 ), /* 0 */ -/* 198 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter phContext */ - -/* 200 */ NdrFcShort( 0x8 ), /* Flags: in, */ -/* 202 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 204 */ NdrFcShort( 0x12 ), /* Type Offset=18 */ - - /* Procedure MeteringDataEvent */ - -/* 206 */ 0x34, /* FC_CALLBACK_HANDLE */ - 0x48, /* Old Flags: */ -/* 208 */ NdrFcLong( 0x0 ), /* 0 */ -/* 212 */ NdrFcShort( 0x0 ), /* 0 */ -/* 214 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 216 */ NdrFcShort( 0x20 ), /* 32 */ -/* 218 */ NdrFcShort( 0x0 ), /* 0 */ -/* 220 */ 0x40, /* Oi2 Flags: has ext, */ - 0x2, /* 2 */ -/* 222 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 224 */ NdrFcShort( 0x0 ), /* 0 */ -/* 226 */ NdrFcShort( 0x0 ), /* 0 */ -/* 228 */ NdrFcShort( 0x0 ), /* 0 */ -/* 230 */ NdrFcShort( 0x0 ), /* 0 */ - - /* Parameter data */ - -/* 232 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 234 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */ -/* 236 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - /* Parameter context */ - -/* 238 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 240 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 242 */ 0xb, /* FC_HYPER */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const RpcInterface_MIDL_TYPE_FORMAT_STRING RpcInterface__MIDL_TypeFormatString = - { - 0, - { - NdrFcShort( 0x0 ), /* 0 */ -/* 2 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ -/* 6 */ 0x30, /* FC_BIND_CONTEXT */ - 0xa0, /* Ctxt flags: via ptr, out, */ -/* 8 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 10 */ - 0x11, 0x4, /* FC_RP [alloced_on_stack] */ -/* 12 */ NdrFcShort( 0x2 ), /* Offset= 2 (14) */ -/* 14 */ 0x30, /* FC_BIND_CONTEXT */ - 0xe1, /* Ctxt flags: via ptr, in, out, can't be null */ -/* 16 */ 0x0, /* 0 */ - 0x0, /* 0 */ -/* 18 */ 0x30, /* FC_BIND_CONTEXT */ - 0x41, /* Ctxt flags: in, can't be null */ -/* 20 */ 0x0, /* 0 */ - 0x0, /* 0 */ - - 0x0 - } - }; - -static const NDR_RUNDOWN RundownRoutines[] = - { - PCONTEXT_HANDLE_TYPE_rundown - }; - - -static const unsigned short RpcInterface_FormatStringOffsetTable[] = - { - 0, - 36, - 74, - 124, - 168, - }; - - -static const unsigned short _callbackRpcInterface_FormatStringOffsetTable[] = - { - 206 - }; - - -static const MIDL_STUB_DESC RpcInterface_StubDesc = - { - (void *)& RpcInterface___RpcServerInterface, - MIDL_user_allocate, - MIDL_user_free, - 0, - RundownRoutines, - 0, - 0, - 0, - RpcInterface__MIDL_TypeFormatString.Format, - 1, /* -error bounds_check flag */ - 0x50002, /* Ndr library version */ - 0, - 0x801026e, /* MIDL Version 8.1.622 */ - 0, - 0, - 0, /* notify & notify_flag routine table */ - 0x1, /* MIDL flag */ - 0, /* cs routines */ - 0, /* proxy/server info */ - 0 - }; - -static const RPC_DISPATCH_FUNCTION RpcInterface_table[] = - { - NdrServerCall2, - NdrServerCall2, - NdrServerCall2, - NdrServerCall2, - NdrServerCall2, - 0 - }; -static const RPC_DISPATCH_TABLE RpcInterface_v1_0_DispatchTable = - { - 5, - (RPC_DISPATCH_FUNCTION*)RpcInterface_table - }; - -static const SERVER_ROUTINE RpcInterface_ServerRoutineTable[] = - { - (SERVER_ROUTINE)RemoteOpen, - (SERVER_ROUTINE)RemoteClose, - (SERVER_ROUTINE)StartMetering, - (SERVER_ROUTINE)SetSamplePeriod, - (SERVER_ROUTINE)StopMetering, - }; - -static const MIDL_SERVER_INFO RpcInterface_ServerInfo = - { - &RpcInterface_StubDesc, - RpcInterface_ServerRoutineTable, - RpcInterface__MIDL_ProcFormatString.Format, - RpcInterface_FormatStringOffsetTable, - 0, - 0, - 0, - 0}; -#if _MSC_VER >= 1200 -#pragma warning(pop) -#endif - - -#endif /* defined(_M_AMD64)*/ - diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/SampleConfiguration.cpp b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/SampleConfiguration.cpp deleted file mode 100644 index a808cf838..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/SampleConfiguration.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#include "pch.h" -#include "MainPage.xaml.h" -#include "SampleConfiguration.h" - -using namespace SDKTemplate; - -Platform::Array^ MainPage::scenariosInner = ref new Platform::Array -{ - { "Connect to an NT Service", "SDKTemplate.MeteringData" }, -}; diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/SampleConfiguration.h b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/SampleConfiguration.h deleted file mode 100644 index 225812757..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/SampleConfiguration.h +++ /dev/null @@ -1,47 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#pragma once -#include "pch.h" - -namespace SDKTemplate -{ - value struct Scenario; - - partial ref class MainPage - { - internal: - static property Platform::String^ FEATURE_NAME - { - Platform::String^ get() - { - return "Custom Capability C++ sample"; - } - } - - static property Platform::Array^ scenarios - { - Platform::Array^ get() - { - return scenariosInner; - } - } - - private: - static Platform::Array^ scenariosInner; - }; - - public value struct Scenario - { - Platform::String^ Title; - Platform::String^ ClassName; - }; -} diff --git a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/Scenario1_MeteringData.xaml b/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/Scenario1_MeteringData.xaml deleted file mode 100644 index 0636f74d0..000000000 --- a/general/WinHEC 2017 Lab/Toaster Support App/App/CustomCapability/cpp/Scenario1_MeteringData.xaml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - This scenario demonstrates RPC communication between an app and an NT service. For demonstration purposes, the service reads data from an imaginary device. - - - - - - - Sample Period (ms): - - - - - - - - -