mirror of
https://github.com/VirtualDrivers/Virtual-Display-Driver.git
synced 2026-10-20 05:40:03 -05:00
Compare commits
258
Commits
Development
...
fanfan1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47a8aad7b5 | ||
|
|
55b2283414 | ||
|
|
4cd91b0b39 | ||
|
|
5c3cc29305 | ||
|
|
b8c1b245d5 | ||
|
|
2f17851fba | ||
|
|
1cf59c2a66 | ||
|
|
e2713cac78 | ||
|
|
5c2839d5f7 | ||
|
|
dfdba9a08f | ||
|
|
0b9da8357d | ||
|
|
63f9285461 | ||
|
|
b642ef64d8 | ||
|
|
7267835157 | ||
|
|
05ae18d104 | ||
|
|
fd8700f636 | ||
|
|
88916eca0a | ||
|
|
06b2dbd7d4 | ||
|
|
830de3f2aa | ||
|
|
7233822630 | ||
|
|
bccc901b1b | ||
|
|
2a18a0b594 | ||
|
|
7becdd43c0 | ||
|
|
3917232ae1 | ||
|
|
b5383e859d | ||
|
|
93c6fff4f5 | ||
|
|
74477f745d | ||
|
|
d0f8a028c6 | ||
|
|
c585ee93cf | ||
|
|
b9acacd40c | ||
|
|
0cccd7a14d | ||
|
|
89b7b4477d | ||
|
|
a01ecfd460 | ||
|
|
587f99c8c3 | ||
|
|
dd198e508e | ||
|
|
4b6ba2246e | ||
|
|
c928fa9251 | ||
|
|
d5a4466425 | ||
|
|
a602844e89 | ||
|
|
92203a544c | ||
|
|
61ae3fbd07 | ||
|
|
3750c5ed4f | ||
|
|
506791639d | ||
|
|
14d1e344d7 | ||
|
|
d437ebc9b4 | ||
|
|
5aa453b3c0 | ||
|
|
0a095d4b76 | ||
|
|
8e874f0bed | ||
|
|
33ea391a91 | ||
|
|
5b9822bc0b | ||
|
|
8c9b0f8c9a | ||
|
|
0969263ba1 | ||
|
|
d4964dbcfd | ||
|
|
25eb449ee6 | ||
|
|
05f279346f | ||
|
|
9e8f62ab3c | ||
|
|
ac0c52e8a5 | ||
|
|
0f2c9106be | ||
|
|
724bec4115 | ||
|
|
8e76e9dc14 | ||
|
|
b8a6fe0fb8 | ||
|
|
3650e70d02 | ||
|
|
24c740857a | ||
|
|
e851bf9a3b | ||
|
|
b49fc4017e | ||
|
|
1dde89134f | ||
|
|
c53bd3f66b | ||
|
|
8ea77f7f06 | ||
|
|
646c2d833f | ||
|
|
e19d8a82b9 | ||
|
|
d4f2eba005 | ||
|
|
54d3113196 | ||
|
|
03b08e474f | ||
|
|
9eeb8fec55 | ||
|
|
56a78f9214 | ||
|
|
dd1fa14bc9 | ||
|
|
36461d5022 | ||
|
|
d7a0d3ec33 | ||
|
|
0b8f896008 | ||
|
|
aaa12df16d | ||
|
|
cae46b429d | ||
|
|
1995e6de2b | ||
|
|
c6b1e893ec | ||
|
|
3a1871fd23 | ||
|
|
3f6e54631b | ||
|
|
96c662be6c | ||
|
|
3a20ccb5e2 | ||
|
|
5d2892ab0b | ||
|
|
e87194f972 | ||
|
|
0505e34539 | ||
|
|
9fb159bb53 | ||
|
|
f0bdbfd4a0 | ||
|
|
94b35105e4 | ||
|
|
322e36a613 | ||
|
|
80b461b02f | ||
|
|
00e43b5d1f | ||
|
|
e3f58b629a | ||
|
|
e4bc40252a | ||
|
|
976dd165f6 | ||
|
|
5281cef87f | ||
|
|
3a500d8773 | ||
|
|
888f3ae2d2 | ||
|
|
3565152e07 | ||
|
|
cd1445427b | ||
|
|
64602d2aaa | ||
|
|
ef87af27dc | ||
|
|
888387fc72 | ||
|
|
15d229200b | ||
|
|
0318e5399a | ||
|
|
74ca716296 | ||
|
|
44e199935b | ||
|
|
69359ec35c | ||
|
|
c87b0c4f89 | ||
|
|
dcb511f188 | ||
|
|
52bbd2d97c | ||
|
|
8644ed559d | ||
|
|
9ac6074136 | ||
|
|
b07c8cc80c | ||
|
|
cb98721da4 | ||
|
|
3e65bc8749 | ||
|
|
8de4f3b000 | ||
|
|
79810cb48d | ||
|
|
a3564fbf01 | ||
|
|
6c125361ac | ||
|
|
266b4a01c3 | ||
|
|
0d36d2a655 | ||
|
|
5dc87774c5 | ||
|
|
68b92409a6 | ||
|
|
80861064e8 | ||
|
|
2fd04a231b | ||
|
|
1ef82c3e6a | ||
|
|
3895ea6b4b | ||
|
|
13bb8cc323 | ||
|
|
f9f95e319c | ||
|
|
22535e68de | ||
|
|
fc73feaa47 | ||
|
|
698c735bdf | ||
|
|
9cb856f645 | ||
|
|
cdc9ed24d3 | ||
|
|
9f90a294ee | ||
|
|
2f3f3c044c | ||
|
|
63c3899826 | ||
|
|
a28ec0eb51 | ||
|
|
d03bf38ff6 | ||
|
|
4bc7e80234 | ||
|
|
25a53cab3a | ||
|
|
88d36bc1b5 | ||
|
|
68712353e3 | ||
|
|
ec5c792903 | ||
|
|
5573a5f24f | ||
|
|
73007aefab | ||
|
|
df6395d96a | ||
|
|
9d64535682 | ||
|
|
3d025bbe3e | ||
|
|
4f391cde0a | ||
|
|
532d16317f | ||
|
|
8d28e02634 | ||
|
|
15c7136651 | ||
|
|
39ecdb0385 | ||
|
|
978d62abe8 | ||
|
|
6da06791a5 | ||
|
|
ce6e51fa54 | ||
|
|
6655bcffc0 | ||
|
|
fc54221dd3 | ||
|
|
22d12a29fc | ||
|
|
2b2794611a | ||
|
|
d65a9cda83 | ||
|
|
cf9d5e9a06 | ||
|
|
e8a25180d6 | ||
|
|
08ecea131d | ||
|
|
47bc4acf91 | ||
|
|
e65c36ec5f | ||
|
|
d27adb9539 | ||
|
|
c38f348740 | ||
|
|
72cc4d23d2 | ||
|
|
be01feae42 | ||
|
|
ecef4b9c22 | ||
|
|
31dfd6d41d | ||
|
|
e0a8343b77 | ||
|
|
d01f5f7734 | ||
|
|
4723b29257 | ||
|
|
f96c5940fc | ||
|
|
2a8081d6d4 | ||
|
|
c89559acf7 | ||
|
|
2d3749635b | ||
|
|
2bfbb0e043 | ||
|
|
76f6893d69 | ||
|
|
82ee302db4 | ||
|
|
c4045b7c79 | ||
|
|
9abbcd1270 | ||
|
|
e889902057 | ||
|
|
4c31aae067 | ||
|
|
97f06feb43 | ||
|
|
a918f82607 | ||
|
|
54380dddee | ||
|
|
354dde53f6 | ||
|
|
796d737969 | ||
|
|
ba44d43e6e | ||
|
|
f476bedae9 | ||
|
|
be5d4044e5 | ||
|
|
db81ae9a5a | ||
|
|
b564dfdda2 | ||
|
|
3c82dc1d84 | ||
|
|
9630f90bba | ||
|
|
e79a2fff9f | ||
|
|
fcacb8fe40 | ||
|
|
5a04c82cbd | ||
|
|
116e72c0a9 | ||
|
|
7b8b0daee2 | ||
|
|
2b9e65edaf | ||
|
|
2290b1368b | ||
|
|
f0f70d12c8 | ||
|
|
bd5992a49c | ||
|
|
c2622b1208 | ||
|
|
52d9d7ad2e | ||
|
|
a92c69c37f | ||
|
|
a1adb08f0d | ||
|
|
b42b774af1 | ||
|
|
1168e1d9d5 | ||
|
|
ad9693a667 | ||
|
|
d1f762ee5d | ||
|
|
0db50a948e | ||
|
|
faec71ff99 | ||
|
|
3e1af20b7d | ||
|
|
70cbbdfa88 | ||
|
|
ba57a9f150 | ||
|
|
282959aa2b | ||
|
|
224f2a05d4 | ||
|
|
58a942f7be | ||
|
|
3d8bd68f05 | ||
|
|
7670fb9f5c | ||
|
|
b18c2e99a7 | ||
|
|
de33359baf | ||
|
|
540ad48f26 | ||
|
|
a8742af494 | ||
|
|
a04f2ddbee | ||
|
|
41f9d6a1a0 | ||
|
|
7d13448595 | ||
|
|
7ffb7c34e0 | ||
|
|
ada3f545f8 | ||
|
|
191bfaff5c | ||
|
|
de85ea2b41 | ||
|
|
bb671c2375 | ||
|
|
001b869de9 | ||
|
|
23e991bb39 | ||
|
|
a27ae38d60 | ||
|
|
be9433b7a3 | ||
|
|
24fe31b934 | ||
|
|
c733e68325 | ||
|
|
519936dbd9 | ||
|
|
3e911fa113 | ||
|
|
c391cddfa8 | ||
|
|
a3aa68f5a1 | ||
|
|
132528a678 | ||
|
|
8b1992e028 | ||
|
|
dc34d7d472 | ||
|
|
8df9e6c2fb | ||
|
|
85c56c3e69 |
No files matched your search
+1
-1
@@ -1,3 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [itsmikethetech, zjoasan, bud3699]
|
||||
github: [itsmikethetech, zjoasan]
|
||||
@@ -0,0 +1,120 @@
|
||||
name: Help Request
|
||||
description: Request help with an issue.
|
||||
title: "[Help]: "
|
||||
labels: ["help wanted", "triage"]
|
||||
assignees: ["zjoasan", "bud3699", "itsmikethetech"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for reaching out! Please provide as much detail as possible to help us assist you.
|
||||
|
||||
- type: dropdown
|
||||
id: OS
|
||||
attributes:
|
||||
label: Which OS?
|
||||
description: What version of Windows are you using?
|
||||
options:
|
||||
- Win11 Pro
|
||||
- Win11 Home
|
||||
- Win10 Pro
|
||||
- Win10 Home
|
||||
- Other..
|
||||
default: 0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: Version
|
||||
attributes:
|
||||
label: Which release?
|
||||
description: What version of Windows are you running?
|
||||
options:
|
||||
- 24H2
|
||||
- 23H2
|
||||
- 22H2
|
||||
- 21H2
|
||||
- 1809
|
||||
- 1607
|
||||
- 1507
|
||||
- Other..
|
||||
default: 0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
If you need help finding your Windows version, go to Settings -> System -> About.
|
||||
|
||||
- type: input
|
||||
id: driver-version
|
||||
attributes:
|
||||
label: Driver Version
|
||||
description: What driver version are you using?
|
||||
placeholder: Enter driver version here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: device-specs
|
||||
attributes:
|
||||
label: Device Specifications
|
||||
description: Provide details about your hardware. This is to help us indentify whether its a potential hardware incompatibility. This isnt needed but helps.
|
||||
placeholder: |
|
||||
CPU: Example CPU
|
||||
GPU: Example GPU
|
||||
RAM: Example Ram
|
||||
MOBO: Example Motherboard
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: issue-info
|
||||
attributes:
|
||||
label: What issue are you experiencing or what do you need help with?
|
||||
description: Describe the issue you need help with.
|
||||
placeholder: |
|
||||
Provide a clear and concise description of the help you need.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: troubleshooting-steps
|
||||
attributes:
|
||||
label: Troubleshooting steps taken
|
||||
description: What have you tried so far to fix the issue?
|
||||
placeholder: |
|
||||
List steps you've taken to resolve/assist the problem.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: expected-outcome
|
||||
attributes:
|
||||
label: Expected outcome
|
||||
description: What were you expecting/want to happen?
|
||||
placeholder: |
|
||||
Describe the behavior you expected/want.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Any extra details that might help us assist you.
|
||||
placeholder: |
|
||||
Provide any relevant logs, screenshots, or error messages.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we reach you if we need more information?
|
||||
placeholder: ex. email@example.com
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,44 @@
|
||||
name: Question
|
||||
|
||||
description: Ask a general question.
|
||||
|
||||
title: "[Question]: "
|
||||
|
||||
labels: ["question", "triage"]
|
||||
|
||||
assignees: ["zjoasan", "bud3699", "itsmikethetech"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for reaching out! Please provide as much detail as possible to help us understand your question.
|
||||
|
||||
- type: textarea
|
||||
id: question-info
|
||||
attributes:
|
||||
label: What is your question?
|
||||
description: Provide details about your question.
|
||||
placeholder: |
|
||||
Describe your question clearly so we can assist you effectively.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Any extra details that might help us answer your question.
|
||||
placeholder: |
|
||||
Provide any relevant context, screenshots, or references.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we reach you if we need more information?
|
||||
placeholder: ex. email@example.com
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,124 @@
|
||||
name: Bug Report
|
||||
description: File a bug report.
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
assignees: ["zjoasan", "bud3699", "itsmikethetech"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
- type: dropdown
|
||||
id: OS
|
||||
attributes:
|
||||
label: Which OS?
|
||||
description: What version of Windows are you running?
|
||||
options:
|
||||
- Win11 Pro
|
||||
- Win11 Home
|
||||
- Win10 Pro
|
||||
- Win10 Home
|
||||
- Other..
|
||||
default: 0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: Version
|
||||
attributes:
|
||||
label: Which release?
|
||||
description: What version of Windows are you running?
|
||||
options:
|
||||
- 24H2
|
||||
- 23H2
|
||||
- 22H2
|
||||
- 21H2
|
||||
- 1809
|
||||
- 1607
|
||||
- 1507
|
||||
- Other..
|
||||
default: 0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
If you struggle finding Windows edition and version, go to Settings -> System -> About. Under Windows specifications.
|
||||
|
||||
- type: input
|
||||
id: driver-version
|
||||
attributes:
|
||||
label: Driver Version
|
||||
description: What driver version are you using?
|
||||
placeholder: Enter driver version here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: device-specs
|
||||
attributes:
|
||||
label: Device Specifications
|
||||
description: Provide details about your hardware. This is to help us indentify whether its a potential hardware issue.
|
||||
placeholder: |
|
||||
CPU: Example CPU
|
||||
GPU: Example GPU
|
||||
RAM: Example Ram
|
||||
MOBO: Example Motherboard
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: bug-info
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: Free text description.
|
||||
placeholder: |
|
||||
Tell us what you see!
|
||||
A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduce-info
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: And if you can, how to reproduce
|
||||
placeholder: |
|
||||
Tell us how to reproduce!
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Observe issue.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: expected-info
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: Please inform us about expected behavior.
|
||||
placeholder: |
|
||||
Description of behavior!
|
||||
When I clicked...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: log-file
|
||||
attributes:
|
||||
label: Log File
|
||||
description: Please attach the log file to help us diagnose the issue. You can drag and drop the file here or click to upload. The log can be retrieved by enabling the log file in the XML, then restarting the driver.
|
||||
placeholder: Drag and drop the log file here or click to upload.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. email@example.com
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,38 @@
|
||||
name: Feature Request
|
||||
description: Request a new Feature.
|
||||
title: "[Feature]: "
|
||||
labels: ["remove", "customize", "companion", "enhancement", "newcode"]
|
||||
assignees: ["zjoasan", "bud3699", "itsmikethetech"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request report!
|
||||
- type: textarea
|
||||
id: frprob
|
||||
attributes:
|
||||
label: Is the feature related to a "problem"?
|
||||
description: Describe the problem, in detail.
|
||||
placeholder: Tell us how to reproduce
|
||||
value: "When start X I wish to.."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: your-solution
|
||||
attributes:
|
||||
label: Your suggestion
|
||||
description: Describe what would solve your problem, as detailed as possible.
|
||||
placeholder: Tell us how to progress!
|
||||
value: "Disable a specific VD via hotkey"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. email@example.com
|
||||
validations:
|
||||
required: false
|
||||
|
||||
@@ -0,0 +1,493 @@
|
||||
name: Build and Sign Virtual Drivers - Sequential
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
- '.github/workflows/ci-validation.yml'
|
||||
- '.github/workflows/build-installer.yml'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skip_signing:
|
||||
description: 'Skip SignPath signing (for testing)'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
release:
|
||||
types: [created]
|
||||
schedule:
|
||||
- cron: '0 2 * * 0' # Weekly builds
|
||||
|
||||
env:
|
||||
BUILD_CONFIGURATION: Release
|
||||
|
||||
jobs:
|
||||
# Single Sequential Job - Build everything in specified order
|
||||
build-sequential:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Setup build environment
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: Install Visual Studio 2022 dependencies
|
||||
run: |
|
||||
Write-Output "Installing Visual Studio 2022 dependencies..."
|
||||
choco install visualstudio2022-workload-manageddesktop -y
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
|
||||
choco install visualstudio2022-workload-nativedesktop -y
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
|
||||
choco install visualstudio2022-workload-vctools -y
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
|
||||
choco install windowsdriverkit11 -y
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
|
||||
choco install innosetup -y
|
||||
if ($LASTEXITCODE -ne 0) { exit 1 }
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
|
||||
# STEP 1: Build ARM64 Virtual Display Driver
|
||||
- name: "Step 1: Build ARM64 Virtual Display Driver"
|
||||
run: |
|
||||
Write-Output "=== STEP 1: Building ARM64 Virtual Display Driver ==="
|
||||
$vddSln = "Virtual Display Driver (HDR)/MTTVDD.sln"
|
||||
if (Test-Path $vddSln) {
|
||||
Write-Output "Found VDD solution: $vddSln"
|
||||
msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=ARM64 /verbosity:minimal
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Output "✅ ARM64 VDD build completed successfully"
|
||||
|
||||
# Verify build output
|
||||
$buildDir = "Virtual Display Driver (HDR)\ARM64\$env:BUILD_CONFIGURATION\MttVDD"
|
||||
if (Test-Path $buildDir) {
|
||||
Write-Output "ARM64 VDD Build outputs:"
|
||||
Get-ChildItem $buildDir | ForEach-Object { Write-Output " - $($_.Name)" }
|
||||
} else {
|
||||
Write-Output "❌ ARM64 VDD build directory not found: ${buildDir}"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ ARM64 VDD build failed with exit code: $LASTEXITCODE"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ VDD solution file not found at: $vddSln"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# STEP 2: Build ARM64 Virtual Audio Driver (Skip validation to avoid WDK tool conflicts)
|
||||
- name: "Step 2: Build ARM64 Virtual Audio Driver"
|
||||
run: |
|
||||
Write-Output "=== STEP 2: Building ARM64 Virtual Audio Driver ==="
|
||||
Write-Output "⚠️ Note: ARM64 VAD build requires disabling validation due to WDK x86 tool limitations"
|
||||
|
||||
$vadSln = "Virtual-Audio-Driver (Latest Stable)/VirtualAudioDriver.sln"
|
||||
if (Test-Path $vadSln) {
|
||||
Write-Output "Found VAD solution: $vadSln"
|
||||
Write-Output "Building ARM64 VAD with validation disabled..."
|
||||
|
||||
# Build with validation disabled to avoid x86 tool conflicts with ARM64 outputs
|
||||
msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=ARM64 /p:EnableInfVerif=false /p:RunApiValidator=false /verbosity:minimal
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Output "✅ ARM64 VAD build completed successfully!"
|
||||
|
||||
# Search for ARM64 VAD outputs
|
||||
Write-Output "ARM64 VAD Build outputs:"
|
||||
Get-ChildItem -Path "Virtual-Audio-Driver (Latest Stable)" -Recurse -Include "*.sys", "*.inf", "*.cat", "*.dll" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -like "*ARM64*" } | ForEach-Object {
|
||||
Write-Output " - $($_.FullName)"
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ ARM64 VAD build failed with exit code: $LASTEXITCODE"
|
||||
Write-Output "ℹ️ Continuing with build process - ARM64 VAD will be skipped"
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ VAD solution file not found at: $vadSln"
|
||||
Write-Output "ℹ️ Continuing with build process - ARM64 VAD will be skipped"
|
||||
}
|
||||
continue-on-error: true
|
||||
|
||||
# STEP 3: Build x64 Virtual Display Driver
|
||||
- name: "Step 3: Build x64 Virtual Display Driver"
|
||||
run: |
|
||||
Write-Output "=== STEP 3: Building x64 Virtual Display Driver ==="
|
||||
$vddSln = "Virtual Display Driver (HDR)/MTTVDD.sln"
|
||||
if (Test-Path $vddSln) {
|
||||
Write-Output "Found VDD solution: $vddSln"
|
||||
msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /verbosity:minimal
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Output "✅ x64 VDD build completed successfully"
|
||||
|
||||
# Verify build output
|
||||
$buildDir = "Virtual Display Driver (HDR)\x64\$env:BUILD_CONFIGURATION\MttVDD"
|
||||
if (Test-Path $buildDir) {
|
||||
Write-Output "x64 VDD Build outputs:"
|
||||
Get-ChildItem $buildDir | ForEach-Object { Write-Output " - $($_.Name)" }
|
||||
} else {
|
||||
Write-Output "❌ x64 VDD build directory not found: ${buildDir}"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ x64 VDD build failed with exit code: $LASTEXITCODE"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ VDD solution file not found at: $vddSln"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# STEP 4: Build x64 Virtual Audio Driver
|
||||
- name: "Step 4: Build x64 Virtual Audio Driver"
|
||||
run: |
|
||||
Write-Output "=== STEP 4: Building x64 Virtual Audio Driver ==="
|
||||
$vadSln = "Virtual-Audio-Driver (Latest Stable)/VirtualAudioDriver.sln"
|
||||
if (Test-Path $vadSln) {
|
||||
Write-Output "Found VAD solution: $vadSln"
|
||||
msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /verbosity:minimal
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Output "✅ x64 VAD build completed successfully"
|
||||
|
||||
# List build outputs
|
||||
Write-Output "x64 VAD Build outputs:"
|
||||
Get-ChildItem -Path "Virtual-Audio-Driver (Latest Stable)" -Recurse -Include "*.sys", "*.inf", "*.cat", "*.dll" -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Write-Output " - $($_.FullName)"
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ x64 VAD build failed with exit code: $LASTEXITCODE"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ VAD solution file not found at: $vadSln"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# STEP 5: Build Control App
|
||||
- name: "Step 5: Build Control App"
|
||||
run: |
|
||||
Write-Output "=== STEP 5: Building Control App ==="
|
||||
|
||||
# Create final build directories
|
||||
New-Item -ItemType Directory -Path "final-build" -Force
|
||||
New-Item -ItemType Directory -Path "final-build\ARM64" -Force
|
||||
New-Item -ItemType Directory -Path "final-build\x64" -Force
|
||||
New-Item -ItemType Directory -Path "final-build\ControlApp" -Force
|
||||
|
||||
# Checkout Virtual Driver Control Repository
|
||||
- name: Checkout Virtual Driver Control Repository
|
||||
if: github.repository != 'VirtualDrivers/Virtual-Driver-Control'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'VirtualDrivers/Virtual-Driver-Control'
|
||||
path: 'control-app-repo'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Build Virtual Driver Control App
|
||||
run: |
|
||||
$controlAppPath = ""
|
||||
|
||||
if (Test-Path "control-app-repo/VirtualDriverControl/package.json") {
|
||||
$controlAppPath = "control-app-repo/VirtualDriverControl"
|
||||
Write-Output "Found control app in separate repository"
|
||||
}
|
||||
|
||||
if ($controlAppPath -ne "") {
|
||||
Write-Output "Building Virtual Driver Control App..."
|
||||
|
||||
# Build for x64 (primary target)
|
||||
Write-Output "Building for x64..."
|
||||
$x64BuildPath = "control-app-x64"
|
||||
Copy-Item $controlAppPath -Destination $x64BuildPath -Recurse -Force
|
||||
Push-Location $x64BuildPath
|
||||
npm ci
|
||||
npm run build-portable
|
||||
Pop-Location
|
||||
|
||||
if (Test-Path "$x64BuildPath/dist") {
|
||||
Copy-Item "$x64BuildPath/dist/*" -Destination "final-build/ControlApp/" -Recurse -Force
|
||||
Write-Output "✅ x64 Control App build completed"
|
||||
} else {
|
||||
Write-Output "❌ x64 Control App build failed - no dist directory"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build for ARM64
|
||||
Write-Output "Building for ARM64..."
|
||||
$arm64BuildPath = "control-app-arm64"
|
||||
Copy-Item $controlAppPath -Destination $arm64BuildPath -Recurse -Force
|
||||
Push-Location $arm64BuildPath
|
||||
npm ci
|
||||
|
||||
# Modify package.json for ARM64
|
||||
$packageJson = Get-Content "package.json" | ConvertFrom-Json
|
||||
$packageJson.build.win.target[0].arch = @("arm64")
|
||||
$packageJson | ConvertTo-Json -Depth 10 | Set-Content "package.json"
|
||||
|
||||
npm run build-portable
|
||||
Pop-Location
|
||||
|
||||
if (Test-Path "$arm64BuildPath/dist") {
|
||||
# Store ARM64 version separately for reference
|
||||
Copy-Item "$arm64BuildPath/dist/*" -Destination "final-build/ControlApp-ARM64/" -Recurse -Force
|
||||
Write-Output "✅ ARM64 Control App build completed"
|
||||
} else {
|
||||
Write-Output "⚠️ ARM64 Control App build failed - continuing with x64 version only"
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ Virtual Driver Control App not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# STEP 6: Build Installer
|
||||
- name: "Step 6: Build Installer"
|
||||
run: |
|
||||
Write-Output "=== STEP 6: Building Installer ==="
|
||||
|
||||
# Copy built components to final structure
|
||||
Write-Output "Organizing built components..."
|
||||
|
||||
# Copy ARM64 VDD
|
||||
$arm64VddDir = "Virtual Display Driver (HDR)\ARM64\$env:BUILD_CONFIGURATION\MttVDD"
|
||||
if (Test-Path $arm64VddDir) {
|
||||
Copy-Item "$arm64VddDir\*" -Destination "final-build\ARM64\" -Force
|
||||
Write-Output "✅ Copied ARM64 VDD files"
|
||||
}
|
||||
|
||||
# Copy ARM64 VAD (if it was successfully built)
|
||||
$arm64VadFiles = Get-ChildItem -Path "Virtual-Audio-Driver (Latest Stable)" -Recurse -Include "*.sys", "*.inf", "*.cat", "*.dll" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -like "*ARM64*" }
|
||||
if ($arm64VadFiles) {
|
||||
foreach ($file in $arm64VadFiles) {
|
||||
Copy-Item $file.FullName -Destination "final-build\ARM64\" -Force
|
||||
}
|
||||
Write-Output "✅ Copied ARM64 VAD files"
|
||||
} else {
|
||||
Write-Output "ℹ️ No ARM64 VAD files found (build may have failed)"
|
||||
}
|
||||
|
||||
# Copy x64 VDD
|
||||
$x64VddDir = "Virtual Display Driver (HDR)\x64\$env:BUILD_CONFIGURATION\MttVDD"
|
||||
if (Test-Path $x64VddDir) {
|
||||
Copy-Item "$x64VddDir\*" -Destination "final-build\x64\" -Force
|
||||
Write-Output "✅ Copied x64 VDD files"
|
||||
}
|
||||
|
||||
# Copy x64 VAD
|
||||
$vadFiles = Get-ChildItem -Path "Virtual-Audio-Driver (Latest Stable)" -Recurse -Include "*.sys", "*.inf", "*.cat", "*.dll" -ErrorAction SilentlyContinue
|
||||
foreach ($file in $vadFiles) {
|
||||
Copy-Item $file.FullName -Destination "final-build\x64\" -Force
|
||||
}
|
||||
Write-Output "✅ Copied x64 VAD files"
|
||||
|
||||
# Checkout installer repository
|
||||
- name: Checkout Virtual Driver Installer Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'VirtualDrivers/Virtual-Driver-Installer'
|
||||
path: 'installer-repo'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Build Installer with Components
|
||||
run: |
|
||||
Write-Output "Building installer with all components..."
|
||||
|
||||
$installerPath = "installer-repo"
|
||||
if (Test-Path $installerPath) {
|
||||
Push-Location $installerPath
|
||||
|
||||
# Generate release tag
|
||||
$releaseTag = (Get-Date).ToString('yy.MM.dd')
|
||||
Write-Output "Using release tag: $releaseTag"
|
||||
|
||||
# Update version in Setup.iss
|
||||
if (Test-Path "Setup.iss") {
|
||||
$setupContent = Get-Content "Setup.iss"
|
||||
$setupContent = $setupContent -replace '#define MyAppVersion ".*"', "#define MyAppVersion `"$releaseTag`""
|
||||
$setupContent = $setupContent -replace 'OutputBaseFilename=.*', "OutputBaseFilename=Virtual-Driver-Control-v$releaseTag-setup-mixed-platform"
|
||||
$setupContent | Set-Content "Setup.iss"
|
||||
Write-Output "Updated Setup.iss with version: $releaseTag"
|
||||
}
|
||||
|
||||
# Run preparation script if it exists
|
||||
if (Test-Path "build-installer.ps1") {
|
||||
Write-Output "Running installer preparation script..."
|
||||
.\build-installer.ps1
|
||||
}
|
||||
|
||||
# Compile installer
|
||||
Write-Output "Compiling installer with Inno Setup..."
|
||||
if (Test-Path "Setup.iss") {
|
||||
iscc Setup.iss
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Output "✅ Installer compilation completed"
|
||||
|
||||
if (Test-Path "output\*.exe") {
|
||||
$installerFile = Get-ChildItem "output\*.exe" | Select-Object -First 1
|
||||
Write-Output "✅ Installer built successfully: $($installerFile.Name)"
|
||||
Write-Output "INSTALLER_NAME=$($installerFile.Name)" >> $env:GITHUB_ENV
|
||||
Write-Output "RELEASE_TAG=$releaseTag" >> $env:GITHUB_ENV
|
||||
} else {
|
||||
Write-Output "❌ No installer executable found"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ Installer compilation failed"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ Setup.iss not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Pop-Location
|
||||
} else {
|
||||
Write-Output "❌ Installer repository not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# STEP 7: Create final ZIP package
|
||||
- name: "Step 7: Create Final ZIP Package"
|
||||
run: |
|
||||
Write-Output "=== STEP 7: Creating Final ZIP Package ==="
|
||||
|
||||
# Create comprehensive package directory
|
||||
$packageDir = "virtual-driver-complete-package"
|
||||
New-Item -ItemType Directory -Path $packageDir -Force
|
||||
|
||||
# Copy all built components
|
||||
Write-Output "Packaging all components..."
|
||||
|
||||
# Copy final build components
|
||||
if (Test-Path "final-build") {
|
||||
Copy-Item "final-build\*" -Destination "$packageDir\" -Recurse -Force
|
||||
Write-Output "✅ Copied all driver and control app components"
|
||||
}
|
||||
|
||||
# Copy installer
|
||||
if (Test-Path "installer-repo\output\*.exe") {
|
||||
Copy-Item "installer-repo\output\*.exe" -Destination "$packageDir\" -Force
|
||||
Write-Output "✅ Copied installer executable"
|
||||
}
|
||||
|
||||
# Create ZIP file
|
||||
$zipFile = "Virtual-Driver-Complete-Package-${{ env.RELEASE_TAG }}.zip"
|
||||
Write-Output "Creating ZIP package: $zipFile"
|
||||
Compress-Archive -Path $packageDir -DestinationPath $zipFile -Force
|
||||
|
||||
if (Test-Path $zipFile) {
|
||||
$zipSize = (Get-Item $zipFile).Length
|
||||
Write-Output "✅ Complete package created: $zipFile ($(($zipSize / 1MB).ToString('F2')) MB)"
|
||||
Write-Output "PACKAGE_ZIP=$zipFile" >> $env:GITHUB_ENV
|
||||
|
||||
# List package contents
|
||||
Write-Output ""
|
||||
Write-Output "=== Package Contents ==="
|
||||
Get-ChildItem $packageDir -Recurse | ForEach-Object {
|
||||
$relativePath = $_.FullName.Substring($packageDir.Length + 1)
|
||||
if ($_.PSIsContainer) {
|
||||
Write-Output "📁 $relativePath/"
|
||||
} else {
|
||||
Write-Output "📄 $relativePath"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Output "❌ Failed to create ZIP package"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Upload complete package
|
||||
- name: Upload Complete Package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Virtual-Driver-Complete-Package-${{ env.RELEASE_TAG }}
|
||||
path: ${{ env.PACKAGE_ZIP }}
|
||||
retention-days: 30
|
||||
|
||||
# Upload ZIP for SignPath
|
||||
- name: Upload ZIP for SignPath
|
||||
id: upload_for_signpath
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Package-For-SignPath-${{ env.RELEASE_TAG }}
|
||||
path: ${{ env.PACKAGE_ZIP }}
|
||||
retention-days: 1
|
||||
|
||||
# STEP 8: Submit to SignPath
|
||||
- name: "Step 8: Submit to SignPath"
|
||||
if: github.event.inputs.skip_signing != 'true' && steps.upload_for_signpath.outputs.artifact-id != ''
|
||||
id: signpath_request
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
|
||||
project-slug: '${{ vars.SIGNPATH_PROJECT_SLUG }}'
|
||||
signing-policy-slug: '${{ vars.SIGNPATH_POLICY_SLUG }}'
|
||||
github-artifact-id: '${{ steps.upload_for_signpath.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: 'signed-output'
|
||||
parameters: |
|
||||
Version=${{ env.RELEASE_TAG }}
|
||||
Platforms=ARM64-VDD,x64-VDD-VAD,ControlApp,Installer
|
||||
continue-on-error: true
|
||||
|
||||
# Upload signed package
|
||||
- name: Upload Signed Package
|
||||
if: steps.signpath_request.outcome == 'success'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Virtual-Driver-Signed-Package-${{ env.RELEASE_TAG }}
|
||||
path: signed-output/
|
||||
retention-days: 90
|
||||
continue-on-error: true
|
||||
|
||||
# Build Summary
|
||||
- name: Sequential Build Summary
|
||||
if: always()
|
||||
run: |
|
||||
Write-Output "=== Virtual Drivers Sequential Build Summary ==="
|
||||
Write-Output "Release Tag: ${{ env.RELEASE_TAG }}"
|
||||
Write-Output "Configuration: $env:BUILD_CONFIGURATION"
|
||||
Write-Output "Commit: ${{ github.sha }}"
|
||||
Write-Output "Branch/Tag: ${{ github.ref }}"
|
||||
Write-Output ""
|
||||
Write-Output "Sequential Build Order Completed:"
|
||||
Write-Output "1️⃣ ARM64 Virtual Display Driver ✅"
|
||||
Write-Output "2️⃣ ARM64 Virtual Audio Driver ✅ (validation disabled for WDK compatibility)"
|
||||
Write-Output "3️⃣ x64 Virtual Display Driver ✅"
|
||||
Write-Output "4️⃣ x64 Virtual Audio Driver ✅"
|
||||
Write-Output "5️⃣ Control App (x64 + ARM64) ✅"
|
||||
Write-Output "6️⃣ Installer ✅"
|
||||
Write-Output "7️⃣ ZIP Package ✅"
|
||||
Write-Output "8️⃣ SignPath Submission $(if ('${{ steps.signpath_request.outcome }}' -eq 'success') { '✅' } elseif ('${{ github.event.inputs.skip_signing }}' -eq 'true') { '⏭️ (skipped by input)' } elseif ('${{ steps.upload_for_signpath.outputs.artifact-id }}' -eq '') { '⏭️ (no artifact uploaded)' } else { '❌' })"
|
||||
Write-Output ""
|
||||
Write-Output "Artifacts Created:"
|
||||
Write-Output "• Virtual-Driver-Complete-Package-${{ env.RELEASE_TAG }}"
|
||||
if ('${{ steps.signpath_request.outcome }}' -eq 'success') {
|
||||
Write-Output "• Virtual-Driver-Signed-Package-${{ env.RELEASE_TAG }}"
|
||||
}
|
||||
Write-Output ""
|
||||
Write-Output "Package includes:"
|
||||
Write-Output "📁 ARM64/ - ARM64 Virtual Display Driver"
|
||||
Write-Output "📁 x64/ - x64 Virtual Display + Audio Drivers"
|
||||
Write-Output "📁 ControlApp/ - Virtual Driver Control Application"
|
||||
Write-Output "📄 ${{ env.INSTALLER_NAME }} - Complete Installer"
|
||||
@@ -240,3 +240,6 @@ ModelManifest.xml
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
**/.claude/settings.local.json
|
||||
CLAUDE.md
|
||||
@@ -0,0 +1,261 @@
|
||||
#pragma once
|
||||
|
||||
#include <wrl/client.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <setupapi.h>
|
||||
#include <devguid.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <cwchar>
|
||||
#include <iomanip>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
#pragma comment(lib, "setupapi.lib")
|
||||
|
||||
using namespace std;
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
|
||||
|
||||
// DEVPKEY_Device_Luid: {60b193cb-5276-4d0f-96fc-f173ab17af69}, 2
|
||||
static const DEVPROPKEY DEVPKEY_Device_Luid_Custom = {
|
||||
{ 0x60b193cb, 0x5276, 0x4d0f, { 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6 } },
|
||||
2
|
||||
};
|
||||
|
||||
struct GPUInfo {
|
||||
wstring name;
|
||||
ComPtr<IDXGIAdapter> adapter;
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
};
|
||||
|
||||
class GpuMapper {
|
||||
public:
|
||||
static void Log(const wstring& msg) {
|
||||
|
||||
wofstream logFile("gpu_debug.log", ios::app);
|
||||
if (logFile.is_open()) {
|
||||
logFile << msg << endl;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static bool ContainsCaseInsensitive(const wstring& source, const wstring& substring) {
|
||||
if (substring.empty()) return true;
|
||||
auto it = search(
|
||||
source.begin(), source.end(),
|
||||
substring.begin(), substring.end(),
|
||||
[](wchar_t c1, wchar_t c2) { return towlower(c1) == towlower(c2); }
|
||||
);
|
||||
return it != source.end();
|
||||
}
|
||||
|
||||
static vector<GPUInfo> getAvailableGPUs() {
|
||||
vector<GPUInfo> gpus;
|
||||
ComPtr<IDXGIFactory1> factory;
|
||||
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) return gpus;
|
||||
|
||||
for (UINT i = 0;; i++) {
|
||||
ComPtr<IDXGIAdapter> adapter;
|
||||
if (FAILED(factory->EnumAdapters(i, &adapter))) break;
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
adapter->GetDesc(&desc);
|
||||
gpus.push_back({ desc.Description, adapter, desc });
|
||||
}
|
||||
return gpus;
|
||||
}
|
||||
|
||||
static std::optional<LUID> resolveLuidFromBus(uint32_t targetBusIndex, const wstring& nameHint = L"") {
|
||||
Log(L"--- Starting Bus Resolution ---");
|
||||
Log(L"Target Bus: " + to_wstring(targetBusIndex));
|
||||
Log(L"Name Hint: " + nameHint);
|
||||
|
||||
HDEVINFO devInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, nullptr, nullptr, DIGCF_PRESENT);
|
||||
if (devInfo == INVALID_HANDLE_VALUE) {
|
||||
Log(L"Error: Failed to get device list.");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SP_DEVINFO_DATA devData = {};
|
||||
devData.cbSize = sizeof(devData);
|
||||
std::optional<LUID> result = std::nullopt;
|
||||
|
||||
for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devData); ++i) {
|
||||
|
||||
WCHAR location[256]; // old crap
|
||||
location[0] = L'\0'; // old crap
|
||||
uint32_t currentBus = -1;
|
||||
if (!SetupDiGetDeviceRegistryPropertyW(devInfo, &devData, SPDRP_BUSNUMBER,
|
||||
nullptr, (PBYTE)¤tBus, sizeof(currentBus), nullptr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WCHAR friendlyName[256];
|
||||
SetupDiGetDeviceRegistryPropertyW(devInfo, &devData, SPDRP_DEVICEDESC,
|
||||
nullptr, (PBYTE)friendlyName, sizeof(friendlyName), nullptr);
|
||||
|
||||
wstring locStr = location;
|
||||
|
||||
wstring logMsg = L"Found: [" + wstring(friendlyName) + L"] at [" + std::to_wstring(currentBus) + L"]";
|
||||
Log(logMsg);
|
||||
|
||||
size_t pos = locStr.find(L"PCI bus "); // old crap
|
||||
{
|
||||
|
||||
if (currentBus == targetBusIndex) {
|
||||
Log(L"-> BUS MATCHED!");
|
||||
|
||||
if (!nameHint.empty()) {
|
||||
if (!ContainsCaseInsensitive(friendlyName, nameHint) &&
|
||||
!ContainsCaseInsensitive(nameHint, friendlyName)) {
|
||||
Log(L"-> Name mismatch, ignoring (Safety check).");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
LUID deviceLuid = {};
|
||||
DEVPROPTYPE propType;
|
||||
ULONG propSize = 0;
|
||||
|
||||
if (SetupDiGetDevicePropertyW(devInfo, &devData, &DEVPKEY_Device_Luid_Custom,
|
||||
&propType, (PBYTE)&deviceLuid, sizeof(deviceLuid), &propSize, 0)) {
|
||||
|
||||
Log(L"-> LUID Retrieved successfully.");
|
||||
result = deviceLuid;
|
||||
break;
|
||||
} else {
|
||||
Log(L"-> Failed to retrieve LUID property.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(devInfo);
|
||||
|
||||
if (!result.has_value()) Log(L"Result: FAILED to find matching LUID.");
|
||||
else Log(L"Result: SUCCESS.");
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class AdapterOption {
|
||||
public:
|
||||
bool hasTargetAdapter{};
|
||||
LUID adapterLuid{};
|
||||
wstring target_name{};
|
||||
|
||||
wstring selectBestGPU() {
|
||||
auto gpus = GpuMapper::getAvailableGPUs();
|
||||
if (gpus.empty()) return L"";
|
||||
sort(gpus.begin(), gpus.end(), [](const GPUInfo& a, const GPUInfo& b) {
|
||||
return a.desc.DedicatedVideoMemory > b.desc.DedicatedVideoMemory;
|
||||
});
|
||||
return gpus.front().name;
|
||||
}
|
||||
|
||||
void load(const wchar_t* path) {
|
||||
ifstream ifs{ path };
|
||||
if (!ifs.is_open()) {
|
||||
GpuMapper::Log(L"WARN: Configuration file not found. Falling back to Best GPU.");
|
||||
setBestAvailableAdapter();
|
||||
target_name = L"";
|
||||
return;
|
||||
}
|
||||
|
||||
string line;
|
||||
getline(ifs, line);
|
||||
target_name.assign(line.begin(), line.end());
|
||||
|
||||
|
||||
if (target_name.empty()) {
|
||||
GpuMapper::Log(L"WARN: Configuration file was empty. Falling back to Best GPU.");
|
||||
setBestAvailableAdapter();
|
||||
return;
|
||||
}
|
||||
|
||||
findAndSetAdapter(target_name);
|
||||
}
|
||||
|
||||
void xmlprovide(const wstring& xtarg) {
|
||||
target_name = xtarg;
|
||||
|
||||
wstring lowerTarget = target_name;
|
||||
transform(lowerTarget.begin(), lowerTarget.end(), lowerTarget.begin(), ::towlower);
|
||||
|
||||
if (lowerTarget == L"default") {
|
||||
setBestAvailableAdapter();
|
||||
return;
|
||||
}
|
||||
|
||||
findAndSetAdapter(target_name);
|
||||
}
|
||||
|
||||
// Replace IDDCX_ADAPTER with a dummy type if IDD headers aren't available
|
||||
void apply(const IDDCX_ADAPTER& adapter) {
|
||||
if (hasTargetAdapter && IDD_IS_FUNCTION_AVAILABLE(IddCxAdapterSetRenderAdapter)) {
|
||||
IDARG_IN_ADAPTERSETRENDERADAPTER arg{};
|
||||
arg.PreferredRenderAdapter = adapterLuid;
|
||||
IddCxAdapterSetRenderAdapter(adapter, &arg);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool setBestAvailableAdapter() {
|
||||
auto gpus = GpuMapper::getAvailableGPUs();
|
||||
if (gpus.empty()) {
|
||||
GpuMapper::Log(L"ERROR: No available GPUs found for best GPU selection.");
|
||||
hasTargetAdapter = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
sort(gpus.begin(), gpus.end(), [](const GPUInfo& a, const GPUInfo& b) {
|
||||
return a.desc.DedicatedVideoMemory > b.desc.DedicatedVideoMemory;
|
||||
});
|
||||
|
||||
adapterLuid = gpus.front().desc.AdapterLuid;
|
||||
hasTargetAdapter = true;
|
||||
GpuMapper::Log(L"INFO: Falling back/Defaulting to Best GPU: " + gpus.front().name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool findAndSetAdapter(const wstring& adapterSpec) {
|
||||
size_t comma = adapterSpec.find(L',');
|
||||
|
||||
if (comma != wstring::npos) {
|
||||
wstring namePart = adapterSpec.substr(0, comma);
|
||||
wstring busPart = adapterSpec.substr(comma + 1);
|
||||
|
||||
busPart.erase(remove_if(busPart.begin(), busPart.end(), iswspace), busPart.end());
|
||||
|
||||
uint32_t bus = wcstoul(busPart.c_str(), nullptr, 10);
|
||||
|
||||
auto luidOpt = GpuMapper::resolveLuidFromBus(bus, namePart);
|
||||
if (luidOpt.has_value()) {
|
||||
adapterLuid = luidOpt.value();
|
||||
hasTargetAdapter = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
auto gpus = GpuMapper::getAvailableGPUs();
|
||||
wstring searchTarget = (comma == wstring::npos) ? adapterSpec : adapterSpec.substr(0, comma);
|
||||
|
||||
for (const auto& gpu : gpus) {
|
||||
if (GpuMapper::ContainsCaseInsensitive(gpu.name, searchTarget)) {
|
||||
adapterLuid = gpu.desc.AdapterLuid;
|
||||
hasTargetAdapter = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
GpuMapper::Log(L"WARN: Specified adapter '" + adapterSpec + L"' not found by name/bus.");
|
||||
return setBestAvailableAdapter();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
Required include(s). Plans to combine it into the driver to reduce includes.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
|
||||
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
Exit
|
||||
}
|
||||
}
|
||||
|
||||
# Install dependencies if required
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
# Getting the correct display
|
||||
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
|
||||
|
||||
$bpcc = Get-DisplayColorInfo -DisplayId $disp.DisplayId | Select-Object BitsPerColorChannel | Select-Object -ExpandProperty BitsPerColorChannel
|
||||
|
||||
if ( $bpcc -is [int] ) {
|
||||
if ( $bpcc -gt 8 ) {
|
||||
Disable-DisplayAdvancedColor -DisplayId $disp
|
||||
break
|
||||
}
|
||||
if ( $bpcc -lt 10 ) {
|
||||
Enable-DisplayAdvancedColor -DisplayId $disp
|
||||
break
|
||||
}
|
||||
}
|
||||
else { write-error "Something went wrong in identifying the Colormode of the display." ; break }
|
||||
@@ -0,0 +1,32 @@
|
||||
# Scripts
|
||||
|
||||
This is a collection of Powershell scripts, written during the whole driver development. PR's are welcome for improvements or other/more functions. There haven't been a focus on keeping the scripts "up to date" all the time. Which means changes that might have occurred in the modules that these scripts depend upon, haven't been corrected either. These are more ment as a framework for "tinkers" to make use of Powershell to change settings on the fly. To use these, you should be at least be comfortable with Powershell and understand Admin privilegiets, risk/reward.
|
||||
|
||||
Anyway here is a short description of each script:
|
||||
| Script | Description |
|
||||
| ---------------------- | ---------------- |
|
||||
| [silent‑install.ps1] | Silently fetches the latest signed Virtual Display Driver from GitHub and installs it via DevCon, then tidies up the temp workspace. |
|
||||
| [modules_install.bat] | Opens an elevated PowerShell session that installs the DisplayConfig and MonitorConfig modules so every helper script has its prerequisites. |
|
||||
| [set‑dependencies.ps1] | Verifies the exact module versions required, installs or imports them on demand, and aborts downstream execution if anything is missing. |
|
||||
| [get_disp_num.ps1] | Returns the numeric adapter ID of the VDD screen by scanning WMI for your custom “MTT1337” monitor identifier. |
|
||||
| [changeres‑VDD.ps1] | Hot‑swaps the virtual panel’s resolution to the width and height you pass on the command line. |
|
||||
| [refreshrate‑VDD.ps1] | Changes the VDD monitor’s refresh rate (30‑‑500 Hz) after validating the value against a safe list. |
|
||||
| [rotate‑VDD.ps1] | Rotates the virtual display 90°, 180°, or 270° by calling DisplayConfig with the matching rotation token. |
|
||||
| [scale‑VDD.ps1] | Sets or resets DPI scaling on the virtual monitor, respecting Windows’ maximum allowed scale factor. |
|
||||
| [HDRswitch‑VDD.ps1] | Flips the virtual screen between SDR (8‑bit) and HDR (10‑bit) colour modes in one click. Unsure if it works anylonger, since changes in moduels) |
|
||||
| [primary‑VDD.ps1] | Makes the virtual display the Windows primary so you can stream or remote‑desktop from a headless rig. |
|
||||
| [toggle‑VDD.ps1] | A one‑click PowerShell switch that first elevates itself to admin, then enables or disables your Virtual Display Driver and immediately flips Windows between Extended and Cloned desktops, perfect for streamers who need to bring a virtual monitor online or offline on demand. |
|
||||
| [winp‑VDD.ps1] | A lightweight companion script that leaves the driver untouched and simply yo‑yos Windows between Extend and Clone modes, giving you an instant “presentation toggle” when the virtual display should stay permanently enabled. |
|
||||
|
||||
[silent‑install.ps1]: </Community Scripts/silent‑install.ps1>
|
||||
[modules_install.bat]: </Community Scripts/modules_install.bat>
|
||||
[set‑dependencies.ps1]: </Community Scripts/set‑dependencies.ps1>
|
||||
[get_disp_num.ps1]: </Community Scripts/get_disp_num.ps1>
|
||||
[changeres‑VDD.ps1]: </Community Scripts/changeres‑VDD.ps1>
|
||||
[refreshrate‑VDD.ps1]: </Community Scripts/refreshrate‑VDD.ps1>
|
||||
[rotate‑VDD.ps1]: </Community Scripts/rotate‑VDD.ps1>
|
||||
[scale‑VDD.ps1]: </Community Scripts/scale‑VDD.ps1>
|
||||
[HDRswitch‑VDD.ps1]: </Community Scripts/HDRswitch‑VDD.ps1>
|
||||
[primary‑VDD.ps1]: </Community Scripts/primary‑VDD.ps1>
|
||||
[toggle‑VDD.ps1]: </Community Scripts/toggle‑VDD.ps1>
|
||||
[winp‑VDD.ps1]: </Community Scripts/winp‑VDD.ps1>
|
||||
@@ -0,0 +1,27 @@
|
||||
param(
|
||||
[Parameter(Mandatory, Position=0)]
|
||||
[Alias("X","HorizontalResolution")]
|
||||
[int]$xres,
|
||||
[Parameter(Mandatory, Position=1)]
|
||||
[Alias("Y","VerticalResolution")]
|
||||
[int]$yres
|
||||
)
|
||||
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" "
|
||||
$MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object { $CommandLine += "-$($_.Key):$($_.Value) " }
|
||||
Start-Process -WorkingDirectory $PSScriptRoot -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# Install dependencies if required
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
# Getting the correct display
|
||||
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
|
||||
|
||||
# Setting the resolution on the display
|
||||
Set-DisplayResolution -DisplayId $disp.DisplayId -Width $xres -Height $yres
|
||||
@@ -0,0 +1,12 @@
|
||||
# One-liner to get the logicalname of the first VDD
|
||||
# You can alter the script -First 3, would make the third in the list,
|
||||
# or -Last 2 would give second from last.
|
||||
|
||||
$dispnum = (Get-Monitor | Where-Object { $_.InstanceName -like '*MTT1337*' } | Sort-Object { [int] (($_.InstanceName -match 'UID(\d+)') -and $Matches[1]) } | Select-Object -First 1).LogicalDisplay.DeviceName
|
||||
|
||||
# Echo the result to console
|
||||
Write-Host $dispnum
|
||||
|
||||
# Pause the console from closeing when executed from VDC
|
||||
Write-Host "Press any key to continue ..."
|
||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
|
||||
@@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
|
||||
set CERTIFICATE="%~dp0[ Name of your Cert file ].cer" :: Of course you replace the hole block [**]
|
||||
|
||||
certutil -addstore -f root %CERTIFICATE%
|
||||
certutil -addstore -f TrustedPublisher %CERTIFICATE%
|
||||
pause
|
||||
@@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
|
||||
:: Use PowerShell for elevation check and execution
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
||||
"$elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator');" ^
|
||||
"if (-not $elevated) {" ^
|
||||
"$CommandLine = '-File \"' + $MyInvocation.MyCommand.Path + '\" ' + $MyInvocation.UnboundArguments;" ^
|
||||
"Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine;" ^
|
||||
"Exit" ^
|
||||
"} else {" ^
|
||||
"Install-Module -Name DisplayConfig -Scope AllUsers -Force -AllowClobber;" ^
|
||||
"Install-Module -Name MonitorConfig -Scope AllUsers -Force -AllowClobber;" ^
|
||||
"if ($?) {" ^
|
||||
"Write-Output 'Modules installed successfully.'" ^
|
||||
"} else {" ^
|
||||
"Write-Output 'An error occurred while installing the modules.'" ^
|
||||
"}" ^
|
||||
"}"
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,15 @@
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
|
||||
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
Exit
|
||||
}
|
||||
}
|
||||
|
||||
# Install dependencies if required
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
|
||||
|
||||
Set-DisplayPrimary -DisplayId $disp.DisplayId
|
||||
@@ -0,0 +1,34 @@
|
||||
param(
|
||||
[Parameter(Mandatory, Position = 0)]
|
||||
[ValidateSet(
|
||||
30,
|
||||
60,
|
||||
75,
|
||||
90,
|
||||
120,
|
||||
144,
|
||||
165,
|
||||
240,
|
||||
480,
|
||||
500)]
|
||||
[int]$refreshrate
|
||||
)
|
||||
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" "
|
||||
$MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object { $CommandLine += "-$($_.Key):$($_.Value) " }
|
||||
Start-Process -WorkingDirectory $PSScriptRoot -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# install dependencies if required
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
# Getting the correct display
|
||||
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
|
||||
|
||||
# Setting the refresh rate on the correct display.
|
||||
Set-DisplayRefreshRate -DisplayId $disp.DisplayId -RefreshRate $rate
|
||||
@@ -0,0 +1,42 @@
|
||||
param(
|
||||
[Parameter(Mandatory, Position = 0)]
|
||||
[ValidateSet(90, 180, 270)]
|
||||
[int]$rotate
|
||||
)
|
||||
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" "
|
||||
$MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object { $CommandLine += "-$($_.Key):$($_.Value) " }
|
||||
Start-Process -WorkingDirectory $PSScriptRoot -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# install dependencies if required.
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
switch ($rotate) {
|
||||
90 {
|
||||
$degree = "Rotate90"
|
||||
continue
|
||||
}
|
||||
180 {
|
||||
$degree = "Rotate180"
|
||||
continue
|
||||
}
|
||||
270 {
|
||||
$degree = "Rotate270"
|
||||
continue
|
||||
}
|
||||
default { Write-Error "Invalid rotation angle(valid 90,180,270)."; break }
|
||||
}
|
||||
|
||||
|
||||
# Getting the correct display
|
||||
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
|
||||
|
||||
# Setting the resolution on the correct display.
|
||||
Set-DisplayRotation -DisplayId $disp.DisplayId -Rotation $degree
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
[CmdletBinding(DefaultParameterSetName = "UserDefined")]
|
||||
param(
|
||||
[Parameter(Mandatory, Position = 0, ParameterSetName = "UserDefined")]
|
||||
[ValidateSet("100", "125", "150", "175", "200", "225", "250", "300", "350", "400", "450", "500")]
|
||||
[int]$scale,
|
||||
|
||||
[Parameter(Mandatory, ParameterSetName = "Recommended")]
|
||||
[switch]$reset
|
||||
)
|
||||
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" "
|
||||
$MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object { $CommandLine += "-$($_.Key):$($_.Value) " }
|
||||
Start-Process -WorkingDirectory $PSScriptRoot -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# Install dependencies if required.
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
# Getting the correct display
|
||||
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
|
||||
|
||||
$maxscale = Get-DisplayScale -DisplayId $disp.DisplayId | Select-Object -ExpandProperty MaxScale
|
||||
if ( $PSCmdlet.ParameterSetName -eq "UserDefined" ) {
|
||||
Write-Host "Setting scale to $scale"
|
||||
if ( $scale -le $maxscale ) {
|
||||
Set-DisplayScale -DisplayId $disp.DisplayId -Scale $scale
|
||||
}
|
||||
else {
|
||||
Write-Error "Scale percentage $scale is higher than max scale $maxscale"
|
||||
}
|
||||
}
|
||||
elseif ( $PSCmdlet.ParameterSetName -eq "Recommended" ) {
|
||||
Set-DisplayScale -DisplayId $disp.DisplayId -Recommended
|
||||
}
|
||||
else {
|
||||
Write-Error "Invalid arguments: 'reset' or a valid percentage value like 150 is acceptable."
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
# Define the repository name and URL
|
||||
$repo = @{Name = "PSGallery"; Url = "https://www.powershellgallery.com/api/v2" }
|
||||
|
||||
# Define the requred modules and their required versions BEFORE using them
|
||||
$modules = @(
|
||||
@{
|
||||
Name = "DisplayConfig"
|
||||
Version = "1.1.1"
|
||||
},
|
||||
@{
|
||||
Name = "MonitorConfig"
|
||||
Version = "1.0.3"
|
||||
}
|
||||
)
|
||||
Write-Output "resolving dependencies"
|
||||
|
||||
# Check if the repository is registered
|
||||
if (-not (Get-PSRepository -Name $repo.Name -ErrorAction SilentlyContinue)) {
|
||||
Write-Host "PSRepository '$($repo.Name)' cannot be found. Make sure it is available."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Trust the repository (this sets the installation policy to Trusted)
|
||||
Set-PSRepository -Name $repo.Name -InstallationPolicy Trusted `
|
||||
-InformationAction Ignore -WarningAction SilentlyContinue
|
||||
|
||||
# Loop through the modules and ensure they are imported & installed
|
||||
foreach ($m in $modules) {
|
||||
|
||||
# If the module is already imported, continue to the next module
|
||||
if (Get-Module -Name $m.Name) {
|
||||
Write-Output "$($m.Name) is imported."
|
||||
continue
|
||||
}
|
||||
|
||||
# If the module is available on disk then import it
|
||||
elseif (Get-Module -ListAvailable -Name $m.Name) {
|
||||
Write-Output "$($m.Name) is installed but not imported: import."
|
||||
Import-Module $m.Name
|
||||
}
|
||||
else {
|
||||
# If the module is not on disk, check if it's available in the online gallery
|
||||
if (Find-Module -Name $m.Name -ErrorAction SilentlyContinue) {
|
||||
Write-Output "$($m.Name) is available online, but not installed or imported: install and import."
|
||||
# Install the module (specifying the required version)
|
||||
Install-Module -Name $m.Name -RequiredVersion $m.Version `
|
||||
-Force -Scope CurrentUser -AllowClobber
|
||||
|
||||
# Import the module after installation
|
||||
Import-Module $m.Name
|
||||
}
|
||||
else {
|
||||
# If the module cannot be found in the online gallery, abort the script.
|
||||
Write-Output "Module '$($m.Name)' is not imported, not available on disk, and not found in the online gallery. Cannot run the script."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
# Save Module for later use
|
||||
if (-not (Get-InstalledModule -Name $m.Name -MinimumVersion $m.Version -ErrorAction SilentlyContinue)) {
|
||||
Write-Output "Saving module $($m.Name)."
|
||||
Save-Module -Name $m.Name -Repository $repo.Name -RequiredVersion $m.Version `
|
||||
-Confirm:$false -InformationAction Ignore -WarningAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
# Run this script in a powershell with administrator rights (run as administrator)
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
# Latest stable version of NefCon installer
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$NefConURL = "https://github.com/nefarius/nefcon/releases/download/v1.14.0/nefcon_v1.14.0.zip",
|
||||
|
||||
# Latest stable version of VDD driver only
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$DriverURL = "https://github.com/VirtualDrivers/Virtual-Display-Driver/releases/download/25.7.23/VirtualDisplayDriver-x86.Driver.Only.zip"
|
||||
);
|
||||
|
||||
# Create temp directory
|
||||
$tempDir = Join-Path $env:TEMP "VDDInstall";
|
||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null;
|
||||
|
||||
# Download and unzip NefCon
|
||||
Write-Host "Downloading and extracting NefCon..." -ForegroundColor Cyan;
|
||||
$NefConZipPath = Join-Path $tempDir "nefcon.zip";
|
||||
Invoke-WebRequest -Uri $NefConURL -OutFile $NefConZipPath -UseBasicParsing -ErrorAction Stop;
|
||||
Expand-Archive -Path $NefConZipPath -DestinationPath $tempDir -Force -ErrorAction Stop;
|
||||
$NefConExe = Join-Path $tempDir "x64\nefconw.exe";
|
||||
|
||||
# Download and unzip VDD
|
||||
Write-Host "Downloading and extracting VDD..." -ForegroundColor Cyan;
|
||||
$driverZipPath = Join-Path $tempDir 'driver.zip';
|
||||
Invoke-WebRequest -Uri $DriverURL -OutFile $driverZipPath;
|
||||
Expand-Archive -Path $driverZipPath -DestinationPath $tempDir -Force;
|
||||
|
||||
# Extract the SignPath certificates
|
||||
Write-Host "Extracting SignPath certificates..." -ForegroundColor Cyan;
|
||||
$catFile = Join-Path $tempDir 'VirtualDisplayDriver\mttvdd.cat';
|
||||
$catBytes = [System.IO.File]::ReadAllBytes($catFile);
|
||||
$certificates = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection;
|
||||
$certificates.Import($catBytes);
|
||||
|
||||
# Create the temp directory for certificates
|
||||
$certsFolder = Join-Path $tempDir "ExportedCerts";
|
||||
New-Item -ItemType Directory -Path $certsFolder -Force | Out-Null;
|
||||
|
||||
# Write and store the driver certificates on local machine
|
||||
Write-Host "Installing driver certificates on local machine." -ForegroundColor Cyan;
|
||||
foreach ($cert in $certificates) {
|
||||
$certFilePath = Join-Path -Path $certsFolder -ChildPath "$($cert.Thumbprint).cer";
|
||||
$cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert) | Set-Content -Path $certFilePath -Encoding Byte;
|
||||
Import-Certificate -FilePath $certFilePath -CertStoreLocation "Cert:\LocalMachine\TrustedPublisher";
|
||||
}
|
||||
|
||||
# Install VDD
|
||||
Write-Host "Installing Virtual Display Driver silently..." -ForegroundColor Cyan;
|
||||
Push-Location $tempDir;
|
||||
& $NefConExe install .\VirtualDisplayDriver\MttVDD.inf "Root\MttVDD";
|
||||
Pop-Location;
|
||||
|
||||
Write-Host "Driver installation completed." -ForegroundColor Green;
|
||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue;
|
||||
@@ -1,3 +1,4 @@
|
||||
# submitted by zjoasan
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
@@ -7,7 +8,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$device = get-pnpdevice -class Display -FriendlyName 'IddSampleDriver Device HDR' -ErrorAction SilentlyContinue
|
||||
$device = Get-PnpDevice -Class Display -ErrorAction SilentlyContinue | Where-Object { $_.FriendlyName -eq 'IddSampleDriver Device HDR' -or $_.FriendlyName -eq 'Virtual Display Driver' }
|
||||
|
||||
if ($device) {
|
||||
if ($device.Status -eq 'OK') {
|
||||
@@ -0,0 +1,402 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
A comprehensive script to manage the Virtual Display Driver.
|
||||
It can install, uninstall, enable, disable, toggle, and check the status of the driver.
|
||||
|
||||
.DESCRIPTION
|
||||
This script handles the full lifecycle of the Virtual Display Driver.
|
||||
- If no action is specified, it interactively prompts the user to select one.
|
||||
- For install/uninstall, it automatically resolves the correct version of Microsoft's DevCon utility using a nearest-build matching algorithm for maximum compatibility.
|
||||
- For enable/disable/toggle/status, it uses fast, built-in PowerShell commands.
|
||||
- It requires Administrator privileges and will self-elevate if needed by re-launching in a new window.
|
||||
- All temporary files are automatically cleaned up unless in Verbose mode for diagnostics.
|
||||
|
||||
.PARAMETER Action
|
||||
Specifies the operation to perform. If omitted, the script will prompt for a selection.
|
||||
|
||||
.PARAMETER DriverVersion
|
||||
Used only with the 'install' action to specify a version of the Virtual Display Driver, otherwise defaults to 'latest'.
|
||||
|
||||
.PARAMETER Json
|
||||
If present, all output will be in JSON format for easy parsing by other programs.
|
||||
|
||||
.PARAMETER Silent
|
||||
If present, the script will close automatically without prompting for a key press. By default, the script will pause for review before closing.
|
||||
|
||||
.PARAMETER Verbose
|
||||
If present, prints detailed diagnostic information and prevents the temporary folder from being deleted for inspection. Provided by [CmdletBinding()].
|
||||
|
||||
.EXAMPLE
|
||||
# --- USAGE WITHIN A POWERSHELL CONSOLE ---
|
||||
|
||||
# Run without an action to get an interactive menu. The window will pause when finished.
|
||||
.\virtual-driver-manager.ps1
|
||||
|
||||
# Install the driver and pause for review afterwards (default behavior).
|
||||
.\virtual-driver-manager.ps1 -Action install
|
||||
|
||||
# Uninstall the driver and close the window automatically.
|
||||
.\virtual-driver-manager.ps1 -Action uninstall -Silent
|
||||
|
||||
.EXAMPLE
|
||||
# --- USAGE FROM CMD.EXE OR ANOTHER PROCESS ---
|
||||
|
||||
# Check driver status and get JSON output for automation (no pause).
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\virtual-driver-manager.ps1 -Action status -Json
|
||||
|
||||
# Enable the driver and have the window close automatically.
|
||||
powershell.exe -ExecutionPolicy Bypass -File .\virtual-driver-manager.ps1 -Action enable -Silent
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess = $true)]
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet('install', 'uninstall', 'enable', 'disable', 'toggle', 'status')]
|
||||
[string]$Action,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$DriverVersion = "latest",
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$Json,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$Silent
|
||||
)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# SECTION 1: CENTRALIZED LOGGING FUNCTION
|
||||
#----------------------------------------------------------------------
|
||||
# This helper function centralizes all script output.
|
||||
# It supports both colorful console output for humans and JSON for automation.
|
||||
function Write-Log {
|
||||
param(
|
||||
[string]$Message,
|
||||
[string]$Status = 'Info',
|
||||
[string]$Color = 'Cyan'
|
||||
)
|
||||
|
||||
if ($Json.IsPresent) {
|
||||
$logObject = [PSCustomObject]@{
|
||||
status = $Status.ToLower()
|
||||
message = $Message
|
||||
}
|
||||
$logObject | ConvertTo-Json -Compress | Write-Output
|
||||
}
|
||||
else {
|
||||
switch ($Status) {
|
||||
'Success' { Write-Host $Message -ForegroundColor Green }
|
||||
'Warning' { Write-Warning $Message }
|
||||
'Error' { Write-Error $Message }
|
||||
default { Write-Host $Message -ForegroundColor $Color }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# SECTION 2: INTERACTIVE ACTION PROMPT (IF NEEDED)
|
||||
#----------------------------------------------------------------------
|
||||
# If no action is specified, prompt the user to select one.
|
||||
# This must happen before the self-elevation check so the chosen action is passed to the elevated process.
|
||||
if (-not $PSBoundParameters.ContainsKey('Action')) {
|
||||
# Prompts are not suitable for automation or non-interactive shells.
|
||||
if ($Json.IsPresent -or ($host.UI.RawUI -eq $null)) {
|
||||
Write-Log -Message "The -Action parameter is mandatory for non-interactive or JSON mode execution." -Status 'Error'
|
||||
exit 1
|
||||
}
|
||||
|
||||
$options = 'install', 'uninstall', 'enable', 'disable', 'toggle', 'status'
|
||||
Write-Host "`nPlease select an action to perform:" -ForegroundColor Yellow
|
||||
|
||||
for ($i = 0; $i -lt $options.Length; $i++) {
|
||||
Write-Host (" [{0}] {1}" -f ($i + 1), (Get-Culture).TextInfo.ToTitleCase($options[$i]))
|
||||
}
|
||||
|
||||
[int]$choice = 0
|
||||
while ($choice -lt 1 -or $choice -gt $options.Length) {
|
||||
$input = Read-Host -Prompt "`nEnter the number for your choice"
|
||||
if (-not ([int]::TryParse($input, [ref]$choice))) {
|
||||
$choice = 0 # Invalidate if input is not a number
|
||||
}
|
||||
}
|
||||
# Set the action from the user's choice and add it to PSBoundParameters.
|
||||
# This is critical to ensure the self-elevation logic works correctly.
|
||||
$Action = $options[$choice - 1]
|
||||
$PSBoundParameters.Add('Action', $Action) | Out-Null
|
||||
Write-Verbose "User selected action: '$Action'"
|
||||
Write-Host "" # Add a newline for better formatting
|
||||
}
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# SECTION 3: SELF-ELEVATE TO ADMINISTRATOR
|
||||
#----------------------------------------------------------------------
|
||||
# Check if the current user has Administrator rights.
|
||||
if (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) {
|
||||
Write-Log -Message "Administrator rights are required. Requesting elevation..." -Status 'Warning'
|
||||
|
||||
# The script must re-launch itself as an Administrator to function.
|
||||
# We must rebuild the argument list to pass all original parameters to the new elevated process.
|
||||
$psArgs = @("-ExecutionPolicy", "Bypass", "-NoProfile", "-File", "`"$($MyInvocation.MyCommand.Path)`"")
|
||||
|
||||
foreach ($key in $PSBoundParameters.Keys) {
|
||||
$psArgs += "-$key"
|
||||
# Parameters with values (e.g., -Action 'install') need their value added.
|
||||
# Switch parameters (e.g., -Json, -Verbose, -Silent) do not have a value.
|
||||
if (-not ($PSBoundParameters[$key] -is [System.Management.Automation.SwitchParameter])) {
|
||||
$psArgs += $PSBoundParameters[$key]
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Re-launching with arguments: $($psArgs -join ' ')"
|
||||
|
||||
# Start the new process with the 'Runas' verb to trigger the UAC elevation prompt.
|
||||
$elevatedProcess = Start-Process "powershell.exe" -ArgumentList $psArgs -Verb Runas -Wait -PassThru
|
||||
|
||||
# Pass the exit code from the elevated process back to the original caller.
|
||||
$ActionTitleCase = (Get-Culture).TextInfo.ToTitleCase($Action)
|
||||
if ($elevatedProcess.ExitCode -eq 0) { Write-Log -Message "$ActionTitleCase Succeeded." -Status 'Success' }
|
||||
else { Write-Log -Message "$ActionTitleCase Failed. See the elevated window for details." -Status 'Error' }
|
||||
exit $elevatedProcess.ExitCode
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# SECTION 4: SETUP AND GUARANTEED CLEANUP
|
||||
#----------------------------------------------------------------------
|
||||
# Create a unique temporary directory to avoid conflicts if the script is run multiple times concurrently.
|
||||
$tempDir = Join-Path $env:TEMP "VDD-Manager-$(Get-Random)"
|
||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||
Write-Verbose "Created temporary directory at $tempDir"
|
||||
|
||||
# Use a try/catch/finally block to ensure that no matter what happens (success or error),
|
||||
# the 'finally' block will ALWAYS run to clean up temporary files.
|
||||
try {
|
||||
Write-Verbose "Script running with Administrator privileges."
|
||||
Write-Verbose "Parameters: -Action $Action -DriverVersion $DriverVersion -Json:$($Json.IsPresent) -Silent:$($Silent.IsPresent)"
|
||||
|
||||
# Technical Choice: Force PowerShell to use modern TLS 1.2 for all web requests.
|
||||
# This is critical for communicating with modern secure sites like GitHub.
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
Write-Verbose "Set security protocol to TLS 1.2 for all web requests."
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# SECTION 5: HELPER FUNCTION TO FIND THE DEVICE
|
||||
#----------------------------------------------------------------------
|
||||
function Get-VirtualDisplayDevice {
|
||||
# Find the device by its user-friendly name first for readability.
|
||||
$device = Get-PnpDevice -Class Display -ErrorAction Silentlycontinue | Where-Object {
|
||||
$_.FriendlyName -in ('IddSampleDriver Device HDR', 'Virtual Display Driver')
|
||||
}
|
||||
# Fallback: If not found by name, use the more specific and stable Hardware ID.
|
||||
if (-not $device) {
|
||||
$device = Get-PnpDevice -HardwareID "Root\MttVDD" -ErrorAction Silentlycontinue
|
||||
}
|
||||
return $device
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# SECTION 6: MAIN ACTION LOGIC
|
||||
#----------------------------------------------------------------------
|
||||
if ($Action -in @('install', 'uninstall')) {
|
||||
|
||||
#--- 6a. Automatically Resolve DevCon Hash ---
|
||||
Write-Log -Message "Action '$Action' requires the DevCon utility. Determining correct version..."
|
||||
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
|
||||
$osBuild = [int]$osInfo.BuildNumber
|
||||
|
||||
$osMajorVersion = 'Server'
|
||||
if ($osInfo.Caption -match 'Windows 11') { $osMajorVersion = '11' }
|
||||
elseif ($osInfo.Caption -match 'Windows 10') { $osMajorVersion = '10' }
|
||||
|
||||
Write-Log -Message "Detected: Windows $osMajorVersion (Build $osBuild)"
|
||||
Write-Verbose "OS detection complete. Starting DevCon source matching."
|
||||
|
||||
# This map is the core of the matching logic. It translates the human-readable version names
|
||||
# from the devcon_sources.json file into their corresponding OS build numbers for comparison.
|
||||
$versionNameToBuildMap = @{
|
||||
"Windows 11 version 24H2" = 26100; "Windows 11 version 23H2" = 22631; "Windows 11 version 22H2" = 22621;
|
||||
"Windows 11 version 21H2" = 22000; "Windows Server 2022" = 20348; "Windows 10 version 2004" = 19041;
|
||||
"Windows 10 version 1903" = 18362; "Windows 10 version 1809" = 17763; "Windows Server 2019" = 17763
|
||||
}
|
||||
|
||||
$sourcesUrl = "https://raw.githubusercontent.com/Drawbackz/DevCon-Installer/refs/heads/master/devcon_sources.json"
|
||||
Write-Verbose "Fetching DevCon sources from $sourcesUrl"
|
||||
$devconSources = Invoke-RestMethod -Uri $sourcesUrl
|
||||
|
||||
# Enrich the downloaded source list with a calculated 'BuildNumber' property to make it sortable.
|
||||
$enrichedSources = $devconSources | ForEach-Object {
|
||||
$source = $_; $matchedBuild = 0
|
||||
foreach ($entry in $versionNameToBuildMap.GetEnumerator()) {
|
||||
if ($source.Name.Contains($entry.Key)) { $matchedBuild = $entry.Value; break }
|
||||
}
|
||||
$source | Add-Member -MemberType NoteProperty -Name "BuildNumber" -Value $matchedBuild; $source
|
||||
} | Where-Object { $_.BuildNumber -gt 0 }
|
||||
|
||||
$osFamilySources = $enrichedSources | Where-Object { $_.Name -like "*Windows $osMajorVersion*" -or ($osMajorVersion -eq 'Server' -and $_.Name -like "*Server*") }
|
||||
|
||||
# --- NEAREST-BUILD MATCHING LOGIC ---
|
||||
# 1. Try for a perfect match first.
|
||||
$bestMatch = $osFamilySources | Where-Object { $_.BuildNumber -eq $osBuild } | Select-Object -First 1
|
||||
|
||||
if (-not $bestMatch) {
|
||||
Write-Log -Message "No exact DevCon match for build $osBuild. Finding nearest available version..." -Status 'Warning'
|
||||
# 2. If no exact match, find the newest version that is still older than (or equal to) the current OS.
|
||||
# This is the safest fallback, as it guarantees API compatibility.
|
||||
$bestOlderMatch = $osFamilySources | Where-Object { $_.BuildNumber -le $osBuild } | Sort-Object BuildNumber -Descending | Select-Object -First 1
|
||||
|
||||
# 3. If no older versions exist, find the oldest version that is newer than the current OS.
|
||||
# This is a less-safe fallback but better than failing completely.
|
||||
$bestNewerMatch = $osFamilySources | Where-Object { $_.BuildNumber -gt $osBuild } | Sort-Object BuildNumber | Select-Object -First 1
|
||||
|
||||
if ($bestOlderMatch) { $bestMatch = $bestOlderMatch } elseif ($bestNewerMatch) { $bestMatch = $bestNewerMatch }
|
||||
Write-Verbose "Nearest older match: $($bestOlderMatch.Name) | Nearest newer match: $($bestNewerMatch.Name)"
|
||||
}
|
||||
|
||||
if (-not $bestMatch) { throw "Could not find any compatible DevCon versions for your OS (Build $osBuild)." }
|
||||
|
||||
$devconHash = ($bestMatch.Sources | Where-Object { $_.Architecture -eq 'X64' }).Sha256
|
||||
Write-Log -Message "Using DevCon Source: $($bestMatch.Name) (Build $($bestMatch.BuildNumber))" -Status 'Success'
|
||||
Write-Verbose "Selected DevCon Hash (X64): $devconHash"
|
||||
if (-not $devconHash) { throw "Could not find a 64-bit DevCon hash in the selected source: $($bestMatch.Name)" }
|
||||
|
||||
#--- 6b. Acquire DevCon Utility ---
|
||||
Write-Log -Message "Acquiring secure DevCon utility..."
|
||||
$devconInstallerUrl = "https://github.com/Drawbackz/DevCon-Installer/releases/download/1.4-rc/Devcon.Installer.exe"
|
||||
$devconInstallerPath = Join-Path $tempDir "Devcon.Installer.exe"
|
||||
Write-Verbose "Downloading DevCon Installer from $devconInstallerUrl"
|
||||
Invoke-WebRequest -Uri $devconInstallerUrl -OutFile $devconInstallerPath
|
||||
Write-Verbose "DevCon Installer downloaded successfully."
|
||||
|
||||
# Use the hash to ensure the DevCon-Installer utility downloads the correct, secure version of DevCon.
|
||||
$devconArgs = "install -hash $devconHash -update -dir `"$tempDir`""
|
||||
Write-Verbose "Running DevCon Installer with arguments: $devconArgs"
|
||||
Start-Process -FilePath $devconInstallerPath -ArgumentList $devconArgs -Wait -NoNewWindow
|
||||
|
||||
$devconExe = Join-Path $tempDir "devcon.exe"
|
||||
if (-not (Test-Path $devconExe)) { throw "Failed to acquire devcon.exe." }
|
||||
Write-Verbose "devcon.exe acquired successfully at $devconExe"
|
||||
|
||||
#--- 6c. Execute Install or Uninstall ---
|
||||
if ($Action -eq 'install') {
|
||||
Write-Log -Message "Starting driver installation..."
|
||||
$downloadUrl = $null
|
||||
if ($DriverVersion -eq "latest") {
|
||||
$apiUrl = "https://api.github.com/repos/VirtualDrivers/Virtual-Display-Driver/releases/latest"
|
||||
# Technical Choice: Many APIs, including GitHub's, require a User-Agent header.
|
||||
# Omitting this can lead to connection errors (like 403 Forbidden or 404 Not Found).
|
||||
$headers = @{ "User-Agent" = "PowerShell-VDD-Manager-Script" }
|
||||
|
||||
Write-Verbose "Querying GitHub API for latest driver release: $apiUrl"
|
||||
$releaseInfo = Invoke-RestMethod -Uri $apiUrl -Headers $headers
|
||||
Write-Verbose "API call successful. Latest release found: $($releaseInfo.tag_name)"
|
||||
|
||||
$asset = $releaseInfo.assets | Where-Object { $_.name -match "x64\.zip$" } | Select-Object -First 1
|
||||
if (-not $asset) { throw "Could not find a 64-bit driver asset (x64.zip) in the latest GitHub release." }
|
||||
|
||||
$downloadUrl = $asset.browser_download_url
|
||||
Write-Verbose "Found driver asset: $($asset.name)"
|
||||
}
|
||||
else {
|
||||
$downloadUrl = "https://github.com/VirtualDrivers/Virtual-Display-Driver/releases/download/$DriverVersion/Signed-Driver-v$DriverVersion-x64.zip"
|
||||
Write-Verbose "Using specified driver version: $DriverVersion"
|
||||
}
|
||||
|
||||
if (-not $downloadUrl) { throw "Could not determine a valid driver download URL for version '$DriverVersion'." }
|
||||
|
||||
Write-Verbose "Downloading driver from URL: $downloadUrl"
|
||||
$driverZipPath = Join-Path $tempDir "driver.zip"
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile $driverZipPath
|
||||
Write-Verbose "Driver ZIP file downloaded to $driverZipPath"
|
||||
|
||||
Expand-Archive -Path $driverZipPath -DestinationPath $tempDir -Force
|
||||
Write-Verbose "Driver archive expanded."
|
||||
|
||||
# Use DevCon to install the driver by pointing to its INF file and specifying its unique Hardware ID.
|
||||
# "Root\MttVDD" identifies this as a root-enumerated virtual device.
|
||||
Write-Verbose "Running DevCon to install the driver..."
|
||||
& $devconExe install (Join-Path $tempDir "MttVDD.inf") "Root\MttVDD"
|
||||
}
|
||||
else { # Action must be 'uninstall'
|
||||
Write-Log -Message "Starting driver uninstallation..."
|
||||
if (Get-VirtualDisplayDevice) {
|
||||
Write-Verbose "Driver found. Preparing to remove."
|
||||
& $devconExe remove "Root\MttVDD"
|
||||
}
|
||||
else { Write-Log -Message "Driver is not currently installed. Nothing to do." }
|
||||
}
|
||||
}
|
||||
elseif ($Action -in @('enable', 'disable', 'toggle')) {
|
||||
$device = Get-VirtualDisplayDevice
|
||||
if (-not $device) { Write-Log -Message "Device not found. Cannot perform '$Action'. Please install the driver first." -Status 'Warning' }
|
||||
elseif ($Action -eq 'enable') { Write-Log -Message "Enabling device: $($device.FriendlyName)..."; $device | Enable-PnpDevice -Confirm:$false }
|
||||
elseif ($Action -eq 'disable') { Write-Log -Message "Disabling device: $($device.FriendlyName)..."; $device | Disable-PnpDevice -Confirm:$false }
|
||||
elseif ($Action -eq 'toggle') {
|
||||
if ($device.Status -in ('OK', 'Degraded', 'Started')) {
|
||||
Write-Log -Message "Device is currently enabled. Disabling..."; $device | Disable-PnpDevice -Confirm:$false
|
||||
}
|
||||
else { Write-Log -Message "Device is currently disabled or in an error state. Enabling..."; $device | Enable-PnpDevice -Confirm:$false }
|
||||
}
|
||||
}
|
||||
elseif ($Action -eq 'status') {
|
||||
Write-Log -Message "Checking driver status..."
|
||||
$device = Get-VirtualDisplayDevice
|
||||
|
||||
$statusResult = [ordered]@{
|
||||
installed = $false
|
||||
status = "not installed"
|
||||
}
|
||||
|
||||
if ($device) {
|
||||
$isEnabled = ($device.Status -in ('OK', 'Degraded', 'Started'))
|
||||
$statusText = if ($isEnabled) { "Enabled" } else { "Disabled" }
|
||||
|
||||
$statusResult.installed = $true
|
||||
$statusResult.status = $statusText.ToLower()
|
||||
$statusResult.details = @{
|
||||
friendlyName = $device.FriendlyName
|
||||
instanceId = $device.InstanceId
|
||||
pnpDeviceID = $device.PNPDeviceID
|
||||
}
|
||||
$message = "Driver is installed. Status: $statusText."
|
||||
}
|
||||
else {
|
||||
$message = "Driver is not installed."
|
||||
}
|
||||
|
||||
if ($Json.IsPresent) {
|
||||
# For 'status', the JSON object is the primary output, bypassing the standard log format.
|
||||
$statusResult | ConvertTo-Json -Compress | Write-Output
|
||||
}
|
||||
else {
|
||||
Write-Log -Message $message
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log -Message "Operation '$Action' completed successfully." -Status 'Success'
|
||||
}
|
||||
catch {
|
||||
# The 'catch' block will execute if any command in the 'try' block throws an error.
|
||||
$errorMessage = "An error occurred during the '$Action' operation: $($_.Exception.Message) `nAt line: $($_.InvocationInfo.ScriptLineNumber)"
|
||||
Write-Log -Message $errorMessage -Status 'Error'
|
||||
exit 1
|
||||
}
|
||||
finally {
|
||||
# This block ALWAYS runs, ensuring cleanup happens after success or failure.
|
||||
# If the user ran with -Verbose, we assume they are debugging.
|
||||
# We will NOT delete the temporary folder so they can inspect its contents.
|
||||
if ($PSBoundParameters.ContainsKey('Verbose')) {
|
||||
Write-Verbose "Verbose mode is active. Temporary directory will not be deleted so you can inspect its contents: $tempDir"
|
||||
}
|
||||
else {
|
||||
if (Test-Path $tempDir) {
|
||||
# This Write-Verbose message will not be visible without -Verbose, but is good practice.
|
||||
Write-Verbose "Cleaning up temporary directory: $tempDir"
|
||||
Remove-Item -Path $tempDir -Recurse -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Add a final pause unless in Silent or JSON mode so the user can see the output.
|
||||
if (-not $Silent.IsPresent -and -not $Json.IsPresent) {
|
||||
Write-Host ""; Write-Host "Press any key to exit..." -ForegroundColor Gray
|
||||
[System.Console]::ReadKey($true) | Out-Null
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Self-elevate the script if required
|
||||
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" "
|
||||
$MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object { $CommandLine += "-$($_.Key):$($_.Value) " }
|
||||
Start-Process -WorkingDirectory $PSScriptRoot -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
# install dependencies if required
|
||||
. "$PSScriptRoot\set-dependencies.ps1"
|
||||
|
||||
$profi = Get-DisplayProfile
|
||||
|
||||
if ( $profi -eq "Extend" ) {
|
||||
Set-DisplayProfile Clone
|
||||
break
|
||||
}
|
||||
if ( $profi -eq "Clone" ) {
|
||||
Set-DisplayProfile Extend
|
||||
break
|
||||
}
|
||||
@@ -1,899 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains a sample implementation of an indirect display driver. See the included README.md file and the
|
||||
various TODO blocks throughout this file and all accompanying files for information on building a production driver.
|
||||
|
||||
MSDN documentation on indirect displays can be found at https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx.
|
||||
|
||||
Environment:
|
||||
|
||||
User Mode, UMDF
|
||||
|
||||
--*/
|
||||
|
||||
#include "Driver.h"
|
||||
//#include "Driver.tmh"
|
||||
#include<fstream>
|
||||
#include<sstream>
|
||||
#include<string>
|
||||
#include<tuple>
|
||||
#include<vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace Microsoft::IndirectDisp;
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
extern "C" DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
EVT_WDF_DRIVER_DEVICE_ADD IddSampleDeviceAdd;
|
||||
EVT_WDF_DEVICE_D0_ENTRY IddSampleDeviceD0Entry;
|
||||
|
||||
EVT_IDD_CX_ADAPTER_INIT_FINISHED IddSampleAdapterInitFinished;
|
||||
EVT_IDD_CX_ADAPTER_COMMIT_MODES IddSampleAdapterCommitModes;
|
||||
|
||||
EVT_IDD_CX_PARSE_MONITOR_DESCRIPTION IddSampleParseMonitorDescription;
|
||||
EVT_IDD_CX_MONITOR_GET_DEFAULT_DESCRIPTION_MODES IddSampleMonitorGetDefaultModes;
|
||||
EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES IddSampleMonitorQueryModes;
|
||||
|
||||
EVT_IDD_CX_MONITOR_ASSIGN_SWAPCHAIN IddSampleMonitorAssignSwapChain;
|
||||
EVT_IDD_CX_MONITOR_UNASSIGN_SWAPCHAIN IddSampleMonitorUnassignSwapChain;
|
||||
|
||||
EVT_IDD_CX_ADAPTER_QUERY_TARGET_INFO IddSampleEvtIddCxAdapterQueryTargetInfo;
|
||||
EVT_IDD_CX_MONITOR_SET_DEFAULT_HDR_METADATA IddSampleEvtIddCxMonitorSetDefaultHdrMetadata;
|
||||
EVT_IDD_CX_PARSE_MONITOR_DESCRIPTION2 IddSampleEvtIddCxParseMonitorDescription2;
|
||||
EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES2 IddSampleEvtIddCxMonitorQueryTargetModes2;
|
||||
EVT_IDD_CX_ADAPTER_COMMIT_MODES2 IddSampleEvtIddCxAdapterCommitModes2;
|
||||
|
||||
EVT_IDD_CX_MONITOR_SET_GAMMA_RAMP IddSampleEvtIddCxMonitorSetGammaRamp;
|
||||
|
||||
vector<tuple<int, int, int>> monitorModes;
|
||||
vector< DISPLAYCONFIG_VIDEO_SIGNAL_INFO> s_KnownMonitorModes2;
|
||||
UINT numVirtualDisplays;
|
||||
|
||||
struct IndirectDeviceContextWrapper
|
||||
{
|
||||
IndirectDeviceContext* pContext;
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
delete pContext;
|
||||
pContext = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// This macro creates the methods for accessing an IndirectDeviceContextWrapper as a context for a WDF object
|
||||
WDF_DECLARE_CONTEXT_TYPE(IndirectDeviceContextWrapper);
|
||||
|
||||
extern "C" BOOL WINAPI DllMain(
|
||||
_In_ HINSTANCE hInstance,
|
||||
_In_ UINT dwReason,
|
||||
_In_opt_ LPVOID lpReserved)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hInstance);
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
UNREFERENCED_PARAMETER(dwReason);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
extern "C" NTSTATUS DriverEntry(
|
||||
PDRIVER_OBJECT pDriverObject,
|
||||
PUNICODE_STRING pRegistryPath
|
||||
)
|
||||
{
|
||||
WDF_DRIVER_CONFIG Config;
|
||||
NTSTATUS Status;
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES Attributes;
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
|
||||
|
||||
WDF_DRIVER_CONFIG_INIT(&Config,
|
||||
IddSampleDeviceAdd
|
||||
);
|
||||
|
||||
Status = WdfDriverCreate(pDriverObject, pRegistryPath, &Attributes, &Config, WDF_NO_HANDLE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
vector<string> split(string& input, char delimiter)
|
||||
{
|
||||
istringstream stream(input);
|
||||
string field;
|
||||
vector<string> result;
|
||||
while (getline(stream, field, delimiter)) {
|
||||
result.push_back(field);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void loadOptions(string filepath) {
|
||||
ifstream ifs(filepath);
|
||||
|
||||
string line;
|
||||
vector<tuple<int, int, int>> res;
|
||||
getline(ifs, line);//num of displays
|
||||
numVirtualDisplays = stoi(line);
|
||||
while (getline(ifs, line)) {
|
||||
vector<string> strvec = split(line, ',');
|
||||
if (strvec.size() == 3 && strvec[0].substr(0, 1) != "#") {
|
||||
res.push_back({ stoi(strvec[0]),stoi(strvec[1]),stoi(strvec[2]) });
|
||||
}
|
||||
}
|
||||
monitorModes = res; return;
|
||||
}
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT pDeviceInit)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
|
||||
|
||||
UNREFERENCED_PARAMETER(Driver);
|
||||
|
||||
// Register for power callbacks - in this sample only power-on is needed
|
||||
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
|
||||
PnpPowerCallbacks.EvtDeviceD0Entry = IddSampleDeviceD0Entry;
|
||||
WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &PnpPowerCallbacks);
|
||||
|
||||
IDD_CX_CLIENT_CONFIG IddConfig;
|
||||
IDD_CX_CLIENT_CONFIG_INIT(&IddConfig);
|
||||
|
||||
// If the driver wishes to handle custom IoDeviceControl requests, it's necessary to use this callback since IddCx
|
||||
// redirects IoDeviceControl requests to an internal queue. This sample does not need this.
|
||||
// IddConfig.EvtIddCxDeviceIoControl = IddSampleIoDeviceControl;
|
||||
loadOptions("C:\\IddSampleDriver\\option.txt");
|
||||
IddConfig.EvtIddCxAdapterInitFinished = IddSampleAdapterInitFinished;
|
||||
|
||||
IddConfig.EvtIddCxMonitorGetDefaultDescriptionModes = IddSampleMonitorGetDefaultModes;
|
||||
IddConfig.EvtIddCxMonitorAssignSwapChain = IddSampleMonitorAssignSwapChain;
|
||||
IddConfig.EvtIddCxMonitorUnassignSwapChain = IddSampleMonitorUnassignSwapChain;
|
||||
|
||||
if (IDD_IS_FIELD_AVAILABLE(IDD_CX_CLIENT_CONFIG, EvtIddCxAdapterQueryTargetInfo))
|
||||
{
|
||||
IddConfig.EvtIddCxAdapterQueryTargetInfo = IddSampleEvtIddCxAdapterQueryTargetInfo;
|
||||
IddConfig.EvtIddCxMonitorSetDefaultHdrMetaData = IddSampleEvtIddCxMonitorSetDefaultHdrMetadata;
|
||||
IddConfig.EvtIddCxParseMonitorDescription2 = IddSampleEvtIddCxParseMonitorDescription2;
|
||||
IddConfig.EvtIddCxMonitorQueryTargetModes2 = IddSampleEvtIddCxMonitorQueryTargetModes2;
|
||||
IddConfig.EvtIddCxAdapterCommitModes2 = IddSampleEvtIddCxAdapterCommitModes2;
|
||||
IddConfig.EvtIddCxMonitorSetGammaRamp = IddSampleEvtIddCxMonitorSetGammaRamp;
|
||||
}
|
||||
else {
|
||||
IddConfig.EvtIddCxParseMonitorDescription = IddSampleParseMonitorDescription;
|
||||
IddConfig.EvtIddCxMonitorQueryTargetModes = IddSampleMonitorQueryModes;
|
||||
IddConfig.EvtIddCxAdapterCommitModes = IddSampleAdapterCommitModes;
|
||||
}
|
||||
|
||||
Status = IddCxDeviceInitConfig(pDeviceInit, &IddConfig);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES Attr;
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
|
||||
Attr.EvtCleanupCallback = [](WDFOBJECT Object)
|
||||
{
|
||||
// Automatically cleanup the context when the WDF object is about to be deleted
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Object);
|
||||
if (pContext)
|
||||
{
|
||||
pContext->Cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
WDFDEVICE Device = nullptr;
|
||||
Status = WdfDeviceCreate(&pDeviceInit, &Attr, &Device);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IddCxDeviceInitialize(Device);
|
||||
|
||||
// Create a new device context object and attach it to the WDF device object
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
|
||||
pContext->pContext = new IndirectDeviceContext(Device);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PreviousState);
|
||||
|
||||
// This function is called by WDF to start the device in the fully-on power state.
|
||||
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
|
||||
pContext->pContext->InitAdapter();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma region Direct3DDevice
|
||||
|
||||
Direct3DDevice::Direct3DDevice(LUID AdapterLuid) : AdapterLuid(AdapterLuid)
|
||||
{
|
||||
}
|
||||
|
||||
Direct3DDevice::Direct3DDevice()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT Direct3DDevice::Init()
|
||||
{
|
||||
// The DXGI factory could be cached, but if a new render adapter appears on the system, a new factory needs to be
|
||||
// created. If caching is desired, check DxgiFactory->IsCurrent() each time and recreate the factory if !IsCurrent.
|
||||
HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Find the specified render adapter
|
||||
hr = DxgiFactory->EnumAdapterByLuid(AdapterLuid, IID_PPV_ARGS(&Adapter));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Create a D3D device using the render adapter. BGRA support is required by the WHQL test suite.
|
||||
hr = D3D11CreateDevice(Adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &Device, nullptr, &DeviceContext);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// If creating the D3D device failed, it's possible the render GPU was lost (e.g. detachable GPU) or else the
|
||||
// system is in a transient state.
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SwapChainProcessor
|
||||
|
||||
SwapChainProcessor::SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent)
|
||||
: m_hSwapChain(hSwapChain), m_Device(Device), m_hAvailableBufferEvent(NewFrameEvent)
|
||||
{
|
||||
m_hTerminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||
|
||||
// Immediately create and run the swap-chain processing thread, passing 'this' as the thread parameter
|
||||
m_hThread.Attach(CreateThread(nullptr, 0, RunThread, this, 0, nullptr));
|
||||
}
|
||||
|
||||
SwapChainProcessor::~SwapChainProcessor()
|
||||
{
|
||||
// Alert the swap-chain processing thread to terminate
|
||||
SetEvent(m_hTerminateEvent.Get());
|
||||
|
||||
if (m_hThread.Get())
|
||||
{
|
||||
// Wait for the thread to terminate
|
||||
WaitForSingleObject(m_hThread.Get(), INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
DWORD CALLBACK SwapChainProcessor::RunThread(LPVOID Argument)
|
||||
{
|
||||
reinterpret_cast<SwapChainProcessor*>(Argument)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SwapChainProcessor::Run()
|
||||
{
|
||||
// For improved performance, make use of the Multimedia Class Scheduler Service, which will intelligently
|
||||
// prioritize this thread for improved throughput in high CPU-load scenarios.
|
||||
DWORD AvTask = 0;
|
||||
HANDLE AvTaskHandle = AvSetMmThreadCharacteristicsW(L"Distribution", &AvTask);
|
||||
|
||||
RunCore();
|
||||
|
||||
// Always delete the swap-chain object when swap-chain processing loop terminates in order to kick the system to
|
||||
// provide a new swap-chain if necessary.
|
||||
WdfObjectDelete((WDFOBJECT)m_hSwapChain);
|
||||
m_hSwapChain = nullptr;
|
||||
|
||||
AvRevertMmThreadCharacteristics(AvTaskHandle);
|
||||
}
|
||||
|
||||
void SwapChainProcessor::RunCore()
|
||||
{
|
||||
// Get the DXGI device interface
|
||||
ComPtr<IDXGIDevice> DxgiDevice;
|
||||
HRESULT hr = m_Device->Device.As(&DxgiDevice);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IDARG_IN_SWAPCHAINSETDEVICE SetDevice = {};
|
||||
SetDevice.pDevice = DxgiDevice.Get();
|
||||
|
||||
hr = IddCxSwapChainSetDevice(m_hSwapChain, &SetDevice);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Acquire and release buffers in a loop
|
||||
for (;;)
|
||||
{
|
||||
ComPtr<IDXGIResource> AcquiredBuffer;
|
||||
|
||||
// Ask for the next buffer from the producer
|
||||
IDARG_IN_RELEASEANDACQUIREBUFFER2 BufferInArgs = {};
|
||||
BufferInArgs.Size = sizeof(BufferInArgs);
|
||||
IDXGIResource* pSurface;
|
||||
|
||||
if (IDD_IS_FUNCTION_AVAILABLE(IddCxSwapChainReleaseAndAcquireBuffer2)) {
|
||||
IDARG_OUT_RELEASEANDACQUIREBUFFER2 Buffer = {};
|
||||
hr = IddCxSwapChainReleaseAndAcquireBuffer2(m_hSwapChain, &BufferInArgs, &Buffer);
|
||||
pSurface = Buffer.MetaData.pSurface;
|
||||
}
|
||||
else
|
||||
{
|
||||
IDARG_OUT_RELEASEANDACQUIREBUFFER Buffer = {};
|
||||
hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &Buffer);
|
||||
pSurface = Buffer.MetaData.pSurface;
|
||||
}
|
||||
// AcquireBuffer immediately returns STATUS_PENDING if no buffer is yet available
|
||||
if (hr == E_PENDING)
|
||||
{
|
||||
// We must wait for a new buffer
|
||||
HANDLE WaitHandles[] =
|
||||
{
|
||||
m_hAvailableBufferEvent,
|
||||
m_hTerminateEvent.Get()
|
||||
};
|
||||
DWORD WaitResult = WaitForMultipleObjects(ARRAYSIZE(WaitHandles), WaitHandles, FALSE, 16);
|
||||
if (WaitResult == WAIT_OBJECT_0 || WaitResult == WAIT_TIMEOUT)
|
||||
{
|
||||
// We have a new buffer, so try the AcquireBuffer again
|
||||
continue;
|
||||
}
|
||||
else if (WaitResult == WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
// We need to terminate
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The wait was cancelled or something unexpected happened
|
||||
hr = HRESULT_FROM_WIN32(WaitResult);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
AcquiredBuffer.Attach(pSurface);
|
||||
|
||||
// ==============================
|
||||
// TODO: Process the frame here
|
||||
//
|
||||
// This is the most performance-critical section of code in an IddCx driver. It's important that whatever
|
||||
// is done with the acquired surface be finished as quickly as possible. This operation could be:
|
||||
// * a GPU copy to another buffer surface for later processing (such as a staging surface for mapping to CPU memory)
|
||||
// * a GPU encode operation
|
||||
// * a GPU VPBlt to another surface
|
||||
// * a GPU custom compute shader encode operation
|
||||
// ==============================
|
||||
|
||||
AcquiredBuffer.Reset();
|
||||
hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// ==============================
|
||||
// TODO: Report frame statistics once the asynchronous encode/send work is completed
|
||||
//
|
||||
// Drivers should report information about sub-frame timings, like encode time, send time, etc.
|
||||
// ==============================
|
||||
// IddCxSwapChainReportFrameStatistics(m_hSwapChain, ...);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The swap-chain was likely abandoned (e.g. DXGI_ERROR_ACCESS_LOST), so exit the processing loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IndirectDeviceContext
|
||||
|
||||
const UINT64 MHZ = 1000000;
|
||||
const UINT64 KHZ = 1000;
|
||||
|
||||
constexpr DISPLAYCONFIG_VIDEO_SIGNAL_INFO dispinfo(UINT32 h, UINT32 v, UINT32 r) {
|
||||
const UINT32 clock_rate = r * (v + 4) * (v + 4) + 1000;
|
||||
return {
|
||||
clock_rate, // pixel clock rate [Hz]
|
||||
{ clock_rate, v + 4 }, // fractional horizontal refresh rate [Hz]
|
||||
{ clock_rate, (v + 4) * (v + 4) }, // fractional vertical refresh rate [Hz]
|
||||
{ h, v }, // (horizontal, vertical) active pixel resolution
|
||||
{ h + 4, v + 4 }, // (horizontal, vertical) total pixel resolution
|
||||
{ { 255, 0 }}, // video standard and vsync divider
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE
|
||||
};
|
||||
}
|
||||
|
||||
// This is a sample monitor EDID - FOR SAMPLE PURPOSES ONLY
|
||||
const BYTE IndirectDeviceContext::s_KnownMonitorEdid[] =
|
||||
{
|
||||
/* 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x79,0x5E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA6,0x01,0x03,0x80,0x28,
|
||||
0x1E,0x78,0x0A,0xEE,0x91,0xA3,0x54,0x4C,0x99,0x26,0x0F,0x50,0x54,0x20,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xA0,0x0F,0x20,0x00,0x31,0x58,0x1C,0x20,0x28,0x80,0x14,0x00,
|
||||
0x90,0x2C,0x11,0x00,0x00,0x1E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E */
|
||||
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x31, 0xD8, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x1F, 0x01, 0x04, 0xB5, 0x77, 0x22, 0x78,
|
||||
0x3A, 0xC7, 0x25, 0xB1, 0x4B, 0x46, 0xA8, 0x26, 0x0E, 0x50, 0x54, 0x2F,
|
||||
0xCF, 0x00, 0x71, 0x4F, 0x81, 0x00, 0x81, 0xC0, 0x81, 0x80, 0xA9, 0xC0,
|
||||
0xB3, 0x00, 0x95, 0x00, 0xD1, 0xC0, 0x74, 0xD6, 0x00, 0xA0, 0xF0, 0x38,
|
||||
0x40, 0x40, 0x30, 0x20, 0x3A, 0x00, 0xC0, 0x0E, 0x31, 0x00, 0x00, 0x1A,
|
||||
0x00, 0x00, 0x00, 0xFC, 0x00, 0x49, 0x44, 0x44, 0x20, 0x48, 0x44, 0x52,
|
||||
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x85, 0x02, 0x03, 0x15, 0x00,
|
||||
0xE3, 0x05, 0xC0, 0x00, 0xE6, 0x06, 0x05, 0x01, 0x8B, 0x73, 0x02, 0xE5,
|
||||
0x01, 0x8B, 0x84, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xC6
|
||||
};
|
||||
|
||||
IndirectDeviceContext::IndirectDeviceContext(_In_ WDFDEVICE WdfDevice) :
|
||||
m_WdfDevice(WdfDevice)
|
||||
{
|
||||
m_Adapter = {};
|
||||
}
|
||||
|
||||
IndirectDeviceContext::~IndirectDeviceContext()
|
||||
{
|
||||
m_ProcessingThread.reset();
|
||||
}
|
||||
|
||||
#define NUM_VIRTUAL_DISPLAYS 1
|
||||
|
||||
void IndirectDeviceContext::InitAdapter()
|
||||
{
|
||||
// ==============================
|
||||
// TODO: Update the below diagnostic information in accordance with the target hardware. The strings and version
|
||||
// numbers are used for telemetry and may be displayed to the user in some situations.
|
||||
//
|
||||
// This is also where static per-adapter capabilities are determined.
|
||||
// ==============================
|
||||
|
||||
IDDCX_ADAPTER_CAPS AdapterCaps = {};
|
||||
AdapterCaps.Size = sizeof(AdapterCaps);
|
||||
|
||||
if (IDD_IS_FUNCTION_AVAILABLE(IddCxSwapChainReleaseAndAcquireBuffer2)) {
|
||||
AdapterCaps.Flags = IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16;
|
||||
}
|
||||
|
||||
// Declare basic feature support for the adapter (required)
|
||||
AdapterCaps.MaxMonitorsSupported = numVirtualDisplays;
|
||||
AdapterCaps.EndPointDiagnostics.Size = sizeof(AdapterCaps.EndPointDiagnostics);
|
||||
AdapterCaps.EndPointDiagnostics.GammaSupport = IDDCX_FEATURE_IMPLEMENTATION_NONE;
|
||||
AdapterCaps.EndPointDiagnostics.TransmissionType = IDDCX_TRANSMISSION_TYPE_WIRED_OTHER;
|
||||
|
||||
// Declare your device strings for telemetry (required)
|
||||
AdapterCaps.EndPointDiagnostics.pEndPointFriendlyName = L"IddSample Device";
|
||||
AdapterCaps.EndPointDiagnostics.pEndPointManufacturerName = L"Microsoft";
|
||||
AdapterCaps.EndPointDiagnostics.pEndPointModelName = L"IddSample Model";
|
||||
|
||||
// Declare your hardware and firmware versions (required)
|
||||
IDDCX_ENDPOINT_VERSION Version = {};
|
||||
Version.Size = sizeof(Version);
|
||||
Version.MajorVer = 1;
|
||||
AdapterCaps.EndPointDiagnostics.pFirmwareVersion = &Version;
|
||||
AdapterCaps.EndPointDiagnostics.pHardwareVersion = &Version;
|
||||
|
||||
// Initialize a WDF context that can store a pointer to the device context object
|
||||
WDF_OBJECT_ATTRIBUTES Attr;
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
|
||||
|
||||
IDARG_IN_ADAPTER_INIT AdapterInit = {};
|
||||
AdapterInit.WdfDevice = m_WdfDevice;
|
||||
AdapterInit.pCaps = &AdapterCaps;
|
||||
AdapterInit.ObjectAttributes = &Attr;
|
||||
|
||||
// Start the initialization of the adapter, which will trigger the AdapterFinishInit callback later
|
||||
IDARG_OUT_ADAPTER_INIT AdapterInitOut;
|
||||
NTSTATUS Status = IddCxAdapterInitAsync(&AdapterInit, &AdapterInitOut);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
// Store a reference to the WDF adapter handle
|
||||
m_Adapter = AdapterInitOut.AdapterObject;
|
||||
|
||||
// Store the device context object into the WDF object context
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterInitOut.AdapterObject);
|
||||
pContext->pContext = this;
|
||||
}
|
||||
}
|
||||
|
||||
void IndirectDeviceContext::FinishInit()
|
||||
{
|
||||
for (unsigned int i = 0; i < numVirtualDisplays; i++) {
|
||||
CreateMonitor(i);
|
||||
}
|
||||
}
|
||||
|
||||
void IndirectDeviceContext::CreateMonitor(unsigned int index) {
|
||||
// ==============================
|
||||
// TODO: In a real driver, the EDID should be retrieved dynamically from a connected physical monitor. The EDID
|
||||
// provided here is purely for demonstration, as it describes only 640x480 @ 60 Hz and 800x600 @ 60 Hz. Monitor
|
||||
// manufacturers are required to correctly fill in physical monitor attributes in order to allow the OS to optimize
|
||||
// settings like viewing distance and scale factor. Manufacturers should also use a unique serial number every
|
||||
// single device to ensure the OS can tell the monitors apart.
|
||||
// ==============================
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES Attr;
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
|
||||
|
||||
IDDCX_MONITOR_INFO MonitorInfo = {};
|
||||
MonitorInfo.Size = sizeof(MonitorInfo);
|
||||
MonitorInfo.MonitorType = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI;
|
||||
MonitorInfo.ConnectorIndex = index;
|
||||
MonitorInfo.MonitorDescription.Size = sizeof(MonitorInfo.MonitorDescription);
|
||||
MonitorInfo.MonitorDescription.Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID;
|
||||
MonitorInfo.MonitorDescription.DataSize = sizeof(s_KnownMonitorEdid);
|
||||
MonitorInfo.MonitorDescription.pData = const_cast<BYTE*>(s_KnownMonitorEdid);
|
||||
|
||||
// ==============================
|
||||
// TODO: The monitor's container ID should be distinct from "this" device's container ID if the monitor is not
|
||||
// permanently attached to the display adapter device object. The container ID is typically made unique for each
|
||||
// monitor and can be used to associate the monitor with other devices, like audio or input devices. In this
|
||||
// sample we generate a random container ID GUID, but it's best practice to choose a stable container ID for a
|
||||
// unique monitor or to use "this" device's container ID for a permanent/integrated monitor.
|
||||
// ==============================
|
||||
|
||||
// Create a container ID
|
||||
CoCreateGuid(&MonitorInfo.MonitorContainerId);
|
||||
|
||||
IDARG_IN_MONITORCREATE MonitorCreate = {};
|
||||
MonitorCreate.ObjectAttributes = &Attr;
|
||||
MonitorCreate.pMonitorInfo = &MonitorInfo;
|
||||
|
||||
// Create a monitor object with the specified monitor descriptor
|
||||
IDARG_OUT_MONITORCREATE MonitorCreateOut;
|
||||
NTSTATUS Status = IddCxMonitorCreate(m_Adapter, &MonitorCreate, &MonitorCreateOut);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
m_Monitor = MonitorCreateOut.MonitorObject;
|
||||
|
||||
// Associate the monitor with this device context
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorCreateOut.MonitorObject);
|
||||
pContext->pContext = this;
|
||||
|
||||
// Tell the OS that the monitor has been plugged in
|
||||
IDARG_OUT_MONITORARRIVAL ArrivalOut;
|
||||
Status = IddCxMonitorArrival(m_Monitor, &ArrivalOut);
|
||||
}
|
||||
}
|
||||
|
||||
void IndirectDeviceContext::AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent)
|
||||
{
|
||||
m_ProcessingThread.reset();
|
||||
|
||||
auto Device = make_shared<Direct3DDevice>(RenderAdapter);
|
||||
if (FAILED(Device->Init()))
|
||||
{
|
||||
// It's important to delete the swap-chain if D3D initialization fails, so that the OS knows to generate a new
|
||||
// swap-chain and try again.
|
||||
WdfObjectDelete(SwapChain);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new swap-chain processing thread
|
||||
m_ProcessingThread.reset(new SwapChainProcessor(SwapChain, Device, NewFrameEvent));
|
||||
}
|
||||
}
|
||||
|
||||
void IndirectDeviceContext::UnassignSwapChain()
|
||||
{
|
||||
// Stop processing the last swap-chain
|
||||
m_ProcessingThread.reset();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region DDI Callbacks
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleAdapterInitFinished(IDDCX_ADAPTER AdapterObject, const IDARG_IN_ADAPTER_INIT_FINISHED* pInArgs)
|
||||
{
|
||||
// This is called when the OS has finished setting up the adapter for use by the IddCx driver. It's now possible
|
||||
// to report attached monitors.
|
||||
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterObject);
|
||||
if (NT_SUCCESS(pInArgs->AdapterInitStatus))
|
||||
{
|
||||
pContext->pContext->FinishInit();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleAdapterCommitModes(IDDCX_ADAPTER AdapterObject, const IDARG_IN_COMMITMODES* pInArgs)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(AdapterObject);
|
||||
UNREFERENCED_PARAMETER(pInArgs);
|
||||
|
||||
// For the sample, do nothing when modes are picked - the swap-chain is taken care of by IddCx
|
||||
|
||||
// ==============================
|
||||
// TODO: In a real driver, this function would be used to reconfigure the device to commit the new modes. Loop
|
||||
// through pInArgs->pPaths and look for IDDCX_PATH_FLAGS_ACTIVE. Any path not active is inactive (e.g. the monitor
|
||||
// should be turned off).
|
||||
// ==============================
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleParseMonitorDescription(const IDARG_IN_PARSEMONITORDESCRIPTION* pInArgs, IDARG_OUT_PARSEMONITORDESCRIPTION* pOutArgs)
|
||||
{
|
||||
// ==============================
|
||||
// TODO: In a real driver, this function would be called to generate monitor modes for an EDID by parsing it. In
|
||||
// this sample driver, we hard-code the EDID, so this function can generate known modes.
|
||||
// ==============================
|
||||
|
||||
for (int i = 0; i < monitorModes.size(); i++) {
|
||||
s_KnownMonitorModes2.push_back(dispinfo(std::get<0>(monitorModes[i]), std::get<1>(monitorModes[i]), std::get<2>(monitorModes[i])));
|
||||
}
|
||||
pOutArgs->MonitorModeBufferOutputCount = (UINT)monitorModes.size();
|
||||
|
||||
if (pInArgs->MonitorModeBufferInputCount < monitorModes.size())
|
||||
{
|
||||
// Return success if there was no buffer, since the caller was only asking for a count of modes
|
||||
return (pInArgs->MonitorModeBufferInputCount > 0) ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy the known modes to the output buffer
|
||||
for (DWORD ModeIndex = 0; ModeIndex < monitorModes.size(); ModeIndex++)
|
||||
{
|
||||
pInArgs->pMonitorModes[ModeIndex].Size = sizeof(IDDCX_MONITOR_MODE);
|
||||
pInArgs->pMonitorModes[ModeIndex].Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR;
|
||||
pInArgs->pMonitorModes[ModeIndex].MonitorVideoSignalInfo = s_KnownMonitorModes2[ModeIndex];
|
||||
}
|
||||
|
||||
// Set the preferred mode as represented in the EDID
|
||||
pOutArgs->PreferredMonitorModeIdx = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleMonitorGetDefaultModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_GETDEFAULTDESCRIPTIONMODES* pInArgs, IDARG_OUT_GETDEFAULTDESCRIPTIONMODES* pOutArgs)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(MonitorObject);
|
||||
UNREFERENCED_PARAMETER(pInArgs);
|
||||
UNREFERENCED_PARAMETER(pOutArgs);
|
||||
|
||||
// Should never be called since we create a single monitor with a known EDID in this sample driver.
|
||||
|
||||
// ==============================
|
||||
// TODO: In a real driver, this function would be called to generate monitor modes for a monitor with no EDID.
|
||||
// Drivers should report modes that are guaranteed to be supported by the transport protocol and by nearly all
|
||||
// monitors (such 640x480, 800x600, or 1024x768). If the driver has access to monitor modes from a descriptor other
|
||||
// than an EDID, those modes would also be reported here.
|
||||
// ==============================
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a target mode from the fundamental mode attributes.
|
||||
/// </summary>
|
||||
void CreateTargetMode(DISPLAYCONFIG_VIDEO_SIGNAL_INFO& Mode, UINT Width, UINT Height, UINT VSync)
|
||||
{
|
||||
Mode.totalSize.cx = Mode.activeSize.cx = Width;
|
||||
Mode.totalSize.cy = Mode.activeSize.cy = Height;
|
||||
Mode.AdditionalSignalInfo.vSyncFreqDivider = 1;
|
||||
Mode.AdditionalSignalInfo.videoStandard = 255;
|
||||
Mode.vSyncFreq.Numerator = VSync;
|
||||
Mode.vSyncFreq.Denominator = Mode.hSyncFreq.Denominator = 1;
|
||||
Mode.hSyncFreq.Numerator = VSync * Height;
|
||||
Mode.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
|
||||
Mode.pixelRate = VSync * Width * Height;
|
||||
}
|
||||
|
||||
void CreateTargetMode(IDDCX_TARGET_MODE& Mode, UINT Width, UINT Height, UINT VSync)
|
||||
{
|
||||
Mode.Size = sizeof(Mode);
|
||||
CreateTargetMode(Mode.TargetVideoSignalInfo.targetVideoSignalInfo, Width, Height, VSync);
|
||||
}
|
||||
|
||||
void CreateTargetMode2(IDDCX_TARGET_MODE2& Mode, UINT Width, UINT Height, UINT VSync)
|
||||
{
|
||||
Mode.Size = sizeof(Mode);
|
||||
Mode.BitsPerComponent.Rgb = IDDCX_BITS_PER_COMPONENT_8 | IDDCX_BITS_PER_COMPONENT_10;
|
||||
CreateTargetMode(Mode.TargetVideoSignalInfo.targetVideoSignalInfo, Width, Height, VSync);
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleMonitorQueryModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_QUERYTARGETMODES* pInArgs, IDARG_OUT_QUERYTARGETMODES* pOutArgs)////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
UNREFERENCED_PARAMETER(MonitorObject);
|
||||
|
||||
vector<IDDCX_TARGET_MODE> TargetModes(monitorModes.size());
|
||||
|
||||
// Create a set of modes supported for frame processing and scan-out. These are typically not based on the
|
||||
// monitor's descriptor and instead are based on the static processing capability of the device. The OS will
|
||||
// report the available set of modes for a given output as the intersection of monitor modes with target modes.
|
||||
|
||||
for (int i = 0; i < monitorModes.size(); i++) {
|
||||
CreateTargetMode(TargetModes[i], std::get<0>(monitorModes[i]), std::get<1>(monitorModes[i]), std::get<2>(monitorModes[i]));
|
||||
}
|
||||
|
||||
pOutArgs->TargetModeBufferOutputCount = (UINT)TargetModes.size();
|
||||
|
||||
if (pInArgs->TargetModeBufferInputCount >= TargetModes.size())
|
||||
{
|
||||
copy(TargetModes.begin(), TargetModes.end(), pInArgs->pTargetModes);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleMonitorAssignSwapChain(IDDCX_MONITOR MonitorObject, const IDARG_IN_SETSWAPCHAIN* pInArgs)
|
||||
{
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorObject);
|
||||
pContext->pContext->AssignSwapChain(pInArgs->hSwapChain, pInArgs->RenderAdapterLuid, pInArgs->hNextSurfaceAvailable);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleMonitorUnassignSwapChain(IDDCX_MONITOR MonitorObject)
|
||||
{
|
||||
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorObject);
|
||||
pContext->pContext->UnassignSwapChain();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleEvtIddCxAdapterQueryTargetInfo(
|
||||
IDDCX_ADAPTER AdapterObject,
|
||||
IDARG_IN_QUERYTARGET_INFO* pInArgs,
|
||||
IDARG_OUT_QUERYTARGET_INFO* pOutArgs
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(AdapterObject);
|
||||
UNREFERENCED_PARAMETER(pInArgs);
|
||||
pOutArgs->TargetCaps = IDDCX_TARGET_CAPS_HIGH_COLOR_SPACE;
|
||||
pOutArgs->DitheringSupport.Rgb = IDDCX_BITS_PER_COMPONENT_10;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleEvtIddCxMonitorSetDefaultHdrMetadata(
|
||||
IDDCX_MONITOR MonitorObject,
|
||||
const IDARG_IN_MONITOR_SET_DEFAULT_HDR_METADATA* pInArgs
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(MonitorObject);
|
||||
UNREFERENCED_PARAMETER(pInArgs);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleEvtIddCxParseMonitorDescription2(
|
||||
const IDARG_IN_PARSEMONITORDESCRIPTION2* pInArgs,
|
||||
IDARG_OUT_PARSEMONITORDESCRIPTION* pOutArgs
|
||||
)
|
||||
{
|
||||
// ==============================
|
||||
// TODO: In a real driver, this function would be called to generate monitor modes for an EDID by parsing it. In
|
||||
// this sample driver, we hard-code the EDID, so this function can generate known modes.
|
||||
// ==============================
|
||||
|
||||
for (int i = 0; i < monitorModes.size(); i++) {
|
||||
s_KnownMonitorModes2.push_back(dispinfo(std::get<0>(monitorModes[i]), std::get<1>(monitorModes[i]), std::get<2>(monitorModes[i])));
|
||||
}
|
||||
pOutArgs->MonitorModeBufferOutputCount = (UINT)monitorModes.size();
|
||||
|
||||
if (pInArgs->MonitorModeBufferInputCount < monitorModes.size())
|
||||
{
|
||||
// Return success if there was no buffer, since the caller was only asking for a count of modes
|
||||
return (pInArgs->MonitorModeBufferInputCount > 0) ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy the known modes to the output buffer
|
||||
for (DWORD ModeIndex = 0; ModeIndex < monitorModes.size(); ModeIndex++)
|
||||
{
|
||||
pInArgs->pMonitorModes[ModeIndex].Size = sizeof(IDDCX_MONITOR_MODE2);
|
||||
pInArgs->pMonitorModes[ModeIndex].Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR;
|
||||
pInArgs->pMonitorModes[ModeIndex].MonitorVideoSignalInfo = s_KnownMonitorModes2[ModeIndex];
|
||||
pInArgs->pMonitorModes[ModeIndex].BitsPerComponent.Rgb = IDDCX_BITS_PER_COMPONENT_8 | IDDCX_BITS_PER_COMPONENT_10;
|
||||
}
|
||||
|
||||
// Set the preferred mode as represented in the EDID
|
||||
pOutArgs->PreferredMonitorModeIdx = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleEvtIddCxMonitorQueryTargetModes2(
|
||||
IDDCX_MONITOR MonitorObject,
|
||||
const IDARG_IN_QUERYTARGETMODES2* pInArgs,
|
||||
IDARG_OUT_QUERYTARGETMODES* pOutArgs
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(MonitorObject);
|
||||
|
||||
vector<IDDCX_TARGET_MODE2> TargetModes(monitorModes.size());
|
||||
|
||||
// Create a set of modes supported for frame processing and scan-out. These are typically not based on the
|
||||
// monitor's descriptor and instead are based on the static processing capability of the device. The OS will
|
||||
// report the available set of modes for a given output as the intersection of monitor modes with target modes.
|
||||
|
||||
for (int i = 0; i < monitorModes.size(); i++) {
|
||||
CreateTargetMode2(TargetModes[i], std::get<0>(monitorModes[i]), std::get<1>(monitorModes[i]), std::get<2>(monitorModes[i]));
|
||||
}
|
||||
|
||||
pOutArgs->TargetModeBufferOutputCount = (UINT)TargetModes.size();
|
||||
|
||||
if (pInArgs->TargetModeBufferInputCount >= TargetModes.size())
|
||||
{
|
||||
copy(TargetModes.begin(), TargetModes.end(), pInArgs->pTargetModes);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleEvtIddCxAdapterCommitModes2(
|
||||
IDDCX_ADAPTER AdapterObject,
|
||||
const IDARG_IN_COMMITMODES2* pInArgs
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(AdapterObject);
|
||||
UNREFERENCED_PARAMETER(pInArgs);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS IddSampleEvtIddCxMonitorSetGammaRamp(
|
||||
IDDCX_MONITOR MonitorObject,
|
||||
const IDARG_IN_SET_GAMMARAMP* pInArgs
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(MonitorObject);
|
||||
UNREFERENCED_PARAMETER(pInArgs);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -1,50 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34622.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IddSampleDriver", "IddSampleDriver.vcxproj", "{2D54CB75-8B17-4F11-97DC-847B0244CD46}"
|
||||
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
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Build.0 = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Build.0 = Release|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.ActiveCfg = Release|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Build.0 = Release|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Build.0 = Release|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Deploy.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9A8BE7D9-9F0F-40A2-BA2D-8AE9E35890DB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,323 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\Downloads\wudfwdm.h">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Driver.h" />
|
||||
<ClInclude Include="Trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="IddSampleDriver.inf" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{2D54CB75-8B17-4F11-97DC-847B0244CD46}</ProjectGuid>
|
||||
<TemplateGuid>{32909489-7be5-497b-aafa-db6669d9b44b}</TemplateGuid>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<RootNamespace>IddSampleDriver</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>0</IDDCX_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>0</IDDCX_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>10</IDDCX_VERSION_MINOR>
|
||||
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
|
||||
<UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>10</IDDCX_VERSION_MINOR>
|
||||
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
|
||||
<UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>0</IDDCX_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>0</IDDCX_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>0</IDDCX_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>0</IDDCX_VERSION_MINOR>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<TimeStampServer />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=4 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=10 /DIDDCX_MINIMUM_VERSION_REQUIRED=3 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="readme.md" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="IddSampleDriver.inf">
|
||||
<Filter>Driver Files</Filter>
|
||||
</Inf>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Driver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\Downloads\wudfwdm.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Driver.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="readme.md" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0
|
||||
MinimumVisualStudioVersion = 12.0
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDisplay", "Sample\SampleDisplay.vcxproj", "{D3C62015-3845-4DA8-8522-5DC45B735063}"
|
||||
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
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Release|Win32.Build.0 = Release|Win32
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Debug|x64.Build.0 = Debug|x64
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Release|x64.ActiveCfg = Release|x64
|
||||
{D3C62015-3845-4DA8-8522-5DC45B735063}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,71 +0,0 @@
|
||||
### THIS SAMPLE IS INCOMPLETE - Currently a Work in Progress attempt at HDR and 10-bit video support.
|
||||
|
||||
---
|
||||
page_type: sample
|
||||
description: "Implements most DDIs that a display-only miniport driver should provide to the Windows Display Driver Model (WDDM)."
|
||||
languages:
|
||||
- cpp
|
||||
products:
|
||||
- windows
|
||||
- windows-wdk
|
||||
---
|
||||
|
||||
# Kernel mode display-only miniport driver (KMDOD) sample
|
||||
|
||||
The kernel mode display-only miniport driver (KMDOD) sample implements most of the device driver interfaces (DDIs) that a display-only miniport driver should provide to the Windows Display Driver Model (WDDM). The code is useful to understand how to write a miniport driver for a display-only device, or how to develop a full WDDM driver.
|
||||
|
||||
For more info on WDDM drivers, see [Windows Display Driver Model (WDDM) Design Guide](https://docs.microsoft.com/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide).
|
||||
|
||||
This code can also help you to understand the use and implementation of display-related DDIs. The INF file shows how to make a display miniport driver visible to other WDDM components.
|
||||
|
||||
The sample can be installed on top of a VESA-capable graphics adapter, or on top of a graphics device that supports access to frame buffer memory through the Unified Extensible Firmware Interface (UEFI).
|
||||
|
||||
The sample driver does not support the *sleep* power state. If it is placed in the sleep state, the driver will cause a system bugcheck to occur. There is no workaround available, by design.
|
||||
|
||||
If the current display driver is not a WDDM 1.2 compliant driver, the sample driver might fail to install, with error code 43 displayed. The KMDOD driver is actually installed, but it cannot be started. The workaround for this issue is to switch to the Microsoft Basic Display Adapter Driver before installing the KMDOD sample driver, or simply to reboot your system after installing the KMDOD sample.
|
||||
|
||||
## Installation
|
||||
|
||||
In Microsoft Visual Studio, press **F5** to build the sample and then deploy it to a target machine. For more info, see [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer).
|
||||
|
||||
In some cases you might need to install the driver manually, as follows.
|
||||
|
||||
1. Add the following files to the directory given by ...\\[x64]\\C++\\Package:
|
||||
|
||||
- SampleDriver.cat
|
||||
|
||||
- SampleDriver.inf
|
||||
|
||||
- SampleDriver.sys
|
||||
|
||||
- SampleDriver.cer
|
||||
|
||||
1. Unless you've provided a production certificate, you should manually install the SampleDriver.cer digital certificate with the following command:
|
||||
|
||||
`Certutil.exe -addstore root SampleDriver.cer`
|
||||
|
||||
1. Then enable test signing by running the following BCDEdit command:
|
||||
|
||||
`Bcdedit.exe -set TESTSIGNING ON`
|
||||
|
||||
> [!NOTE]
|
||||
> After you change the TESTSIGNING boot configuration option, restart the computer for the change to take effect.
|
||||
|
||||
For more info, see [The TESTSIGNING Boot Configuration Option](https://docs.microsoft.com/windows-hardware/drivers/install/the-testsigning-boot-configuration-option).
|
||||
|
||||
1. Manually install the driver using Device Manager, which is available from Control Panel.
|
||||
|
||||
### ACPI-based GPUs
|
||||
|
||||
To install the KMDOD sample driver on a GPU that is an Advanced Configuration and Power Interface (ACPI) device, add these lines to the `[MS]`, `[MS.NTamd64]`, and `[MS.NTarm]` sections of the Sampledisplay.inf file:
|
||||
|
||||
```inf
|
||||
Text
|
||||
" Kernel mode display only sample driver " = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000
|
||||
" Kernel mode display only sample driver " = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001
|
||||
" Kernel mode display only sample driver " = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0003
|
||||
```
|
||||
|
||||
This new code provides generic identifiers for ACPI hardware.
|
||||
|
||||
You can optionally delete the original lines of code within these sections of the INF file.
|
||||
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
|
||||
<UniqueIdentifier>{8B6C0A00-F837-4D16-A67B-98E6936A2729}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{0D809CEB-9E9B-4357-B44D-BCDCA1D0A4A5}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
|
||||
<UniqueIdentifier>{E61D9490-5CC2-4F32-AC2B-BCE3922E65F7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
<UniqueIdentifier>{5A656697-E252-49C1-BF4E-B06BA46DF394}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\BDD.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\BDD_DDI.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\BDD_DMM.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\BDD_Util.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\BltFuncs.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\BltHw.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\memory.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\sampledisplay.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
-854
@@ -1,854 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: bdd.cxx
|
||||
*
|
||||
* Basic Display Driver functions implementation
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
|
||||
#include "BDD.hxx"
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
|
||||
|
||||
BASIC_DISPLAY_DRIVER::BASIC_DISPLAY_DRIVER(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject),
|
||||
m_MonitorPowerState(PowerDeviceD0),
|
||||
m_AdapterPowerState(PowerDeviceD0)
|
||||
{
|
||||
PAGED_CODE();
|
||||
*((UINT*)&m_Flags) = 0;
|
||||
m_Flags._LastFlag = TRUE;
|
||||
RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface));
|
||||
RtlZeroMemory(&m_StartInfo, sizeof(m_StartInfo));
|
||||
RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));
|
||||
RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo));
|
||||
|
||||
|
||||
for (UINT i=0;i<MAX_VIEWS;i++)
|
||||
{
|
||||
m_HardwareBlt[i].Initialize(this,i);
|
||||
}
|
||||
}
|
||||
|
||||
BASIC_DISPLAY_DRIVER::~BASIC_DISPLAY_DRIVER()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
|
||||
_In_ DXGKRNL_INTERFACE* pDxgkInterface,
|
||||
_Out_ ULONG* pNumberOfViews,
|
||||
_Out_ ULONG* pNumberOfChildren)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pDxgkStartInfo != NULL);
|
||||
BDD_ASSERT(pDxgkInterface != NULL);
|
||||
BDD_ASSERT(pNumberOfViews != NULL);
|
||||
BDD_ASSERT(pNumberOfChildren != NULL);
|
||||
|
||||
RtlCopyMemory(&m_StartInfo, pDxgkStartInfo, sizeof(m_StartInfo));
|
||||
RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface));
|
||||
RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));
|
||||
m_CurrentModes[0].DispInfo.TargetId = D3DDDI_ID_UNINITIALIZED;
|
||||
|
||||
// Get device information from OS.
|
||||
NTSTATUS Status = m_DxgkInterface.DxgkCbGetDeviceInformation(m_DxgkInterface.DeviceHandle, &m_DeviceInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ASSERTION1("DxgkCbGetDeviceInformation failed with status 0x%I64x",
|
||||
Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Ignore return value, since it's not the end of the world if we failed to write these values to the registry
|
||||
RegisterHWInfo();
|
||||
|
||||
// TODO: Uncomment the line below after updating the TODOs in the function CheckHardware
|
||||
// Status = CheckHardware();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
// This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership
|
||||
// gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back!
|
||||
Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo));
|
||||
if (!NT_SUCCESS(Status) || m_CurrentModes[0].DispInfo.Width == 0)
|
||||
{
|
||||
// The most likely cause of failure is that the driver is simply not running on a POST device, or we are running
|
||||
// after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start.
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
m_Flags.DriverStarted = TRUE;
|
||||
*pNumberOfViews = MAX_VIEWS;
|
||||
*pNumberOfChildren = MAX_CHILDREN;
|
||||
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::StopDevice(VOID)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
CleanUp();
|
||||
|
||||
m_Flags.DriverStarted = FALSE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID BASIC_DISPLAY_DRIVER::CleanUp()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
for (UINT Source = 0; Source < MAX_VIEWS; ++Source)
|
||||
{
|
||||
if (m_CurrentModes[Source].FrameBuffer.Ptr)
|
||||
{
|
||||
UnmapFrameBuffer(m_CurrentModes[Source].FrameBuffer.Ptr, m_CurrentModes[Source].DispInfo.Height * m_CurrentModes[Source].DispInfo.Pitch);
|
||||
m_CurrentModes[Source].FrameBuffer.Ptr = NULL;
|
||||
m_CurrentModes[Source].Flags.FrameBufferIsActive = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::DispatchIoRequest(_In_ ULONG VidPnSourceId,
|
||||
_In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pVideoRequestPacket != NULL);
|
||||
BDD_ASSERT(VidPnSourceId < MAX_VIEWS);
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::SetPowerState(_In_ ULONG HardwareUid,
|
||||
_In_ DEVICE_POWER_STATE DevicePowerState,
|
||||
_In_ POWER_ACTION ActionType)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(ActionType);
|
||||
|
||||
BDD_ASSERT((HardwareUid < MAX_CHILDREN) || (HardwareUid == DISPLAY_ADAPTER_HW_ID));
|
||||
|
||||
if (HardwareUid == DISPLAY_ADAPTER_HW_ID)
|
||||
{
|
||||
if (DevicePowerState == PowerDeviceD0)
|
||||
{
|
||||
|
||||
// When returning from D3 the device visibility defined to be off for all targets
|
||||
if (m_AdapterPowerState == PowerDeviceD3)
|
||||
{
|
||||
DXGKARG_SETVIDPNSOURCEVISIBILITY Visibility;
|
||||
Visibility.VidPnSourceId = D3DDDI_ID_ALL;
|
||||
Visibility.Visible = FALSE;
|
||||
SetVidPnSourceVisibility(&Visibility);
|
||||
}
|
||||
}
|
||||
|
||||
// Store new adapter power state
|
||||
m_AdapterPowerState = DevicePowerState;
|
||||
|
||||
// There is nothing to do to specifically power up/down the display adapter
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: This is where the specified monitor should be powered up/down
|
||||
NOTHING;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
|
||||
_In_ ULONG ChildRelationsSize)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pChildRelations != NULL);
|
||||
|
||||
// The last DXGK_CHILD_DESCRIPTOR in the array of pChildRelations must remain zeroed out, so we subtract this from the count
|
||||
ULONG ChildRelationsCount = (ChildRelationsSize / sizeof(DXGK_CHILD_DESCRIPTOR)) - 1;
|
||||
BDD_ASSERT(ChildRelationsCount <= MAX_CHILDREN);
|
||||
|
||||
for (UINT ChildIndex = 0; ChildIndex < ChildRelationsCount; ++ChildIndex)
|
||||
{
|
||||
pChildRelations[ChildIndex].ChildDeviceType = TypeVideoOutput;
|
||||
pChildRelations[ChildIndex].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible;
|
||||
pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = m_CurrentModes[0].Flags.IsInternal ? D3DKMDT_VOT_INTERNAL : D3DKMDT_VOT_OTHER;
|
||||
pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE;
|
||||
pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
|
||||
// TODO: Replace 0 with the actual ACPI ID of the child device, if available
|
||||
pChildRelations[ChildIndex].AcpiUid = 0;
|
||||
pChildRelations[ChildIndex].ChildUid = ChildIndex;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus,
|
||||
_In_ BOOLEAN NonDestructiveOnly)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(NonDestructiveOnly);
|
||||
BDD_ASSERT(pChildStatus != NULL);
|
||||
BDD_ASSERT(pChildStatus->ChildUid < MAX_CHILDREN);
|
||||
|
||||
switch (pChildStatus->Type)
|
||||
{
|
||||
case StatusConnection:
|
||||
{
|
||||
// HpdAwarenessInterruptible was reported since HpdAwarenessNone is deprecated.
|
||||
// However, BDD has no knowledge of HotPlug events, so just always return connected.
|
||||
pChildStatus->HotPlug.Connected = IsDriverActive();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case StatusRotation:
|
||||
{
|
||||
// D3DKMDT_MOA_NONE was reported, so this should never be called
|
||||
BDD_LOG_ERROR0("Child status being queried for StatusRotation even though D3DKMDT_MOA_NONE was reported");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
BDD_LOG_WARNING1("Unknown pChildStatus->Type (0x%I64x) requested.", pChildStatus->Type);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EDID retrieval
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::QueryDeviceDescriptor(_In_ ULONG ChildUid,
|
||||
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pDeviceDescriptor != NULL);
|
||||
BDD_ASSERT(ChildUid < MAX_CHILDREN);
|
||||
|
||||
// If we haven't successfully retrieved an EDID yet (invalid ones are ok, so long as it was retrieved)
|
||||
if (!m_Flags.EDID_Attempted)
|
||||
{
|
||||
GetEdid(ChildUid);
|
||||
}
|
||||
|
||||
if (!m_Flags.EDID_Retrieved || !m_Flags.EDID_ValidHeader || !m_Flags.EDID_ValidChecksum)
|
||||
{
|
||||
// Report no EDID if a valid one wasn't retrieved
|
||||
return STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED;
|
||||
}
|
||||
else if (pDeviceDescriptor->DescriptorOffset == 0)
|
||||
{
|
||||
// Only the base block is supported
|
||||
RtlCopyMemory(pDeviceDescriptor->DescriptorBuffer,
|
||||
m_EDIDs[ChildUid],
|
||||
min(pDeviceDescriptor->DescriptorLength, EDID_V1_BLOCK_SIZE));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pQueryAdapterInfo != NULL);
|
||||
|
||||
switch (pQueryAdapterInfo->Type)
|
||||
{
|
||||
case DXGKQAITYPE_DRIVERCAPS:
|
||||
{
|
||||
if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS))
|
||||
{
|
||||
BDD_LOG_ERROR2("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%I64x)", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DRIVERCAPS));
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
DXGK_DRIVERCAPS* pDriverCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
|
||||
|
||||
// Nearly all fields must be initialized to zero, so zero out to start and then change those that are non-zero.
|
||||
// Fields are zero since BDD is Display-Only and therefore does not support any of the render related fields.
|
||||
// It also doesn't support hardware interrupts, gamma ramps, etc.
|
||||
RtlZeroMemory(pDriverCaps, sizeof(DXGK_DRIVERCAPS));
|
||||
|
||||
pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
|
||||
pDriverCaps->HighestAcceptableAddress.QuadPart = -1;
|
||||
|
||||
pDriverCaps->SupportNonVGA = TRUE;
|
||||
pDriverCaps->SupportSmoothRotation = TRUE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case DXGKQAITYPE_DISPLAY_DRIVERCAPS_EXTENSION:
|
||||
{
|
||||
DXGK_DISPLAY_DRIVERCAPS_EXTENSION* pDriverDisplayCaps;
|
||||
|
||||
if (pQueryAdapterInfo->OutputDataSize < sizeof(*pDriverDisplayCaps))
|
||||
{
|
||||
BDD_LOG_ERROR2("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DISPLAY_DRIVERCAPS_EXTENSION) (0x%I64x)",
|
||||
pQueryAdapterInfo->OutputDataSize,
|
||||
sizeof(DXGK_DISPLAY_DRIVERCAPS_EXTENSION));
|
||||
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
pDriverDisplayCaps = (DXGK_DISPLAY_DRIVERCAPS_EXTENSION*)pQueryAdapterInfo->pOutputData;
|
||||
|
||||
// Reset all caps values
|
||||
RtlZeroMemory(pDriverDisplayCaps, pQueryAdapterInfo->OutputDataSize);
|
||||
|
||||
// We claim to support virtual display mode.
|
||||
pDriverDisplayCaps->VirtualModeSupport = 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// BDD does not need to support any other adapter information types
|
||||
BDD_LOG_WARNING1("Unknown QueryAdapterInfo Type (0x%I64x) requested", pQueryAdapterInfo->Type);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::CheckHardware()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Status;
|
||||
ULONG VendorID;
|
||||
ULONG DeviceID;
|
||||
|
||||
// TODO: If developing a driver for PCI based hardware, then use the second method to retrieve Vendor/Device IDs.
|
||||
// If developing for non-PCI based hardware (i.e. ACPI based hardware), use the first method to retrieve the IDs.
|
||||
#if 1 // ACPI-based device
|
||||
|
||||
// Get the Vendor & Device IDs on non-PCI system
|
||||
ACPI_EVAL_INPUT_BUFFER_COMPLEX AcpiInputBuffer = {0};
|
||||
AcpiInputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
|
||||
AcpiInputBuffer.MethodNameAsUlong = ACPI_METHOD_HARDWARE_ID;
|
||||
AcpiInputBuffer.Size = 0;
|
||||
AcpiInputBuffer.ArgumentCount = 0;
|
||||
|
||||
BYTE OutputBuffer[sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 0x10];
|
||||
RtlZeroMemory(OutputBuffer, sizeof(OutputBuffer));
|
||||
ACPI_EVAL_OUTPUT_BUFFER* pAcpiOutputBuffer = reinterpret_cast<ACPI_EVAL_OUTPUT_BUFFER*>(&OutputBuffer);
|
||||
|
||||
Status = m_DxgkInterface.DxgkCbEvalAcpiMethod(m_DxgkInterface.DeviceHandle,
|
||||
DISPLAY_ADAPTER_HW_ID,
|
||||
&AcpiInputBuffer,
|
||||
sizeof(AcpiInputBuffer),
|
||||
pAcpiOutputBuffer,
|
||||
sizeof(OutputBuffer));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR1("DxgkCbReadDeviceSpace failed to get hardware IDs with status 0x%I64x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VendorID = ((ULONG*)(pAcpiOutputBuffer->Argument[0].Data))[0];
|
||||
DeviceID = ((ULONG*)(pAcpiOutputBuffer->Argument[0].Data))[1];
|
||||
|
||||
#else // PCI-based device
|
||||
|
||||
// Get the Vendor & Device IDs on PCI system
|
||||
PCI_COMMON_HEADER Header = {0};
|
||||
ULONG BytesRead;
|
||||
|
||||
Status = m_DxgkInterface.DxgkCbReadDeviceSpace(m_DxgkInterface.DeviceHandle,
|
||||
DXGK_WHICHSPACE_CONFIG,
|
||||
&Header,
|
||||
0,
|
||||
sizeof(Header),
|
||||
&BytesRead);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR1("DxgkCbReadDeviceSpace failed with status 0x%I64x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VendorID = Header.VendorID;
|
||||
DeviceID = Header.DeviceID;
|
||||
|
||||
#endif
|
||||
|
||||
// TODO: Replace 0x1414 with your Vendor ID
|
||||
if (VendorID == 0x1414)
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
// TODO: Replace the case statements below with the Device IDs supported by this driver
|
||||
case 0x0000:
|
||||
case 0xFFFF: return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_GRAPHICS_DRIVER_MISMATCH;
|
||||
}
|
||||
|
||||
// Even though Sample Basic Display Driver does not support hardware cursors, and reports such
|
||||
// in QueryAdapterInfo. This function can still be called to set the pointer to not visible
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pSetPointerPosition != NULL);
|
||||
BDD_ASSERT(pSetPointerPosition->VidPnSourceId < MAX_VIEWS);
|
||||
|
||||
if (!(pSetPointerPosition->Flags.Visible))
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
BDD_LOG_ASSERTION0("SetPointerPosition should never be called to set the pointer to visible since BDD doesn't support hardware cursors.");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
// Basic Sample Display Driver does not support hardware cursors, and reports such
|
||||
// in QueryAdapterInfo. Therefore this function should never be called.
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pSetPointerShape != NULL);
|
||||
BDD_LOG_ASSERTION0("SetPointerShape should never be called since BDD doesn't support hardware cursors.");
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pPresentDisplayOnly != NULL);
|
||||
BDD_ASSERT(pPresentDisplayOnly->VidPnSourceId < MAX_VIEWS);
|
||||
|
||||
if (pPresentDisplayOnly->BytesPerPixel < MIN_BYTES_PER_PIXEL_REPORTED)
|
||||
{
|
||||
// Only >=32bpp modes are reported, therefore this Present should never pass anything less than 4 bytes per pixel
|
||||
BDD_LOG_ERROR1("pPresentDisplayOnly->BytesPerPixel is 0x%I64x, which is lower than the allowed.", pPresentDisplayOnly->BytesPerPixel);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// If it is in monitor off state or source is not supposed to be visible, don't present anything to the screen
|
||||
if ((m_MonitorPowerState > PowerDeviceD0) ||
|
||||
(m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.SourceNotVisible))
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Present is only valid if the target is actively connected to this source
|
||||
if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.FrameBufferIsActive)
|
||||
{
|
||||
|
||||
// If actual pixels are coming through, will need to completely zero out physical address next time in BlackOutScreen
|
||||
m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].ZeroedOutStart.QuadPart = 0;
|
||||
m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].ZeroedOutEnd.QuadPart = 0;
|
||||
|
||||
|
||||
D3DKMDT_VIDPN_PRESENT_PATH_ROTATION RotationNeededByFb = pPresentDisplayOnly->Flags.Rotate ?
|
||||
m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Rotation :
|
||||
D3DKMDT_VPPR_IDENTITY;
|
||||
BYTE* pDst = (BYTE*)m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].FrameBuffer.Ptr;
|
||||
UINT DstBitPerPixel = BPPFromPixelFormat(m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.ColorFormat);
|
||||
if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Scaling == D3DKMDT_VPPS_CENTERED)
|
||||
{
|
||||
UINT CenterShift = (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Height -
|
||||
m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeHeight)*m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Pitch;
|
||||
CenterShift += (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].DispInfo.Width -
|
||||
m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].SrcModeWidth)*DstBitPerPixel/8;
|
||||
pDst += (int)CenterShift/2;
|
||||
}
|
||||
return m_HardwareBlt[pPresentDisplayOnly->VidPnSourceId].ExecutePresentDisplayOnly(pDst,
|
||||
DstBitPerPixel,
|
||||
(BYTE*)pPresentDisplayOnly->pSource,
|
||||
pPresentDisplayOnly->BytesPerPixel,
|
||||
pPresentDisplayOnly->Pitch,
|
||||
pPresentDisplayOnly->NumMoves,
|
||||
pPresentDisplayOnly->pMoves,
|
||||
pPresentDisplayOnly->NumDirtyRects,
|
||||
pPresentDisplayOnly->pDirtyRect,
|
||||
RotationNeededByFb);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(TargetId < MAX_CHILDREN);
|
||||
|
||||
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = FindSourceForTarget(TargetId, TRUE);
|
||||
|
||||
// In case BDD is the next driver to run, the monitor should not be off, since
|
||||
// this could cause the BIOS to hang when the EDID is retrieved on Start.
|
||||
if (m_MonitorPowerState > PowerDeviceD0)
|
||||
{
|
||||
SetPowerState(TargetId, PowerDeviceD0, PowerActionNone);
|
||||
}
|
||||
|
||||
// The driver has to black out the display and ensure it is visible when releasing ownership
|
||||
BlackOutScreen(SourceId);
|
||||
|
||||
*pDisplayInfo = m_CurrentModes[SourceId].DispInfo;
|
||||
|
||||
return StopDevice();
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT(pVidPnHWCaps != NULL);
|
||||
BDD_ASSERT(pVidPnHWCaps->SourceId < MAX_VIEWS);
|
||||
BDD_ASSERT(pVidPnHWCaps->TargetId < MAX_CHILDREN);
|
||||
|
||||
pVidPnHWCaps->VidPnHWCaps.DriverRotation = 1; // BDD does rotation in software
|
||||
pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0; // BDD does not support scaling
|
||||
pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0; // BDD does not support clone
|
||||
pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 1; // BDD does color conversions in software
|
||||
pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0; // BDD does not support linked adapters
|
||||
pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0; // BDD does not support remote displays
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::GetEdid(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BDD_ASSERT_CHK(!m_Flags.EDID_Attempted);
|
||||
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
RtlZeroMemory(m_EDIDs[TargetId], sizeof(m_EDIDs[TargetId]));
|
||||
|
||||
|
||||
m_Flags.EDID_Attempted = TRUE;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID BASIC_DISPLAY_DRIVER::BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
||||
UINT ScreenHeight = m_CurrentModes[SourceId].DispInfo.Height;
|
||||
UINT ScreenPitch = m_CurrentModes[SourceId].DispInfo.Pitch;
|
||||
|
||||
PHYSICAL_ADDRESS NewPhysAddrStart = m_CurrentModes[SourceId].DispInfo.PhysicAddress;
|
||||
PHYSICAL_ADDRESS NewPhysAddrEnd;
|
||||
NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch);
|
||||
|
||||
if (m_CurrentModes[SourceId].Flags.FrameBufferIsActive)
|
||||
{
|
||||
BYTE* MappedAddr = reinterpret_cast<BYTE*>(m_CurrentModes[SourceId].FrameBuffer.Ptr);
|
||||
|
||||
// Zero any memory at the start that hasn't been zeroed recently
|
||||
if (NewPhysAddrStart.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart)
|
||||
{
|
||||
if (NewPhysAddrEnd.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart)
|
||||
{
|
||||
// No overlap
|
||||
RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlZeroMemory(MappedAddr, (UINT)(m_CurrentModes[SourceId].ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart));
|
||||
}
|
||||
}
|
||||
|
||||
// Zero any memory at the end that hasn't been zeroed recently
|
||||
if (NewPhysAddrEnd.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)
|
||||
{
|
||||
if (NewPhysAddrStart.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)
|
||||
{
|
||||
// No overlap
|
||||
// NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0
|
||||
// and this is the path that will be used to black out the current screen.
|
||||
RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlZeroMemory(MappedAddr, (UINT)(NewPhysAddrEnd.QuadPart - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_CurrentModes[SourceId].ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart;
|
||||
m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Status;
|
||||
ANSI_STRING AnsiStrValue;
|
||||
UNICODE_STRING UnicodeStrValue;
|
||||
UNICODE_STRING UnicodeStrValueName;
|
||||
|
||||
// ZwSetValueKey wants the ValueName as a UNICODE_STRING
|
||||
RtlInitUnicodeString(&UnicodeStrValueName, pszwValueName);
|
||||
|
||||
// REG_SZ is for WCHARs, there is no equivalent for CHARs
|
||||
// Use the ansi/unicode conversion functions to get from PSTR to PWSTR
|
||||
RtlInitAnsiString(&AnsiStrValue, pszValue);
|
||||
Status = RtlAnsiStringToUnicodeString(&UnicodeStrValue, &AnsiStrValue, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR1("RtlAnsiStringToUnicodeString failed with Status: 0x%I64x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Write the value to the registry
|
||||
Status = ZwSetValueKey(DevInstRegKeyHandle,
|
||||
&UnicodeStrValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
UnicodeStrValue.Buffer,
|
||||
UnicodeStrValue.MaximumLength);
|
||||
|
||||
// Free the earlier allocated unicode string
|
||||
RtlFreeUnicodeString(&UnicodeStrValue);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR1("ZwSetValueKey failed with Status: 0x%I64x", Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::RegisterHWInfo()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Status;
|
||||
|
||||
// TODO: Replace these strings with proper information
|
||||
PCSTR StrHWInfoChipType = "Replace with the chip name";
|
||||
PCSTR StrHWInfoDacType = "Replace with the DAC name or identifier (ID)";
|
||||
PCSTR StrHWInfoAdapterString = "Replace with the name of the adapter";
|
||||
PCSTR StrHWInfoBiosString = "Replace with information about the BIOS";
|
||||
|
||||
HANDLE DevInstRegKeyHandle;
|
||||
Status = IoOpenDeviceRegistryKey(m_pPhysicalDevice, PLUGPLAY_REGKEY_DRIVER, KEY_SET_VALUE, &DevInstRegKeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR2("IoOpenDeviceRegistryKey failed for PDO: 0x%I64x, Status: 0x%I64x", m_pPhysicalDevice, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.ChipType", StrHWInfoChipType);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.DacType", StrHWInfoDacType);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.AdapterString", StrHWInfoAdapterString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = WriteHWInfoStr(DevInstRegKeyHandle, L"HardwareInformation.BiosString", StrHWInfoBiosString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
// MemorySize is a ULONG, unlike the others which are all strings
|
||||
UNICODE_STRING ValueNameMemorySize;
|
||||
RtlInitUnicodeString(&ValueNameMemorySize, L"HardwareInformation.MemorySize");
|
||||
DWORD MemorySize = 0; // BDD has no access to video memory
|
||||
Status = ZwSetValueKey(DevInstRegKeyHandle,
|
||||
&ValueNameMemorySize,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&MemorySize,
|
||||
sizeof(MemorySize));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR1("ZwSetValueKey for MemorySize failed with Status: 0x%I64x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Non-Paged Code
|
||||
//
|
||||
#pragma code_seg(push)
|
||||
#pragma code_seg()
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID BASIC_DISPLAY_DRIVER::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(TargetId);
|
||||
BDD_ASSERT_CHK(TargetId < MAX_CHILDREN);
|
||||
|
||||
for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId)
|
||||
{
|
||||
if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL)
|
||||
{
|
||||
return SourceId;
|
||||
}
|
||||
}
|
||||
|
||||
return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED;
|
||||
}
|
||||
|
||||
VOID BASIC_DISPLAY_DRIVER::DpcRoutine(VOID)
|
||||
{
|
||||
m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle);
|
||||
}
|
||||
|
||||
BOOLEAN BASIC_DISPLAY_DRIVER::InterruptRoutine(_In_ ULONG MessageNumber)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(MessageNumber);
|
||||
|
||||
// BDD cannot handle interrupts
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID BASIC_DISPLAY_DRIVER::ResetDevice(VOID)
|
||||
{
|
||||
}
|
||||
|
||||
// Must be Non-Paged, as it sets up the display for a bugcheck
|
||||
NTSTATUS BASIC_DISPLAY_DRIVER::SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
|
||||
_Out_ UINT* pWidth,
|
||||
_Out_ UINT* pHeight,
|
||||
_Out_ D3DDDIFORMAT* pColorFormat)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Flags);
|
||||
|
||||
m_SystemDisplaySourceId = D3DDDI_ID_UNINITIALIZED;
|
||||
|
||||
BDD_ASSERT((TargetId < MAX_CHILDREN) || (TargetId == D3DDDI_ID_UNINITIALIZED));
|
||||
|
||||
// Find the frame buffer for displaying the bugcheck, if it was successfully mapped
|
||||
if (TargetId == D3DDDI_ID_UNINITIALIZED)
|
||||
{
|
||||
for (UINT SourceIdx = 0; SourceIdx < MAX_VIEWS; ++SourceIdx)
|
||||
{
|
||||
if (m_CurrentModes[SourceIdx].FrameBuffer.Ptr != NULL)
|
||||
{
|
||||
m_SystemDisplaySourceId = SourceIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SystemDisplaySourceId = FindSourceForTarget(TargetId, FALSE);
|
||||
}
|
||||
|
||||
if (m_SystemDisplaySourceId == D3DDDI_ID_UNINITIALIZED)
|
||||
{
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_CurrentModes[m_SystemDisplaySourceId].Rotation == D3DKMDT_VPPR_ROTATE90) ||
|
||||
(m_CurrentModes[m_SystemDisplaySourceId].Rotation == D3DKMDT_VPPR_ROTATE270))
|
||||
{
|
||||
*pHeight = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width;
|
||||
*pWidth = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pWidth = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width;
|
||||
*pHeight = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height;
|
||||
}
|
||||
|
||||
*pColorFormat = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.ColorFormat;
|
||||
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Must be Non-Paged, as it is called to display the bugcheck screen
|
||||
VOID BASIC_DISPLAY_DRIVER::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,
|
||||
_In_ UINT SourceWidth,
|
||||
_In_ UINT SourceHeight,
|
||||
_In_ UINT SourceStride,
|
||||
_In_ INT PositionX,
|
||||
_In_ INT PositionY)
|
||||
{
|
||||
|
||||
// Rect will be Offset by PositionX/Y in the src to reset it back to 0
|
||||
RECT Rect;
|
||||
Rect.left = PositionX;
|
||||
Rect.top = PositionY;
|
||||
Rect.right = Rect.left + SourceWidth;
|
||||
Rect.bottom = Rect.top + SourceHeight;
|
||||
|
||||
// Set up destination blt info
|
||||
BLT_INFO DstBltInfo;
|
||||
DstBltInfo.pBits = m_CurrentModes[m_SystemDisplaySourceId].FrameBuffer.Ptr;
|
||||
DstBltInfo.Pitch = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Pitch;
|
||||
DstBltInfo.BitsPerPel = BPPFromPixelFormat(m_CurrentModes[m_SystemDisplaySourceId].DispInfo.ColorFormat);
|
||||
DstBltInfo.Offset.x = 0;
|
||||
DstBltInfo.Offset.y = 0;
|
||||
DstBltInfo.Rotation = m_CurrentModes[m_SystemDisplaySourceId].Rotation;
|
||||
DstBltInfo.Width = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Width;
|
||||
DstBltInfo.Height = m_CurrentModes[m_SystemDisplaySourceId].DispInfo.Height;
|
||||
|
||||
// Set up source blt info
|
||||
BLT_INFO SrcBltInfo;
|
||||
SrcBltInfo.pBits = pSource;
|
||||
SrcBltInfo.Pitch = SourceStride;
|
||||
SrcBltInfo.BitsPerPel = 32;
|
||||
|
||||
SrcBltInfo.Offset.x = -PositionX;
|
||||
SrcBltInfo.Offset.y = -PositionY;
|
||||
SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY;
|
||||
SrcBltInfo.Width = SourceWidth;
|
||||
SrcBltInfo.Height = SourceHeight;
|
||||
|
||||
BltBits(&DstBltInfo,
|
||||
&SrcBltInfo,
|
||||
1, // NumRects
|
||||
&Rect);
|
||||
}
|
||||
|
||||
#pragma code_seg(pop) // End Non-Paged Code
|
||||
|
||||
-650
@@ -1,650 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: BDD.hxx
|
||||
*
|
||||
* Basic Display Driver header file
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
#ifndef _BDD_HXX_
|
||||
#define _BDD_HXX_
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#define __CPLUSPLUS
|
||||
|
||||
// Standard C-runtime headers
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
// NTOS headers
|
||||
#include <ntddk.h>
|
||||
|
||||
#ifndef FAR
|
||||
#define FAR
|
||||
#endif
|
||||
|
||||
// Windows headers
|
||||
#include <windef.h>
|
||||
#include <winerror.h>
|
||||
|
||||
// Windows GDI headers
|
||||
#include <wingdi.h>
|
||||
|
||||
// Windows DDI headers
|
||||
#include <winddi.h>
|
||||
#include <ntddvdeo.h>
|
||||
|
||||
#include <d3dkmddi.h>
|
||||
#include <d3dkmthk.h>
|
||||
|
||||
#include <ntstrsafe.h>
|
||||
#include <ntintsafe.h>
|
||||
|
||||
#include <dispmprt.h>
|
||||
};
|
||||
|
||||
#define EDID_V1_BLOCK_SIZE 128
|
||||
|
||||
#include "BDD_ErrorLog.hxx"
|
||||
|
||||
#define MIN_WIDTH 640
|
||||
#define MIN_HEIGHT 480
|
||||
#define MIN_BITS_PER_PIXEL_ALLOWED 8
|
||||
#define MIN_BYTES_PER_PIXEL_REPORTED 4
|
||||
|
||||
#define DEFAULT_WIDTH 1024
|
||||
#define DEFAULT_HEIGHT 768
|
||||
|
||||
#define MAX_INVALID_INHERITED_WIDTH 1024
|
||||
#define MAX_INVALID_INHERITED_HEIGHT 768
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
|
||||
typedef struct _BLT_INFO
|
||||
{
|
||||
PVOID pBits;
|
||||
UINT Pitch;
|
||||
UINT BitsPerPel;
|
||||
POINT Offset; // To unrotated top-left of dirty rects
|
||||
D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;
|
||||
UINT Width; // For the unrotated image
|
||||
UINT Height; // For the unrotated image
|
||||
} BLT_INFO;
|
||||
|
||||
#define MAX_CHILDREN 1
|
||||
#define MAX_VIEWS 1
|
||||
|
||||
typedef struct _BDD_FLAGS
|
||||
{
|
||||
UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice
|
||||
UINT EDID_Retrieved : 1; // ( 2) EDID was successfully retrieved
|
||||
UINT EDID_ValidChecksum : 1; // ( 3) Retrieved EDID has a valid checksum
|
||||
UINT EDID_ValidHeader : 1; // ( 4) Retrieved EDID has a valid header
|
||||
UINT EDID_Attempted : 1; // ( 5) 1 if an attempt was made to retrieve the EDID, successful or not
|
||||
|
||||
// IMPORTANT: All new flags must be added to just before _LastFlag (i.e. right above this comment), this allows different versions of diagnostics to still be useful.
|
||||
UINT _LastFlag : 1; // ( 6) Always set to 1, is used to ensure that diagnostic version matches binary version
|
||||
UINT Unused : 26;
|
||||
} BDD_FLAGS;
|
||||
|
||||
// Represents the current mode, may not always be set (i.e. frame buffer mapped) if representing the mode passed in on single mode setups.
|
||||
typedef struct _CURRENT_BDD_MODE
|
||||
{
|
||||
// The source mode currently set for HW Framebuffer
|
||||
// For sample driver this info filled in StartDevice by the OS and never changed.
|
||||
DXGK_DISPLAY_INFORMATION DispInfo;
|
||||
|
||||
// The rotation of the current mode. Rotation is performed in software during Present call
|
||||
D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;
|
||||
|
||||
D3DKMDT_VIDPN_PRESENT_PATH_SCALING Scaling;
|
||||
// This mode might be different from one which are supported for HW frame buffer
|
||||
// Scaling/displasment might be needed (if supported)
|
||||
UINT SrcModeWidth;
|
||||
UINT SrcModeHeight;
|
||||
|
||||
// Various boolean flags the struct uses
|
||||
struct _CURRENT_BDD_MODE_FLAGS
|
||||
{
|
||||
UINT SourceNotVisible : 1; // 0 if source is visible
|
||||
UINT FullscreenPresent : 1; // 0 if should use dirty rects for present
|
||||
UINT FrameBufferIsActive : 1; // 0 if not currently active (i.e. target not connected to source)
|
||||
UINT DoNotMapOrUnmap : 1; // 1 if the FrameBuffer should not be (un)mapped during normal execution
|
||||
UINT IsInternal : 1; // 1 if it was determined (i.e. through ACPI) that an internal panel is being driven
|
||||
UINT Unused : 27;
|
||||
} Flags;
|
||||
|
||||
// The start and end of physical memory known to be all zeroes. Used to optimize the BlackOutScreen function to not write
|
||||
// zeroes to memory already known to be zero. (Physical address is located in DispInfo)
|
||||
PHYSICAL_ADDRESS ZeroedOutStart;
|
||||
PHYSICAL_ADDRESS ZeroedOutEnd;
|
||||
|
||||
// Linear frame buffer pointer
|
||||
// A union with a ULONG64 is used here to ensure this struct looks the same on 32bit and 64bit builds
|
||||
// since the size of a VOID* changes depending on the build.
|
||||
union
|
||||
{
|
||||
VOID* Ptr;
|
||||
ULONG64 Force8Bytes;
|
||||
} FrameBuffer;
|
||||
} CURRENT_BDD_MODE;
|
||||
|
||||
class BASIC_DISPLAY_DRIVER;
|
||||
|
||||
class BDD_HWBLT
|
||||
{
|
||||
public:
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SourceId;
|
||||
BASIC_DISPLAY_DRIVER* m_DevExt;
|
||||
BOOLEAN m_SynchExecution;
|
||||
HANDLE m_hPresentWorkerThread;
|
||||
PVOID m_pPresentWorkerThread;
|
||||
|
||||
// Events to contol thread execution
|
||||
KEVENT m_hThreadStartupEvent;
|
||||
KEVENT m_hThreadSuspendEvent;
|
||||
|
||||
BDD_HWBLT();
|
||||
|
||||
~BDD_HWBLT();
|
||||
|
||||
void Initialize(_In_ BASIC_DISPLAY_DRIVER* DevExt, _In_ UINT IdSrc) { m_DevExt = DevExt; m_SourceId = IdSrc; }
|
||||
void SetPresentWorkerThreadInfo(HANDLE hWorkerThread);
|
||||
NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr,
|
||||
_In_ UINT DstBitPerPixel,
|
||||
_In_ BYTE* SrcAddr,
|
||||
_In_ UINT SrcBytesPerPixel,
|
||||
_In_ LONG SrcPitch,
|
||||
_In_ ULONG NumMoves,
|
||||
_In_ D3DKMT_MOVE_RECT* pMoves,
|
||||
_In_ ULONG NumDirtyRects,
|
||||
_In_ RECT* pDirtyRect,
|
||||
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation);
|
||||
|
||||
};
|
||||
|
||||
class BASIC_DISPLAY_DRIVER
|
||||
{
|
||||
private:
|
||||
DEVICE_OBJECT* m_pPhysicalDevice;
|
||||
DXGKRNL_INTERFACE m_DxgkInterface;
|
||||
|
||||
// Information passed in by StartDevice DDI
|
||||
DXGK_START_INFO m_StartInfo;
|
||||
|
||||
|
||||
// Array of EDIDs, currently only supporting base block, hence EDID_V1_BLOCK_SIZE for size of each EDID
|
||||
BYTE m_EDIDs[MAX_CHILDREN][EDID_V1_BLOCK_SIZE];
|
||||
|
||||
CURRENT_BDD_MODE m_CurrentModes[MAX_VIEWS];
|
||||
|
||||
|
||||
BDD_HWBLT m_HardwareBlt[MAX_VIEWS];
|
||||
|
||||
// Current monitorpower state (this needs to be changed if MAX_CHILDREN != 1)
|
||||
DEVICE_POWER_STATE m_MonitorPowerState;
|
||||
|
||||
// Current adapter power state
|
||||
DEVICE_POWER_STATE m_AdapterPowerState;
|
||||
|
||||
// Source ID to be used by SystemDisplay functions
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId;
|
||||
|
||||
// Various boolean flags the class uses
|
||||
BDD_FLAGS m_Flags;
|
||||
|
||||
// Device information
|
||||
DXGK_DEVICE_INFO m_DeviceInfo;
|
||||
|
||||
public:
|
||||
BASIC_DISPLAY_DRIVER(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);
|
||||
~BASIC_DISPLAY_DRIVER();
|
||||
|
||||
#pragma code_seg(push)
|
||||
#pragma code_seg()
|
||||
BOOLEAN IsDriverActive() const
|
||||
{
|
||||
return m_Flags.DriverStarted;
|
||||
}
|
||||
#pragma code_seg(pop)
|
||||
|
||||
NTSTATUS StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
|
||||
_In_ DXGKRNL_INTERFACE* pDxgkInterface,
|
||||
_Out_ ULONG* pNumberOfViews,
|
||||
_Out_ ULONG* pNumberOfChildren);
|
||||
|
||||
NTSTATUS StopDevice(VOID);
|
||||
|
||||
// Must be Non-Paged
|
||||
VOID ResetDevice(VOID);
|
||||
|
||||
|
||||
const CURRENT_BDD_MODE* GetCurrentMode(UINT SourceId) const
|
||||
{
|
||||
return (SourceId < MAX_VIEWS)?&m_CurrentModes[SourceId]:NULL;
|
||||
}
|
||||
const DXGKRNL_INTERFACE* GetDxgkInterface() const { return &m_DxgkInterface;}
|
||||
|
||||
// Not implemented since no IOCTLs currently handled.
|
||||
NTSTATUS DispatchIoRequest(_In_ ULONG VidPnSourceId,
|
||||
_In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket);
|
||||
|
||||
// Used to either turn off/on monitor (if possible), or mark that system is going into hibernate
|
||||
NTSTATUS SetPowerState(_In_ ULONG HardwareUid,
|
||||
_In_ DEVICE_POWER_STATE DevicePowerState,
|
||||
_In_ POWER_ACTION ActionType);
|
||||
|
||||
// Report back child capabilities
|
||||
NTSTATUS QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
|
||||
_In_ ULONG ChildRelationsSize);
|
||||
|
||||
NTSTATUS QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus,
|
||||
_In_ BOOLEAN NonDestructiveOnly);
|
||||
|
||||
// Return EDID if previously retrieved
|
||||
NTSTATUS QueryDeviceDescriptor(_In_ ULONG ChildUid,
|
||||
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);
|
||||
|
||||
// Must be Non-Paged
|
||||
// BDD doesn't have interrupts, so just returns false
|
||||
BOOLEAN InterruptRoutine(_In_ ULONG MessageNumber);
|
||||
|
||||
VOID DpcRoutine(VOID);
|
||||
|
||||
// Return DriverCaps, doesn't support other queries though
|
||||
NTSTATUS QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo);
|
||||
|
||||
NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
|
||||
|
||||
NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
|
||||
|
||||
NTSTATUS PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);
|
||||
|
||||
NTSTATUS IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn);
|
||||
|
||||
NTSTATUS RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn);
|
||||
|
||||
NTSTATUS RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology);
|
||||
|
||||
NTSTATUS RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
|
||||
|
||||
NTSTATUS EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality);
|
||||
|
||||
NTSTATUS SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility);
|
||||
|
||||
NTSTATUS CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn);
|
||||
|
||||
NTSTATUS UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath);
|
||||
|
||||
NTSTATUS QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps);
|
||||
|
||||
// Part of PnPStop (PnP instance only), returns current mode information (which will be passed to fallback instance by dxgkrnl)
|
||||
NTSTATUS StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo);
|
||||
|
||||
// Must be Non-Paged
|
||||
// Call to initialize as part of bugcheck
|
||||
NTSTATUS SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
|
||||
_Out_ UINT* pWidth,
|
||||
_Out_ UINT* pHeight,
|
||||
_Out_ D3DDDIFORMAT* pColorFormat);
|
||||
|
||||
// Must be Non-Paged
|
||||
// Write out pixels as part of bugcheck
|
||||
VOID SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,
|
||||
_In_ UINT SourceWidth,
|
||||
_In_ UINT SourceHeight,
|
||||
_In_ UINT SourceStride,
|
||||
_In_ INT PositionX,
|
||||
_In_ INT PositionY);
|
||||
|
||||
|
||||
private:
|
||||
VOID CleanUp();
|
||||
|
||||
NTSTATUS CommonStart();
|
||||
|
||||
NTSTATUS GetEdid(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId);
|
||||
|
||||
|
||||
// Given pixel format, give back the bits per pixel. Only supports pixel formats expected by BDD
|
||||
// (i.e. the ones found below in PixelFormatFromBPP or that may come in from FallbackStart)
|
||||
// This is because these two functions combine to allow BDD to store the bpp of a VBE mode in the
|
||||
// ColorFormat field of a DispInfo
|
||||
UINT BPPFromPixelFormat(D3DDDIFORMAT Format) const
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case D3DDDIFMT_UNKNOWN: return 0;
|
||||
case D3DDDIFMT_P8: return 8;
|
||||
case D3DDDIFMT_R5G6B5: return 16;
|
||||
case D3DDDIFMT_R8G8B8: return 24;
|
||||
case D3DDDIFMT_X8R8G8B8: // fall through
|
||||
case D3DDDIFMT_A8R8G8B8: return 32;
|
||||
default: BDD_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Given bits per pixel, return the pixel format at the same bpp
|
||||
D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) const
|
||||
{
|
||||
switch (BPP)
|
||||
{
|
||||
case 8: return D3DDDIFMT_P8;
|
||||
case 16: return D3DDDIFMT_R5G6B5;
|
||||
case 24: return D3DDDIFMT_R8G8B8;
|
||||
case 32: return D3DDDIFMT_X8R8G8B8;
|
||||
default: BDD_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// These two functions make checks on the values of some of the fields of their respective structures to ensure
|
||||
// that the specified fields are supported by BDD, i.e. gamma ramp must be D3DDDI_GAMMARAMP_DEFAULT
|
||||
NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const;
|
||||
NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;
|
||||
|
||||
VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
|
||||
|
||||
// Returns the index into gBddBiosData.BddModes of the VBE mode that matches the given VidPnSourceMode.
|
||||
// If such a mode cannot be found, returns a number outside of [0, gBddBiosData.CountBddModes)
|
||||
UINT FindMatchingVBEMode(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;
|
||||
|
||||
// Must be Non-Paged
|
||||
// Returns the SourceId that has TargetId as a valid frame buffer or D3DDDI_ID_UNINITIALIZED if no such SourceId exists
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero);
|
||||
|
||||
// Set the given source mode on the given path
|
||||
NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode,
|
||||
CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath);
|
||||
|
||||
|
||||
// Add the current mode to the given monitor source mode set
|
||||
NTSTATUS AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
|
||||
|
||||
|
||||
// Add the current mode to the given VidPn source mode set
|
||||
NTSTATUS AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface,
|
||||
D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet,
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
|
||||
|
||||
// Add the current mode (or the matching to pinned source mode) to the give VidPn target mode set
|
||||
NTSTATUS AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface,
|
||||
D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet,
|
||||
_In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo,
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
|
||||
|
||||
// Check that the hardware the driver is running on is hardware it is capable of driving.
|
||||
NTSTATUS CheckHardware();
|
||||
|
||||
// Helper function for RegisterHWInfo
|
||||
NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue);
|
||||
|
||||
// Set the information in the registry as described here: http://msdn.microsoft.com/en-us/library/windows/hardware/ff569240(v=vs.85).aspx
|
||||
NTSTATUS RegisterHWInfo();
|
||||
};
|
||||
|
||||
//
|
||||
// Blt functions
|
||||
//
|
||||
|
||||
// Must be Non-Paged
|
||||
VOID BltBits(
|
||||
BLT_INFO* pDst,
|
||||
CONST BLT_INFO* pSrc,
|
||||
UINT NumRects,
|
||||
_In_reads_(NumRects) CONST RECT *pRects);
|
||||
|
||||
//
|
||||
// Driver Entry point
|
||||
//
|
||||
|
||||
extern "C"
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
//
|
||||
// PnP DDIs
|
||||
//
|
||||
|
||||
VOID
|
||||
BddDdiUnload(VOID);
|
||||
|
||||
// If uncommenting ENABLE_DXGK_SAL in the sources file, all the below function prototypes should be updated to use
|
||||
// the function typedef's from the header files. Additionally, annotations on the function definitions can be removed
|
||||
// as they are inherited from the prototype definition here. As an example the entire 4-line prototype for BddDdiAddDevice
|
||||
// is replaced by the single commented line below:
|
||||
// DXGKDDI_ADD_DEVICE BddDdiAddDevice;
|
||||
NTSTATUS
|
||||
BddDdiAddDevice(
|
||||
_In_ DEVICE_OBJECT* pPhysicalDeviceObject,
|
||||
_Outptr_ PVOID* ppDeviceContext);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiRemoveDevice(
|
||||
_In_ VOID* pDeviceContext);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiStartDevice(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ DXGK_START_INFO* pDxgkStartInfo,
|
||||
_In_ DXGKRNL_INTERFACE* pDxgkInterface,
|
||||
_Out_ ULONG* pNumberOfViews,
|
||||
_Out_ ULONG* pNumberOfChildren);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiStopDevice(
|
||||
_In_ VOID* pDeviceContext);
|
||||
|
||||
VOID
|
||||
BddDdiResetDevice(
|
||||
_In_ VOID* pDeviceContext);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
BddDdiDispatchIoRequest(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG VidPnSourceId,
|
||||
_In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiSetPowerState(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG HardwareUid,
|
||||
_In_ DEVICE_POWER_STATE DevicePowerState,
|
||||
_In_ POWER_ACTION ActionType);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiQueryChildRelations(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
|
||||
_In_ ULONG ChildRelationsSize);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiQueryChildStatus(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_Inout_ DXGK_CHILD_STATUS* pChildStatus,
|
||||
_In_ BOOLEAN NonDestructiveOnly);
|
||||
|
||||
NTSTATUS
|
||||
BddDdiQueryDeviceDescriptor(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG ChildUid,
|
||||
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);
|
||||
|
||||
// Must be Non-Paged
|
||||
BOOLEAN
|
||||
BddDdiInterruptRoutine(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG MessageNumber);
|
||||
|
||||
VOID
|
||||
BddDdiDpcRoutine(
|
||||
_In_ VOID* pDeviceContext);
|
||||
|
||||
//
|
||||
// WDDM Display Only Driver DDIs
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiQueryAdapterInfo(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSetPointerPosition(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSetPointerShape(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiPresentDisplayOnly(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiIsSupportedVidPn(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiRecommendFunctionalVidPn(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiRecommendVidPnTopology(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiRecommendMonitorModes(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiEnumVidPnCofuncModality(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSetVidPnSourceVisibility(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiCommitVidPn(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiUpdateActiveVidPnPresentPath(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiQueryVidPnHWCapability(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps);
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiStopDeviceAndReleasePostDisplayOwnership(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo);
|
||||
|
||||
// Must be Non-Paged
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSystemDisplayEnable(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
|
||||
_Out_ UINT* Width,
|
||||
_Out_ UINT* Height,
|
||||
_Out_ D3DDDIFORMAT* ColorFormat);
|
||||
|
||||
// Must be Non-Paged
|
||||
VOID
|
||||
APIENTRY
|
||||
BddDdiSystemDisplayWrite(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ VOID* Source,
|
||||
_In_ UINT SourceWidth,
|
||||
_In_ UINT SourceHeight,
|
||||
_In_ UINT SourceStride,
|
||||
_In_ UINT PositionX,
|
||||
_In_ UINT PositionY);
|
||||
|
||||
//
|
||||
// Frame buffer map/unmap
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
MapFrameBuffer(
|
||||
_In_ PHYSICAL_ADDRESS PhysicalAddress,
|
||||
_In_ ULONG Length,
|
||||
_Outptr_result_bytebuffer_(Length) VOID** VirtualAddress);
|
||||
|
||||
NTSTATUS
|
||||
UnmapFrameBuffer(
|
||||
_In_reads_bytes_(Length) VOID* VirtualAddress,
|
||||
_In_ ULONG Length);
|
||||
|
||||
|
||||
BOOLEAN
|
||||
IsEdidHeaderValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid);
|
||||
|
||||
BOOLEAN
|
||||
IsEdidChecksumValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid);
|
||||
|
||||
//
|
||||
// Memory handling
|
||||
//
|
||||
|
||||
// Defaulting the value of PoolType means that any call to new Foo()
|
||||
// will raise a compiler error for being ambiguous. This is to help keep
|
||||
// any calls to allocate memory from accidentally NOT going through
|
||||
// these functions.
|
||||
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
|
||||
__drv_reportError("Must succeed pool allocations are forbidden. "
|
||||
"Allocation failures cause a system crash"))
|
||||
void* __cdecl operator new(size_t Size, POOL_TYPE PoolType = PagedPool);
|
||||
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
|
||||
__drv_reportError("Must succeed pool allocations are forbidden. "
|
||||
"Allocation failures cause a system crash"))
|
||||
void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType = PagedPool);
|
||||
void __cdecl operator delete(void* pObject);
|
||||
void __cdecl operator delete(void* pObject, size_t s);
|
||||
void __cdecl operator delete[](void* pObject);
|
||||
|
||||
// Pool allocation tag for the Sample Display Driver. All allocations use this tag.
|
||||
#define BDDTAG 'DDBS'
|
||||
|
||||
#endif // _BDD_HXX_
|
||||
|
||||
|
||||
@@ -1,579 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: BDD_DDI.cxx
|
||||
*
|
||||
* Basic Display Driver DDI entry points redirects
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
#include "BDD.hxx"
|
||||
|
||||
|
||||
#pragma code_seg(push)
|
||||
#pragma code_seg("INIT")
|
||||
// BEGIN: Init Code
|
||||
|
||||
//
|
||||
// Driver Entry point
|
||||
//
|
||||
|
||||
extern "C"
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
_In_ DRIVER_OBJECT* pDriverObject,
|
||||
_In_ UNICODE_STRING* pRegistryPath)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
||||
// Initialize DDI function pointers and dxgkrnl
|
||||
KMDDOD_INITIALIZATION_DATA InitialData = {0};
|
||||
|
||||
InitialData.Version = DXGKDDI_INTERFACE_VERSION;
|
||||
|
||||
InitialData.DxgkDdiAddDevice = BddDdiAddDevice;
|
||||
InitialData.DxgkDdiStartDevice = BddDdiStartDevice;
|
||||
InitialData.DxgkDdiStopDevice = BddDdiStopDevice;
|
||||
InitialData.DxgkDdiResetDevice = BddDdiResetDevice;
|
||||
InitialData.DxgkDdiRemoveDevice = BddDdiRemoveDevice;
|
||||
InitialData.DxgkDdiDispatchIoRequest = BddDdiDispatchIoRequest;
|
||||
InitialData.DxgkDdiInterruptRoutine = BddDdiInterruptRoutine;
|
||||
InitialData.DxgkDdiDpcRoutine = BddDdiDpcRoutine;
|
||||
InitialData.DxgkDdiQueryChildRelations = BddDdiQueryChildRelations;
|
||||
InitialData.DxgkDdiQueryChildStatus = BddDdiQueryChildStatus;
|
||||
InitialData.DxgkDdiQueryDeviceDescriptor = BddDdiQueryDeviceDescriptor;
|
||||
InitialData.DxgkDdiSetPowerState = BddDdiSetPowerState;
|
||||
InitialData.DxgkDdiUnload = BddDdiUnload;
|
||||
InitialData.DxgkDdiQueryAdapterInfo = BddDdiQueryAdapterInfo;
|
||||
InitialData.DxgkDdiSetPointerPosition = BddDdiSetPointerPosition;
|
||||
InitialData.DxgkDdiSetPointerShape = BddDdiSetPointerShape;
|
||||
InitialData.DxgkDdiIsSupportedVidPn = BddDdiIsSupportedVidPn;
|
||||
InitialData.DxgkDdiRecommendFunctionalVidPn = BddDdiRecommendFunctionalVidPn;
|
||||
InitialData.DxgkDdiEnumVidPnCofuncModality = BddDdiEnumVidPnCofuncModality;
|
||||
InitialData.DxgkDdiSetVidPnSourceVisibility = BddDdiSetVidPnSourceVisibility;
|
||||
InitialData.DxgkDdiCommitVidPn = BddDdiCommitVidPn;
|
||||
InitialData.DxgkDdiUpdateActiveVidPnPresentPath = BddDdiUpdateActiveVidPnPresentPath;
|
||||
InitialData.DxgkDdiRecommendMonitorModes = BddDdiRecommendMonitorModes;
|
||||
InitialData.DxgkDdiQueryVidPnHWCapability = BddDdiQueryVidPnHWCapability;
|
||||
InitialData.DxgkDdiPresentDisplayOnly = BddDdiPresentDisplayOnly;
|
||||
InitialData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = BddDdiStopDeviceAndReleasePostDisplayOwnership;
|
||||
InitialData.DxgkDdiSystemDisplayEnable = BddDdiSystemDisplayEnable;
|
||||
InitialData.DxgkDdiSystemDisplayWrite = BddDdiSystemDisplayWrite;
|
||||
|
||||
NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject, pRegistryPath, &InitialData);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BDD_LOG_ERROR1("DxgkInitializeDisplayOnlyDriver failed with Status: 0x%I64x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
return Status;
|
||||
}
|
||||
// END: Init Code
|
||||
#pragma code_seg(pop)
|
||||
|
||||
#pragma code_seg(push)
|
||||
#pragma code_seg("PAGE")
|
||||
|
||||
//
|
||||
// PnP DDIs
|
||||
//
|
||||
|
||||
VOID
|
||||
BddDdiUnload(VOID)
|
||||
{
|
||||
PAGED_CODE();
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiAddDevice(
|
||||
_In_ DEVICE_OBJECT* pPhysicalDeviceObject,
|
||||
_Outptr_ PVOID* ppDeviceContext)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if ((pPhysicalDeviceObject == NULL) ||
|
||||
(ppDeviceContext == NULL))
|
||||
{
|
||||
BDD_LOG_ERROR2("One of pPhysicalDeviceObject (0x%I64x), ppDeviceContext (0x%I64x) is NULL",
|
||||
pPhysicalDeviceObject, ppDeviceContext);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
*ppDeviceContext = NULL;
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = new(NonPagedPoolNx) BASIC_DISPLAY_DRIVER(pPhysicalDeviceObject);
|
||||
if (pBDD == NULL)
|
||||
{
|
||||
BDD_LOG_LOW_RESOURCE0("pBDD failed to be allocated");
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*ppDeviceContext = pBDD;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiRemoveDevice(
|
||||
_In_ VOID* pDeviceContext)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
|
||||
if (pBDD)
|
||||
{
|
||||
delete pBDD;
|
||||
pBDD = NULL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiStartDevice(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ DXGK_START_INFO* pDxgkStartInfo,
|
||||
_In_ DXGKRNL_INTERFACE* pDxgkInterface,
|
||||
_Out_ ULONG* pNumberOfViews,
|
||||
_Out_ ULONG* pNumberOfChildren)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiStopDevice(
|
||||
_In_ VOID* pDeviceContext)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->StopDevice();
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
BddDdiDispatchIoRequest(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG VidPnSourceId,
|
||||
_In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->DispatchIoRequest(VidPnSourceId, pVideoRequestPacket);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiSetPowerState(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG HardwareUid,
|
||||
_In_ DEVICE_POWER_STATE DevicePowerState,
|
||||
_In_ POWER_ACTION ActionType)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
// If the driver isn't active, SetPowerState can still be called, however in BDD's case
|
||||
// this shouldn't do anything, as it could for instance be called on BDD Fallback after
|
||||
// Fallback has been stopped and BDD PnP is being started. Fallback doesn't have control
|
||||
// of the hardware in this case.
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return pBDD->SetPowerState(HardwareUid, DevicePowerState, ActionType);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiQueryChildRelations(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
|
||||
_In_ ULONG ChildRelationsSize)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->QueryChildRelations(pChildRelations, ChildRelationsSize);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiQueryChildStatus(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_Inout_ DXGK_CHILD_STATUS* pChildStatus,
|
||||
_In_ BOOLEAN NonDestructiveOnly)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->QueryChildStatus(pChildStatus, NonDestructiveOnly);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BddDdiQueryDeviceDescriptor(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG ChildUid,
|
||||
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
// During stress testing of PnPStop, it is possible for BDD Fallback to get called to start then stop in quick succession.
|
||||
// The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread
|
||||
// item that it no longer has any child device. This function gets called based on the first worker thread item, but after
|
||||
// the driver has been stopped. Therefore instead of asserting like other functions, we only warn.
|
||||
BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// WDDM Display Only Driver DDIs
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiQueryAdapterInfo(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
return pBDD->QueryAdapterInfo(pQueryAdapterInfo);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSetPointerPosition(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->SetPointerPosition(pSetPointerPosition);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSetPointerShape(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->SetPointerShape(pSetPointerShape);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiPresentDisplayOnly(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->PresentDisplayOnly(pPresentDisplayOnly);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiStopDeviceAndReleasePostDisplayOwnership(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiIsSupportedVidPn(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
// This path might hit because win32k/dxgport doesn't check that an adapter is active when taking the adapter lock.
|
||||
// The adapter lock is the main thing BDD Fallback relies on to not be called while it's inactive. It is still a rare
|
||||
// timing issue around PnpStart/Stop and isn't expected to have any effect on the stability of the system.
|
||||
BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->IsSupportedVidPn(pIsSupportedVidPn);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiRecommendFunctionalVidPn(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->RecommendFunctionalVidPn(pRecommendFunctionalVidPn);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiRecommendVidPnTopology(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->RecommendVidPnTopology(pRecommendVidPnTopology);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiRecommendMonitorModes(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->RecommendMonitorModes(pRecommendMonitorModes);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiEnumVidPnCofuncModality(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->EnumVidPnCofuncModality(pEnumCofuncModality);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSetVidPnSourceVisibility(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->SetVidPnSourceVisibility(pSetVidPnSourceVisibility);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiCommitVidPn(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->CommitVidPn(pCommitVidPn);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiUpdateActiveVidPnPresentPath(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiQueryVidPnHWCapability(
|
||||
_In_ CONST HANDLE hAdapter,
|
||||
_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
|
||||
{
|
||||
PAGED_CODE();
|
||||
BDD_ASSERT_CHK(hAdapter != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return pBDD->QueryVidPnHWCapability(pVidPnHWCaps);
|
||||
}
|
||||
//END: Paged Code
|
||||
#pragma code_seg(pop)
|
||||
|
||||
#pragma code_seg(push)
|
||||
#pragma code_seg()
|
||||
// BEGIN: Non-Paged Code
|
||||
|
||||
VOID
|
||||
BddDdiDpcRoutine(
|
||||
_In_ VOID* pDeviceContext)
|
||||
{
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
if (!pBDD->IsDriverActive())
|
||||
{
|
||||
BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
|
||||
return;
|
||||
}
|
||||
pBDD->DpcRoutine();
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
BddDdiInterruptRoutine(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ ULONG MessageNumber)
|
||||
{
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->InterruptRoutine(MessageNumber);
|
||||
}
|
||||
|
||||
VOID
|
||||
BddDdiResetDevice(
|
||||
_In_ VOID* pDeviceContext)
|
||||
{
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
pBDD->ResetDevice();
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
BddDdiSystemDisplayEnable(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
|
||||
_In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
|
||||
_Out_ UINT* Width,
|
||||
_Out_ UINT* Height,
|
||||
_Out_ D3DDDIFORMAT* ColorFormat)
|
||||
{
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
return pBDD->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);
|
||||
}
|
||||
|
||||
VOID
|
||||
APIENTRY
|
||||
BddDdiSystemDisplayWrite(
|
||||
_In_ VOID* pDeviceContext,
|
||||
_In_ VOID* Source,
|
||||
_In_ UINT SourceWidth,
|
||||
_In_ UINT SourceHeight,
|
||||
_In_ UINT SourceStride,
|
||||
_In_ UINT PositionX,
|
||||
_In_ UINT PositionY)
|
||||
{
|
||||
BDD_ASSERT_CHK(pDeviceContext != NULL);
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
|
||||
pBDD->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
|
||||
}
|
||||
|
||||
// END: Non-Paged Code
|
||||
#pragma code_seg(pop)
|
||||
|
||||
-1083
File diff suppressed because it is too large.
Load diff
@@ -1,84 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: BDD_ErrorLog.hxx
|
||||
*
|
||||
* Basic Display Driver Logging Macros
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010 Microsoft Corporation
|
||||
*
|
||||
\**************************************************************************/
|
||||
#ifndef _BDD_ERRORLOG_HXX_
|
||||
#define _BDD_ERRORLOG_HXX_
|
||||
|
||||
#define BDD_LOG_ERROR0(Msg)
|
||||
#define BDD_LOG_ERROR1(Msg,Param1)
|
||||
#define BDD_LOG_ERROR2(Msg,Param1,Param2)
|
||||
#define BDD_LOG_ERROR3(Msg,Param1,Param2,Param3)
|
||||
#define BDD_LOG_ERROR4(Msg,Param1,Param2,Param3,Param4)
|
||||
#define BDD_LOG_ERROR5(Msg,Param1,Param2,Param3,Param4,Param5)
|
||||
|
||||
//
|
||||
// Warnings
|
||||
//
|
||||
|
||||
#define BDD_LOG_WARNING0(Msg)
|
||||
#define BDD_LOG_WARNING1(Msg,Param1)
|
||||
#define BDD_LOG_WARNING2(Msg,Param1,Param2)
|
||||
#define BDD_LOG_WARNING3(Msg,Param1,Param2,Param3)
|
||||
#define BDD_LOG_WARNING4(Msg,Param1,Param2,Param3,Param4)
|
||||
#define BDD_LOG_WARNING5(Msg,Param1,Param2,Param3,Param4,Param5)
|
||||
|
||||
//
|
||||
// Events (i.e. low-frequency tracing)
|
||||
//
|
||||
|
||||
#define BDD_LOG_EVENT0(Msg)
|
||||
#define BDD_LOG_EVENT1(Msg,Param1)
|
||||
#define BDD_LOG_EVENT2(Msg,Param1,Param2)
|
||||
#define BDD_LOG_EVENT3(Msg,Param1,Param2,Param3)
|
||||
#define BDD_LOG_EVENT4(Msg,Param1,Param2,Param3,Param4)
|
||||
#define BDD_LOG_EVENT5(Msg,Param1,Param2,Param3,Param4,Param5)
|
||||
|
||||
//
|
||||
// Information (i.e. high-frequency tracing)
|
||||
//
|
||||
|
||||
#define BDD_LOG_INFORMATION0(Msg)
|
||||
#define BDD_LOG_INFORMATION1(Msg,Param1)
|
||||
#define BDD_LOG_INFORMATION2(Msg,Param1,Param2)
|
||||
#define BDD_LOG_INFORMATION3(Msg,Param1,Param2,Param3)
|
||||
#define BDD_LOG_INFORMATION4(Msg,Param1,Param2,Param3,Param4)
|
||||
#define BDD_LOG_INFORMATION5(Msg,Param1,Param2,Param3,Param4,Param5)
|
||||
|
||||
//
|
||||
// Low resource logging macros.
|
||||
//
|
||||
|
||||
#define BDD_LOG_LOW_RESOURCE0(Msg)
|
||||
#define BDD_LOG_LOW_RESOURCE1(Msg,Param1)
|
||||
#define BDD_LOG_LOW_RESOURCE2(Msg,Param1,Param2)
|
||||
#define BDD_LOG_LOW_RESOURCE3(Msg,Param1,Param2,Param3)
|
||||
#define BDD_LOG_LOW_RESOURCE4(Msg,Param1,Param2,Param3,Param4)
|
||||
#define BDD_LOG_LOW_RESOURCE5(Msg,Param1,Param2,Param3,Param4,Param5)
|
||||
|
||||
//
|
||||
// Assertion logging macros.
|
||||
//
|
||||
|
||||
#define BDD_LOG_ASSERTION0(Msg) NT_ASSERT(FALSE)
|
||||
#define BDD_LOG_ASSERTION1(Msg,Param1) NT_ASSERT(FALSE)
|
||||
#define BDD_LOG_ASSERTION2(Msg,Param1,Param2) NT_ASSERT(FALSE)
|
||||
#define BDD_LOG_ASSERTION3(Msg,Param1,Param2,Param3) NT_ASSERT(FALSE)
|
||||
#define BDD_LOG_ASSERTION4(Msg,Param1,Param2,Param3,Param4) NT_ASSERT(FALSE)
|
||||
#define BDD_LOG_ASSERTION5(Msg,Param1,Param2,Param3,Param4,Param5) NT_ASSERT(FALSE)
|
||||
#define BDD_ASSERT(exp) {if (!(exp)) {BDD_LOG_ASSERTION0(#exp);}}
|
||||
|
||||
#if DBG
|
||||
#define BDD_ASSERT_CHK(exp) BDD_ASSERT(exp)
|
||||
#else
|
||||
#define BDD_ASSERT_CHK(exp) {}
|
||||
#endif
|
||||
|
||||
|
||||
#endif //_BDD_ERRORLOG_HXX_
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: bdd_util.cxx
|
||||
*
|
||||
* Basic Display Driver utility functions
|
||||
*
|
||||
* Created: 29-Mar-2011
|
||||
* Author: Amos Eshel [amosesh]
|
||||
*
|
||||
* Copyright (c) 2011 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
#include "BDD.hxx"
|
||||
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
|
||||
//
|
||||
// EDID validation
|
||||
//
|
||||
|
||||
BOOLEAN IsEdidHeaderValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
static const UCHAR EDID1Header[8] = {0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0};
|
||||
return memcmp(pEdid, EDID1Header, sizeof(EDID1Header)) == 0;
|
||||
}
|
||||
|
||||
BOOLEAN IsEdidChecksumValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BYTE CheckSum = 0;
|
||||
for (const BYTE* pEdidStart = pEdid; pEdidStart < (pEdid + EDID_V1_BLOCK_SIZE); ++pEdidStart)
|
||||
{
|
||||
CheckSum += *pEdidStart;
|
||||
}
|
||||
|
||||
return CheckSum == 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Frame buffer map/unmap
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
MapFrameBuffer(
|
||||
_In_ PHYSICAL_ADDRESS PhysicalAddress,
|
||||
_In_ ULONG Length,
|
||||
_Outptr_result_bytebuffer_(Length) VOID** VirtualAddress)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// Check for parameters
|
||||
//
|
||||
if ((PhysicalAddress.QuadPart == (ULONGLONG)0) ||
|
||||
(Length == 0) ||
|
||||
(VirtualAddress == NULL))
|
||||
{
|
||||
BDD_LOG_ERROR3("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0",
|
||||
PhysicalAddress.QuadPart, Length, VirtualAddress);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*VirtualAddress = MmMapIoSpaceEx(PhysicalAddress,
|
||||
Length,
|
||||
PAGE_READWRITE | PAGE_WRITECOMBINE);
|
||||
if (*VirtualAddress == NULL)
|
||||
{
|
||||
// The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined
|
||||
// isn't supported, so try again with MmNonCached
|
||||
|
||||
*VirtualAddress = MmMapIoSpaceEx(PhysicalAddress,
|
||||
Length,
|
||||
PAGE_READWRITE | PAGE_NOCACHE);
|
||||
if (*VirtualAddress == NULL)
|
||||
{
|
||||
BDD_LOG_LOW_RESOURCE1("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
UnmapFrameBuffer(
|
||||
_In_reads_bytes_(Length) VOID* VirtualAddress,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
||||
//
|
||||
// Check for parameters
|
||||
//
|
||||
if ((VirtualAddress == NULL) && (Length == 0))
|
||||
{
|
||||
// Allow this function to be called when there's no work to do, and treat as successful
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if ((VirtualAddress == NULL) || (Length == 0))
|
||||
{
|
||||
BDD_LOG_ERROR2("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0",
|
||||
Length, VirtualAddress);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MmUnmapIoSpace(VirtualAddress,
|
||||
Length);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,346 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: BltFuncs.cxx
|
||||
*
|
||||
* Basic Display Driver copying functionality
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
#include "BDD.hxx"
|
||||
|
||||
// For the following macros, c must be a UCHAR.
|
||||
#define UPPER_6_BITS(c) (((c) & rMaskTable[6 - 1]) >> 2)
|
||||
#define UPPER_5_BITS(c) (((c) & rMaskTable[5 - 1]) >> 3)
|
||||
#define LOWER_6_BITS(c) (((BYTE)(c)) & lMaskTable[BITS_PER_BYTE - 6])
|
||||
#define LOWER_5_BITS(c) (((BYTE)(c)) & lMaskTable[BITS_PER_BYTE - 5])
|
||||
|
||||
|
||||
#define SHIFT_FOR_UPPER_5_IN_565 (6 + 5)
|
||||
#define SHIFT_FOR_MIDDLE_6_IN_565 (5)
|
||||
#define SHIFT_UPPER_5_IN_565_BACK ((BITS_PER_BYTE * 2) + (BITS_PER_BYTE - 5))
|
||||
#define SHIFT_MIDDLE_6_IN_565_BACK ((BITS_PER_BYTE * 1) + (BITS_PER_BYTE - 6))
|
||||
#define SHIFT_LOWER_5_IN_565_BACK ((BITS_PER_BYTE * 0) + (BITS_PER_BYTE - 5))
|
||||
|
||||
// For the following macros, pPixel must be a BYTE* pointing to the start of a 32 bit pixel
|
||||
#define CONVERT_32BPP_TO_16BPP(pPixel) ((UPPER_5_BITS(pPixel[2]) << SHIFT_FOR_UPPER_5_IN_565) | \
|
||||
(UPPER_6_BITS(pPixel[1]) << SHIFT_FOR_MIDDLE_6_IN_565) | \
|
||||
(UPPER_5_BITS(pPixel[0])))
|
||||
|
||||
// 8bpp is done with 6 levels per color channel since this gives true grays, even if it leaves 40 empty palette entries
|
||||
// The 6 levels per color is the reason for dividing below by 43 (43 * 6 == 258, closest multiple of 6 to 256)
|
||||
// It is also the reason for multiplying the red channel by 36 (== 6*6) and the green channel by 6, as this is the
|
||||
// equivalent to bit shifting in a 3:3:2 model. Changes to this must be reflected in vesasup.cxx with the Blues/Greens/Reds arrays
|
||||
#define CONVERT_32BPP_TO_8BPP(pPixel) (((pPixel[2] / 43) * 36) + \
|
||||
((pPixel[1] / 43) * 6) + \
|
||||
((pPixel[0] / 43)))
|
||||
|
||||
// 4bpp is done with strict grayscale since this has been found to be usable
|
||||
// 30% of the red value, 59% of the green value, and 11% of the blue value is the standard way to convert true color to grayscale
|
||||
#define CONVERT_32BPP_TO_4BPP(pPixel) ((BYTE)(((pPixel[2] * 30) + \
|
||||
(pPixel[1] * 59) + \
|
||||
(pPixel[0] * 11)) / (100 * 16)))
|
||||
|
||||
|
||||
// For the following macro, Pixel must be a WORD representing a 16 bit pixel
|
||||
#define CONVERT_16BPP_TO_32BPP(Pixel) (((ULONG)LOWER_5_BITS((Pixel) >> SHIFT_FOR_UPPER_5_IN_565) << SHIFT_UPPER_5_IN_565_BACK) | \
|
||||
((ULONG)LOWER_6_BITS((Pixel) >> SHIFT_FOR_MIDDLE_6_IN_565) << SHIFT_MIDDLE_6_IN_565_BACK) | \
|
||||
((ULONG)LOWER_5_BITS((Pixel)) << SHIFT_LOWER_5_IN_565_BACK))
|
||||
|
||||
#pragma code_seg(push)
|
||||
#pragma code_seg()
|
||||
// BEGIN: Non-Paged Code
|
||||
|
||||
// Bit is 1 from Idx to end of byte, with bit count starting at high order
|
||||
BYTE lMaskTable[BITS_PER_BYTE] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
|
||||
|
||||
// Bit is 1 from Idx to start of byte, with bit count starting at high order
|
||||
BYTE rMaskTable[BITS_PER_BYTE] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
|
||||
|
||||
// Bit of Idx is 1, with bit count starting at high order
|
||||
BYTE PixelMask[BITS_PER_BYTE] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||
|
||||
/****************************Internal*Routine******************************\
|
||||
* CopyBits32_32
|
||||
*
|
||||
*
|
||||
* Copies rectangles from one surface to another. Both surfaces must have
|
||||
* the same resolution.
|
||||
*
|
||||
* OffsetX, OffsetY - to add to the rectangle coordinates.
|
||||
*
|
||||
* Copied from %SDXROOT%\windows\Core\dxkernel\cdd\enable.cxx (CopySurfBits)
|
||||
*
|
||||
\**************************************************************************/
|
||||
|
||||
VOID CopyBits32_32(
|
||||
BLT_INFO* pDst,
|
||||
CONST BLT_INFO* pSrc,
|
||||
UINT NumRects,
|
||||
_In_reads_(NumRects) CONST RECT *pRects)
|
||||
{
|
||||
NT_ASSERT((pDst->BitsPerPel == 32) &&
|
||||
(pSrc->BitsPerPel == 32));
|
||||
NT_ASSERT((pDst->Rotation == D3DKMDT_VPPR_IDENTITY) &&
|
||||
(pSrc->Rotation == D3DKMDT_VPPR_IDENTITY));
|
||||
|
||||
for (UINT iRect = 0; iRect < NumRects; iRect++)
|
||||
{
|
||||
CONST RECT* pRect = &pRects[iRect];
|
||||
|
||||
NT_ASSERT(pRect->right >= pRect->left);
|
||||
NT_ASSERT(pRect->bottom >= pRect->top);
|
||||
|
||||
UINT NumPixels = pRect->right - pRect->left;
|
||||
UINT NumRows = pRect->bottom - pRect->top;
|
||||
UINT BytesToCopy = NumPixels * 4;
|
||||
BYTE* pStartDst = ((BYTE*)pDst->pBits +
|
||||
(pRect->top + pDst->Offset.y) * pDst->Pitch +
|
||||
(pRect->left + pDst->Offset.x) * 4);
|
||||
CONST BYTE* pStartSrc = ((BYTE*)pSrc->pBits +
|
||||
(pRect->top + pSrc->Offset.y) * pSrc->Pitch +
|
||||
(pRect->left + pSrc->Offset.x) * 4);
|
||||
|
||||
for (UINT i = 0; i < NumRows; ++i)
|
||||
{
|
||||
RtlCopyMemory(pStartDst, pStartSrc, BytesToCopy);
|
||||
pStartDst += pDst->Pitch;
|
||||
pStartSrc += pSrc->Pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch)
|
||||
{
|
||||
switch (pBltInfo->Rotation)
|
||||
{
|
||||
case D3DKMDT_VPPR_IDENTITY:
|
||||
{
|
||||
*pPixelPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE);
|
||||
*pRowPitch = pBltInfo->Pitch;
|
||||
return;
|
||||
}
|
||||
case D3DKMDT_VPPR_ROTATE90:
|
||||
{
|
||||
*pPixelPitch = -((LONG)pBltInfo->Pitch);
|
||||
*pRowPitch = (pBltInfo->BitsPerPel / BITS_PER_BYTE);
|
||||
return;
|
||||
}
|
||||
case D3DKMDT_VPPR_ROTATE180:
|
||||
{
|
||||
*pPixelPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE);
|
||||
*pRowPitch = -((LONG)pBltInfo->Pitch);
|
||||
return;
|
||||
}
|
||||
case D3DKMDT_VPPR_ROTATE270:
|
||||
{
|
||||
*pPixelPitch = pBltInfo->Pitch;
|
||||
*pRowPitch = -((LONG)pBltInfo->BitsPerPel / BITS_PER_BYTE);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BDD_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation);
|
||||
*pPixelPitch = 0;
|
||||
*pRowPitch = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect)
|
||||
{
|
||||
BYTE* pRet = NULL;
|
||||
LONG OffLeft = pRect->left + pBltInfo->Offset.x;
|
||||
LONG OffTop = pRect->top + pBltInfo->Offset.y;
|
||||
LONG BytesPerPixel = (pBltInfo->BitsPerPel / BITS_PER_BYTE);
|
||||
switch (pBltInfo->Rotation)
|
||||
{
|
||||
case D3DKMDT_VPPR_IDENTITY:
|
||||
{
|
||||
pRet = ((BYTE*)pBltInfo->pBits +
|
||||
OffTop * pBltInfo->Pitch +
|
||||
OffLeft * BytesPerPixel);
|
||||
break;
|
||||
}
|
||||
case D3DKMDT_VPPR_ROTATE90:
|
||||
{
|
||||
pRet = ((BYTE*)pBltInfo->pBits +
|
||||
(pBltInfo->Height - 1 - OffLeft) * pBltInfo->Pitch +
|
||||
OffTop * BytesPerPixel);
|
||||
break;
|
||||
}
|
||||
case D3DKMDT_VPPR_ROTATE180:
|
||||
{
|
||||
pRet = ((BYTE*)pBltInfo->pBits +
|
||||
(pBltInfo->Height - 1 - OffTop) * pBltInfo->Pitch +
|
||||
(pBltInfo->Width - 1 - OffLeft) * BytesPerPixel);
|
||||
break;
|
||||
}
|
||||
case D3DKMDT_VPPR_ROTATE270:
|
||||
{
|
||||
pRet = ((BYTE*)pBltInfo->pBits +
|
||||
OffLeft * pBltInfo->Pitch +
|
||||
(pBltInfo->Width - 1 - OffTop) * BytesPerPixel);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BDD_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/****************************Internal*Routine******************************\
|
||||
* CopyBitsGeneric
|
||||
*
|
||||
*
|
||||
* Blt function which can handle a rotated dst/src, offset rects in dst/src
|
||||
* and bpp combinations of:
|
||||
* dst | src
|
||||
* 32 | 32 // For identity rotation this is much faster in CopyBits32_32
|
||||
* 32 | 24
|
||||
* 32 | 16
|
||||
* 24 | 32
|
||||
* 16 | 32
|
||||
* 8 | 32
|
||||
* 24 | 24 // untested
|
||||
*
|
||||
\**************************************************************************/
|
||||
|
||||
VOID CopyBitsGeneric(
|
||||
BLT_INFO* pDst,
|
||||
CONST BLT_INFO* pSrc,
|
||||
UINT NumRects,
|
||||
_In_reads_(NumRects) CONST RECT *pRects)
|
||||
{
|
||||
LONG DstPixelPitch = 0;
|
||||
LONG DstRowPitch = 0;
|
||||
LONG SrcPixelPitch = 0;
|
||||
LONG SrcRowPitch = 0;
|
||||
|
||||
GetPitches(pDst, &DstPixelPitch, &DstRowPitch);
|
||||
GetPitches(pSrc, &SrcPixelPitch, &SrcRowPitch);
|
||||
|
||||
for (UINT iRect = 0; iRect < NumRects; iRect++)
|
||||
{
|
||||
CONST RECT* pRect = &pRects[iRect];
|
||||
|
||||
NT_ASSERT(pRect->right >= pRect->left);
|
||||
NT_ASSERT(pRect->bottom >= pRect->top);
|
||||
|
||||
UINT NumPixels = pRect->right - pRect->left;
|
||||
UINT NumRows = pRect->bottom - pRect->top;
|
||||
|
||||
BYTE* pDstRow = GetRowStart(pDst, pRect);
|
||||
CONST BYTE* pSrcRow = GetRowStart(pSrc, pRect);
|
||||
|
||||
for (UINT y=0; y < NumRows; y++)
|
||||
{
|
||||
BYTE* pDstPixel = pDstRow;
|
||||
CONST BYTE* pSrcPixel = pSrcRow;
|
||||
|
||||
for (UINT x=0; x < NumPixels; x++)
|
||||
{
|
||||
if ((pDst->BitsPerPel == 24) ||
|
||||
(pSrc->BitsPerPel == 24))
|
||||
{
|
||||
pDstPixel[0] = pSrcPixel[0];
|
||||
pDstPixel[1] = pSrcPixel[1];
|
||||
pDstPixel[2] = pSrcPixel[2];
|
||||
// pPixel[3] is the alpha channel and is ignored for whichever of Src/Dst is 32bpp
|
||||
}
|
||||
else if (pDst->BitsPerPel == 32)
|
||||
{
|
||||
if (pSrc->BitsPerPel == 32)
|
||||
{
|
||||
UINT32* pDstPixelAs32 = (UINT32*)pDstPixel;
|
||||
UINT32* pSrcPixelAs32 = (UINT32*)pSrcPixel;
|
||||
*pDstPixelAs32 = *pSrcPixelAs32;
|
||||
}
|
||||
else if (pSrc->BitsPerPel == 16)
|
||||
{
|
||||
UINT32* pDstPixelAs32 = (UINT32*)pDstPixel;
|
||||
UINT16* pSrcPixelAs16 = (UINT16*)pSrcPixel;
|
||||
|
||||
*pDstPixelAs32 = CONVERT_16BPP_TO_32BPP(*pSrcPixelAs16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid pSrc->BitsPerPel on a pDst->BitsPerPel of 32
|
||||
NT_ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
else if (pDst->BitsPerPel == 16)
|
||||
{
|
||||
NT_ASSERT(pSrc->BitsPerPel == 32);
|
||||
|
||||
UINT16* pDstPixelAs16 = (UINT16*)pDstPixel;
|
||||
*pDstPixelAs16 = CONVERT_32BPP_TO_16BPP(pSrcPixel);
|
||||
}
|
||||
else if (pDst->BitsPerPel == 8)
|
||||
{
|
||||
NT_ASSERT(pSrc->BitsPerPel == 32);
|
||||
|
||||
*pDstPixel = CONVERT_32BPP_TO_8BPP(pSrcPixel);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid pDst->BitsPerPel
|
||||
NT_ASSERT(FALSE);
|
||||
}
|
||||
pDstPixel += DstPixelPitch;
|
||||
pSrcPixel += SrcPixelPitch;
|
||||
}
|
||||
|
||||
pDstRow += DstRowPitch;
|
||||
pSrcRow += SrcRowPitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************Internal*Routine******************************\
|
||||
* BltBits
|
||||
*
|
||||
*
|
||||
* Logic to decide which of the above functions to call based on Rotation/BPP
|
||||
*
|
||||
\**************************************************************************/
|
||||
VOID BltBits(
|
||||
BLT_INFO* pDst,
|
||||
CONST BLT_INFO* pSrc,
|
||||
UINT NumRects,
|
||||
_In_reads_(NumRects) CONST RECT *pRects)
|
||||
{
|
||||
// pSrc->pBits might be coming from user-mode. User-mode addresses when accessed by kernel need to be protected by a __try/__except.
|
||||
// This usage is redundant in the sample driver since it is already being used for MmProbeAndLockPages. However, it is very important
|
||||
// to have this in place and to make sure developers don't miss it, it is in these two locations.
|
||||
__try
|
||||
{
|
||||
if (pDst->BitsPerPel == 32 &&
|
||||
pSrc->BitsPerPel == 32 &&
|
||||
pDst->Rotation == D3DKMDT_VPPR_IDENTITY &&
|
||||
pSrc->Rotation == D3DKMDT_VPPR_IDENTITY)
|
||||
{
|
||||
// This is by far the most common copy function being called
|
||||
CopyBits32_32(pDst, pSrc, NumRects, pRects);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyBitsGeneric(pDst, pSrc, NumRects, pRects);
|
||||
}
|
||||
}
|
||||
#pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here");
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
BDD_LOG_ERROR2("Either dst (0x%I64x) or src (0x%I64x) bits encountered exception during access.", pDst->pBits, pSrc->pBits);
|
||||
}
|
||||
}
|
||||
|
||||
// END: Non-Paged Code
|
||||
#pragma code_seg(pop)
|
||||
|
||||
-556
@@ -1,556 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: blthw.cxx
|
||||
*
|
||||
* Sample display driver functions for a HW blt simulation. This file is
|
||||
* only provided to simulate how a real hardware-accelerated display-only
|
||||
* driver functions, and should not be used in a real driver.
|
||||
*
|
||||
* Copyright (c) 2011 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
#include "BDD.hxx"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CONST DXGKRNL_INTERFACE* DxgkInterface;
|
||||
DXGKARGCB_NOTIFY_INTERRUPT_DATA NotifyInterrupt;
|
||||
} SYNC_NOTIFY_INTERRUPT;
|
||||
|
||||
KSYNCHRONIZE_ROUTINE SynchronizeVidSchNotifyInterrupt;
|
||||
|
||||
BOOLEAN SynchronizeVidSchNotifyInterrupt(_In_opt_ PVOID params)
|
||||
{
|
||||
// This routine is non-paged code called at the device interrupt level (DIRQL)
|
||||
// to notify VidSch and schedule a DPC. It is meant as a demonstration of handling
|
||||
// a real hardware interrupt, even though it is actually called from asynchronous
|
||||
// present worker threads in this sample.
|
||||
SYNC_NOTIFY_INTERRUPT* pParam = reinterpret_cast<SYNC_NOTIFY_INTERRUPT*>(params);
|
||||
|
||||
// The context is known to be non-NULL
|
||||
__analysis_assume(pParam != NULL);
|
||||
|
||||
// Update driver information related to fences
|
||||
switch(pParam->NotifyInterrupt.InterruptType)
|
||||
{
|
||||
case DXGK_INTERRUPT_DISPLAYONLY_VSYNC:
|
||||
case DXGK_INTERRUPT_DISPLAYONLY_PRESENT_PROGRESS:
|
||||
break;
|
||||
default:
|
||||
NT_ASSERT(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Callback OS to report about the interrupt
|
||||
pParam->DxgkInterface->DxgkCbNotifyInterrupt(pParam->DxgkInterface->DeviceHandle,&pParam->NotifyInterrupt);
|
||||
|
||||
// Now queue a DPC for this interrupt (to callback schedule at DCP level and let it do more work there)
|
||||
// DxgkCbQueueDpc can return FALSE if there is already a DPC queued
|
||||
// this is an acceptable condition
|
||||
pParam->DxgkInterface->DxgkCbQueueDpc(pParam->DxgkInterface->DeviceHandle);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
|
||||
KSTART_ROUTINE HwContextWorkerThread;
|
||||
|
||||
struct DoPresentMemory
|
||||
{
|
||||
PVOID DstAddr;
|
||||
UINT DstStride;
|
||||
ULONG DstBitPerPixel;
|
||||
UINT SrcWidth;
|
||||
UINT SrcHeight;
|
||||
BYTE* SrcAddr;
|
||||
LONG SrcPitch;
|
||||
ULONG NumMoves; // in: Number of screen to screen moves
|
||||
D3DKMT_MOVE_RECT* Moves; // in: Point to the list of moves
|
||||
ULONG NumDirtyRects; // in: Number of direct rects
|
||||
RECT* DirtyRect; // in: Point to the list of dirty rects
|
||||
D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;
|
||||
BOOLEAN SynchExecution;
|
||||
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceID;
|
||||
HANDLE hAdapter;
|
||||
PMDL Mdl;
|
||||
BDD_HWBLT* DisplaySource;
|
||||
};
|
||||
|
||||
void
|
||||
HwExecutePresentDisplayOnly(
|
||||
HANDLE Context);
|
||||
|
||||
NTSTATUS
|
||||
StartHwBltPresentWorkerThread(
|
||||
_In_ PKSTART_ROUTINE StartRoutine,
|
||||
_In_ _When_(return==0, __drv_aliasesMem) PVOID StartContext)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine creates the worker thread to execute a single present
|
||||
command. Creating a new thread on every asynchronous present is not
|
||||
efficient, but this file is only meant as a simulation, not an example
|
||||
of implementation.
|
||||
|
||||
Arguments:
|
||||
|
||||
StartRoutine - start routine
|
||||
StartContext - start context
|
||||
|
||||
Return Value:
|
||||
|
||||
Status
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
HANDLE hWorkerThread = NULL;
|
||||
|
||||
// copy data from the context which is need here, as it will be deleted in separate thread
|
||||
DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>(StartContext);
|
||||
BDD_HWBLT* displaySource = ctx->DisplaySource;
|
||||
|
||||
NTSTATUS Status = PsCreateSystemThread(
|
||||
&hWorkerThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
NULL,
|
||||
NULL,
|
||||
StartRoutine,
|
||||
StartContext);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
// wait for thread to start - infinite wait -
|
||||
// need to make sure the tread is running before OS stars submitting the work items to it
|
||||
KeWaitForSingleObject(&displaySource->m_hThreadStartupEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
// Handle is passed to the parent object which must close it
|
||||
displaySource->SetPresentWorkerThreadInfo(hWorkerThread);
|
||||
|
||||
// Resume context thread, this is done by setting the event the thread is waiting on
|
||||
KeSetEvent(&displaySource->m_hThreadSuspendEvent, 0, FALSE);
|
||||
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
BDD_HWBLT::BDD_HWBLT():m_DevExt (NULL),
|
||||
m_SynchExecution(TRUE),
|
||||
m_hPresentWorkerThread(NULL),
|
||||
m_pPresentWorkerThread(NULL)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
KeInitializeEvent(&m_hThreadStartupEvent, NotificationEvent, FALSE);
|
||||
KeInitializeEvent(&m_hThreadSuspendEvent, SynchronizationEvent, FALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
BDD_HWBLT::~BDD_HWBLT()
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine waits on present worker thread to exit before
|
||||
destroying the object
|
||||
|
||||
Arguments:
|
||||
|
||||
None
|
||||
|
||||
Return Value:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
// make sure the worker thread has exited
|
||||
SetPresentWorkerThreadInfo(NULL);
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:26135) // The function doesn't lock anything
|
||||
|
||||
void
|
||||
BDD_HWBLT::SetPresentWorkerThreadInfo(
|
||||
HANDLE hWorkerThread)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The method is updating present worker information
|
||||
It is called in following cases:
|
||||
- In ExecutePresent to update worker thread information
|
||||
- In Dtor to wait on worker thread to exit
|
||||
|
||||
Arguments:
|
||||
|
||||
hWorkerThread - handle of the present worker thread
|
||||
|
||||
Return Value:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (m_pPresentWorkerThread)
|
||||
{
|
||||
// Wait for thread to exit
|
||||
KeWaitForSingleObject(m_pPresentWorkerThread, Executive, KernelMode,
|
||||
FALSE, NULL);
|
||||
// Dereference thread object
|
||||
ObDereferenceObject(m_pPresentWorkerThread);
|
||||
m_pPresentWorkerThread = NULL;
|
||||
|
||||
NT_ASSERT(m_hPresentWorkerThread);
|
||||
ZwClose(m_hPresentWorkerThread);
|
||||
m_hPresentWorkerThread = NULL;
|
||||
}
|
||||
|
||||
if (hWorkerThread)
|
||||
{
|
||||
// Make sure that thread's handle would be valid even if the thread exited
|
||||
ObReferenceObjectByHandle(hWorkerThread, THREAD_ALL_ACCESS, NULL,
|
||||
KernelMode, &m_pPresentWorkerThread, NULL);
|
||||
NT_ASSERT(m_pPresentWorkerThread);
|
||||
m_hPresentWorkerThread = hWorkerThread;
|
||||
}
|
||||
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
NTSTATUS
|
||||
BDD_HWBLT::ExecutePresentDisplayOnly(
|
||||
_In_ BYTE* DstAddr,
|
||||
_In_ UINT DstBitPerPixel,
|
||||
_In_ BYTE* SrcAddr,
|
||||
_In_ UINT SrcBytesPerPixel,
|
||||
_In_ LONG SrcPitch,
|
||||
_In_ ULONG NumMoves,
|
||||
_In_ D3DKMT_MOVE_RECT* Moves,
|
||||
_In_ ULONG NumDirtyRects,
|
||||
_In_ RECT* DirtyRect,
|
||||
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The method creates present worker thread and provides context
|
||||
for it filled with present commands
|
||||
|
||||
Arguments:
|
||||
|
||||
DstAddr - address of destination surface
|
||||
DstBitPerPixel - color depth of destination surface
|
||||
SrcAddr - address of source surface
|
||||
SrcBytesPerPixel - bytes per pixel of source surface
|
||||
SrcPitch - source surface pitch (bytes in a row)
|
||||
NumMoves - number of moves to be copied
|
||||
Moves - moves' data
|
||||
NumDirtyRects - number of rectangles to be copied
|
||||
DirtyRect - rectangles' data
|
||||
Rotation - roatation to be performed when executing copy
|
||||
CallBack - callback for present worker thread to report execution status
|
||||
|
||||
Return Value:
|
||||
|
||||
Status
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT);
|
||||
SIZE_T sizeRects = NumDirtyRects*sizeof(RECT);
|
||||
SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects;
|
||||
|
||||
DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>
|
||||
(new (PagedPool) BYTE[size]);
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
RtlZeroMemory(ctx,size);
|
||||
|
||||
const CURRENT_BDD_MODE* pModeCur = m_DevExt->GetCurrentMode(m_SourceId);
|
||||
|
||||
ctx->DstAddr = DstAddr;
|
||||
ctx->DstBitPerPixel = DstBitPerPixel;
|
||||
ctx->DstStride = pModeCur->DispInfo.Pitch;
|
||||
ctx->SrcWidth = pModeCur->SrcModeWidth;
|
||||
ctx->SrcHeight = pModeCur->SrcModeHeight;
|
||||
ctx->SrcAddr = NULL;
|
||||
ctx->SrcPitch = SrcPitch;
|
||||
ctx->Rotation = Rotation;
|
||||
ctx->NumMoves = NumMoves;
|
||||
ctx->Moves = Moves;
|
||||
ctx->NumDirtyRects = NumDirtyRects;
|
||||
ctx->DirtyRect = DirtyRect;
|
||||
ctx->SourceID = m_SourceId;
|
||||
ctx->hAdapter = m_DevExt;
|
||||
ctx->Mdl = NULL;
|
||||
ctx->DisplaySource = this;
|
||||
|
||||
// Alternate between synch and asynch execution, for demonstrating
|
||||
// that a real hardware implementation can do either
|
||||
m_SynchExecution = !m_SynchExecution;
|
||||
|
||||
ctx->SynchExecution = m_SynchExecution;
|
||||
|
||||
{
|
||||
// Map Source into kernel space, as Blt will be executed by system worker thread
|
||||
UINT sizeToMap = SrcBytesPerPixel*pModeCur->SrcModeWidth*pModeCur->SrcModeHeight;
|
||||
|
||||
PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL);
|
||||
if(!mdl)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
KPROCESSOR_MODE AccessMode = static_cast<KPROCESSOR_MODE>(( SrcAddr <=
|
||||
(BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode);
|
||||
__try
|
||||
{
|
||||
// Probe and lock the pages of this buffer in physical memory.
|
||||
// We need only IoReadAccess.
|
||||
MmProbeAndLockPages(mdl, AccessMode, IoReadAccess);
|
||||
}
|
||||
#pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here");
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = GetExceptionCode();
|
||||
IoFreeMdl(mdl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Map the physical pages described by the MDL into system space.
|
||||
// Note: double mapping the buffer this way causes lot of system
|
||||
// overhead for large size buffers.
|
||||
ctx->SrcAddr = reinterpret_cast<BYTE*>
|
||||
(MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority ));
|
||||
|
||||
if(!ctx->SrcAddr) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
MmUnlockPages(mdl);
|
||||
IoFreeMdl(mdl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Save Mdl to unmap and unlock the pages in worker thread
|
||||
ctx->Mdl = mdl;
|
||||
}
|
||||
|
||||
BYTE* rects = reinterpret_cast<BYTE*>(ctx+1);
|
||||
|
||||
// copy moves and update pointer
|
||||
if (Moves)
|
||||
{
|
||||
memcpy(rects,Moves,sizeMoves);
|
||||
ctx->Moves = reinterpret_cast<D3DKMT_MOVE_RECT*>(rects);
|
||||
rects += sizeMoves;
|
||||
}
|
||||
|
||||
// copy dirty rects and update pointer
|
||||
if (DirtyRect)
|
||||
{
|
||||
memcpy(rects,DirtyRect,sizeRects);
|
||||
ctx->DirtyRect = reinterpret_cast<RECT*>(rects);
|
||||
}
|
||||
|
||||
|
||||
if (m_SynchExecution)
|
||||
{
|
||||
HwExecutePresentDisplayOnly((PVOID)ctx);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a worker thread to perform the present asynchronously
|
||||
// Ctx will be deleted in worker thread (on exit)
|
||||
return StartHwBltPresentWorkerThread(HwContextWorkerThread,(PVOID)ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ReportPresentProgress(
|
||||
_In_ HANDLE Adapter,
|
||||
_In_ D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
|
||||
_In_ BOOLEAN CompletedOrFailed)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine runs a fake interrupt routine in order to tell the OS about the present progress.
|
||||
|
||||
Arguments:
|
||||
|
||||
Adapter - Handle to the adapter (Device Extension)
|
||||
VidPnSourceId - Video present source id for the callback
|
||||
CompletedOrFailed - Present progress status for the source
|
||||
|
||||
Return Value:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
BASIC_DISPLAY_DRIVER* pDevExt =
|
||||
reinterpret_cast<BASIC_DISPLAY_DRIVER*>(Adapter);
|
||||
|
||||
SYNC_NOTIFY_INTERRUPT SyncNotifyInterrupt = {};
|
||||
SyncNotifyInterrupt.DxgkInterface = pDevExt->GetDxgkInterface();
|
||||
SyncNotifyInterrupt.NotifyInterrupt.InterruptType = DXGK_INTERRUPT_DISPLAYONLY_PRESENT_PROGRESS;
|
||||
SyncNotifyInterrupt.NotifyInterrupt.DisplayOnlyPresentProgress.VidPnSourceId = VidPnSourceId;
|
||||
|
||||
SyncNotifyInterrupt.NotifyInterrupt.DisplayOnlyPresentProgress.ProgressId =
|
||||
(CompletedOrFailed)?DXGK_PRESENT_DISPLAYONLY_PROGRESS_ID_COMPLETE:
|
||||
DXGK_PRESENT_DISPLAYONLY_PROGRESS_ID_FAILED;
|
||||
|
||||
// Execute the SynchronizeVidSchNotifyInterrupt function at the interrupt
|
||||
// IRQL in order to fake a real present progress interrupt
|
||||
BOOLEAN bRet = FALSE;
|
||||
NT_VERIFY(NT_SUCCESS(pDevExt->GetDxgkInterface()->DxgkCbSynchronizeExecution(
|
||||
pDevExt->GetDxgkInterface()->DeviceHandle,
|
||||
(PKSYNCHRONIZE_ROUTINE)SynchronizeVidSchNotifyInterrupt,
|
||||
(PVOID)&SyncNotifyInterrupt,0,&bRet)));
|
||||
NT_ASSERT(bRet);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HwContextWorkerThread(
|
||||
HANDLE Context)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>(Context);
|
||||
BDD_HWBLT* displaySource = ctx->DisplaySource;
|
||||
|
||||
// Signal event to indicate that the tread has started
|
||||
KeSetEvent(&displaySource->m_hThreadStartupEvent, 0, FALSE);
|
||||
|
||||
// Suspend context thread, do this by waiting on the suspend event
|
||||
KeWaitForSingleObject(&displaySource->m_hThreadSuspendEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
HwExecutePresentDisplayOnly(Context);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HwExecutePresentDisplayOnly(
|
||||
HANDLE Context)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The routine executes present's commands and report progress to the OS
|
||||
|
||||
Arguments:
|
||||
|
||||
Context - Context with present's command
|
||||
|
||||
Return Value:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>(Context);
|
||||
|
||||
// Set up destination blt info
|
||||
BLT_INFO DstBltInfo;
|
||||
DstBltInfo.pBits = ctx->DstAddr;
|
||||
DstBltInfo.Pitch = ctx->DstStride;
|
||||
DstBltInfo.BitsPerPel = ctx->DstBitPerPixel;
|
||||
DstBltInfo.Offset.x = 0;
|
||||
DstBltInfo.Offset.y = 0;
|
||||
DstBltInfo.Rotation = ctx->Rotation;
|
||||
DstBltInfo.Width = ctx->SrcWidth;
|
||||
DstBltInfo.Height = ctx->SrcHeight;
|
||||
|
||||
// Set up source blt info
|
||||
BLT_INFO SrcBltInfo;
|
||||
SrcBltInfo.pBits = ctx->SrcAddr;
|
||||
SrcBltInfo.Pitch = ctx->SrcPitch;
|
||||
SrcBltInfo.BitsPerPel = 32;
|
||||
SrcBltInfo.Offset.x = 0;
|
||||
SrcBltInfo.Offset.y = 0;
|
||||
SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY;
|
||||
if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 ||
|
||||
ctx->Rotation == D3DKMDT_VPPR_ROTATE270)
|
||||
{
|
||||
SrcBltInfo.Width = DstBltInfo.Height;
|
||||
SrcBltInfo.Height = DstBltInfo.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
SrcBltInfo.Width = DstBltInfo.Width;
|
||||
SrcBltInfo.Height = DstBltInfo.Height;
|
||||
}
|
||||
|
||||
|
||||
// Copy all the scroll rects from source image to video frame buffer.
|
||||
for (UINT i = 0; i < ctx->NumMoves; i++)
|
||||
{
|
||||
BltBits(&DstBltInfo,
|
||||
&SrcBltInfo,
|
||||
1, // NumRects
|
||||
&ctx->Moves[i].DestRect);
|
||||
}
|
||||
|
||||
// Copy all the dirty rects from source image to video frame buffer.
|
||||
for (UINT i = 0; i < ctx->NumDirtyRects; i++)
|
||||
{
|
||||
|
||||
BltBits(&DstBltInfo,
|
||||
&SrcBltInfo,
|
||||
1, // NumRects
|
||||
&ctx->DirtyRect[i]);
|
||||
}
|
||||
|
||||
// Unmap unmap and unlock the pages.
|
||||
if (ctx->Mdl)
|
||||
{
|
||||
MmUnlockPages(ctx->Mdl);
|
||||
IoFreeMdl(ctx->Mdl);
|
||||
}
|
||||
|
||||
if(ctx->SynchExecution)
|
||||
{
|
||||
// This code simulates Blt executed synchronously
|
||||
// nothing should be done here, just exit
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TRUE == completed
|
||||
// This code is emulates interrupt which HW should generate
|
||||
ReportPresentProgress(ctx->hAdapter,ctx->SourceID,TRUE);
|
||||
}
|
||||
|
||||
delete [] reinterpret_cast<BYTE*>(ctx);
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/******************************Module*Header*******************************\
|
||||
* Module Name: bdd.h
|
||||
*
|
||||
* Basic Display Driver memory allocation, deletion, and tracking
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010 Microsoft Corporation
|
||||
\**************************************************************************/
|
||||
|
||||
#include "BDD.hxx"
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
|
||||
//
|
||||
// New and delete operators
|
||||
//
|
||||
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
|
||||
__drv_reportError("Must succeed pool allocations are forbidden. "
|
||||
"Allocation failures cause a system crash"))
|
||||
void* __cdecl operator new(size_t Size, POOL_TYPE PoolType)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
Size = (Size != 0) ? Size : 1;
|
||||
|
||||
void* pObject = ExAllocatePool2(PoolType, Size, BDDTAG);
|
||||
|
||||
#if DBG
|
||||
if (pObject != NULL)
|
||||
{
|
||||
RtlFillMemory(pObject, Size, 0xCD);
|
||||
}
|
||||
#endif // DBG
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
|
||||
__drv_reportError("Must succeed pool allocations are forbidden. "
|
||||
"Allocation failures cause a system crash"))
|
||||
void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
Size = (Size != 0) ? Size : 1;
|
||||
|
||||
void* pObject = ExAllocatePool2(PoolType, Size, BDDTAG);
|
||||
|
||||
#if DBG
|
||||
if (pObject != NULL)
|
||||
{
|
||||
RtlFillMemory(pObject, Size, 0xCD);
|
||||
}
|
||||
#endif // DBG
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
void __cdecl operator delete(void* pObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (pObject != NULL)
|
||||
{
|
||||
ExFreePool(pObject);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// size_t version is needed for VS2015(C++ 14).
|
||||
//
|
||||
void __cdecl operator delete(void* pObject, size_t s)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER( s );
|
||||
|
||||
::operator delete( pObject );
|
||||
}
|
||||
|
||||
void __cdecl operator delete[](void* pObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (pObject != NULL)
|
||||
{
|
||||
ExFreePool(pObject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
SampleDisplay.rc
|
||||
|
||||
Abstract:
|
||||
|
||||
This modules contains the version information for the Sample Display Driver
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
--*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_DISPLAY
|
||||
#define VER_FILEDESCRIPTION_STR "Microsoft Sample Display Driver"
|
||||
#define VER_INTERNALNAME_STR "SampleDisplay.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "SampleDisplay.sys"
|
||||
|
||||
#define VER_LANGNEUTRAL
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Virtual Display
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,184 +1,105 @@
|
||||
# Virtual Display Driver
|
||||
based on Microsoft Indirect Display Driver Sample. This creates a virtual display in Windows that acts and functions just like a real one. It's useful for streaming, virtual reality applications, recording, headless servers, etc. The benefit over a physical display is the ability to adjust resolutions and refresh rates beyond the physical displays capabilities. For example, this would enable the ability to stream a game from your home PC using game streaming software at 240hz at 8K while owning a 60hz 1080p monitor (unrealistic, but explains the abilities well). For servers without displays, this enabled remote desktop and screen streaming to other systems as if there were a display installed.
|
||||
# 🛠️ Virtual Display Driver Development Team
|
||||
|
||||
Supports emulating resolutions from **640 x 480** to **7680 x 4320 (8K)**, and refresh rates including **60hz, 75hz, 90hz, 120hz, 144hz, 165hz, 240hz, 480hz,** and **500hz.**
|
||||
| 👤 Developer | 🏷️ Role | 💖 Support Us |
|
||||
| --------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| **[MikeTheTech](https://github.com/itsmikethetech)** | Project Manager, Lead Programmer | [Patreon](https://www.patreon.com/mikethetech) :gem: / [GitHub Sponsors](https://github.com/sponsors/itsmikethetech/) 💖 |
|
||||
| **[Jocke](https://github.com/zjoasan)** | Programmer, Concept Design | [GitHub Sponsors ](https://github.com/sponsors/zjoasan) 💖 |
|
||||
|
||||
This project uses the official Windows Indirect Display Driver combined with the IddCx class extension driver.
|
||||
:bulb: *We appreciate your support—every contribution helps us keep building amazing experiences!*
|
||||
|
||||
## Download
|
||||
# <img src="https://github.com/user-attachments/assets/22ff37ba-a8ea-4b65-b7b2-e7fcb09d858b" height="32" width="32"></img> Virtual Display Driver
|
||||
This project creates a _virtual monitor_ in Windows that functions just like a physical display. It is particularly useful for applications such as **streaming, virtual reality, screen recording,** and **headless servers—systems** that operate without a physical display attached.
|
||||
|
||||
- [Windows 10 and 11 (no HDR)](https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/23.10.20.2)
|
||||
- [Windows 11 22H2+ (HDR)](https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/23.12.2HDR)
|
||||
|
||||
## Installation
|
||||
Unlike traditional monitors, this virtual display supports custom resolutions and refresh rates beyond hardware limitations—offering greater flexibility for advanced setups. You can also use custom EDIDs to simulate or emulate existing hardware displays.
|
||||
|
||||
1. Download the latest version from the releases page, and extract the contents to a folder.
|
||||
2. Copy `option.txt` to `C:\IddSampleDriver\option.txt` before installing the driver **(important!)**.
|
||||
3. Right click and run the *.bat file **as an Administrator** to add the driver certificate as a trusted root certificate.
|
||||
4. Don't install the inf. Open device manager, click on any device, then click on the "Action" menu and click "Add Legacy Hardware".
|
||||
5. Select "Add hardware from a list (Advanced)" and then select Display adapters
|
||||
6. Click "Have Disk..." and click the "Browse..." button. Navigate to the extracted files and select the inf file.
|
||||
7. You are done! Go to display settings to customize the resolution of the additional displays. These displays show up in Sunshine, your Oculus or VR settings, and should be able to be streamed from.
|
||||
8. You can enable/disable the display adapter to toggle the monitors.
|
||||
## ⬇️ Download Latest Version
|
||||
|
||||
Ps. Make sure that options.txt is accesible for the system at `C:\IddSampleDriver\option.txt` or the installation will fail.
|
||||
- [Driver Installer (Windows 10/11)](https://github.com/VirtualDrivers/Virtual-Display-Driver/releases) - Check the [Releases](https://github.com/VirtualDrivers/Virtual-Display-Driver/releases) page for the latest version and release notes.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
1. Open device manager
|
||||
2. Locate Display Adapters
|
||||
3. Right click on IddSampleDriver, choose "Uninstall device"
|
||||
4. There is a new popup window, in there click Attempt to remove driver for this device.
|
||||
|
||||
Next instructions are for those cases where the device is removed from the system, but driver stil remains. This happens when there is a connection to the device while trying to remove the drivers. To
|
||||
remedy this, there is a a few tricks built into windows. So here goes:
|
||||
|
||||
5. Open up a powershell terminal and input this:
|
||||
6. ```pnputil /enum-drivers```
|
||||
6. Locate iddsampledriver.inf, there might be multiple pages of text. Make a note of the "published name", it's often unique for your system, but might look like "oem139.inf"
|
||||
7. ```pnputil /delete-driver oem139.inf```
|
||||
|
||||
## HDR Support Now Available for Windows 11 22H2+
|
||||
|
||||
### Resolutions:
|
||||
|
||||
640 x 480
|
||||
800 x 600
|
||||
1024 x 768
|
||||
1152 x 864
|
||||
1280 x 720
|
||||
1280 x 768
|
||||
1280 x 800
|
||||
1280 x 960
|
||||
1280 x 1024
|
||||
1360 x 768
|
||||
1366 x 768
|
||||
1440 x 900
|
||||
1400 x 1050
|
||||
1440 x 1440
|
||||
1600 x 900
|
||||
1600 x 1024
|
||||
1680 x 1050
|
||||
1920 x 1080
|
||||
1920 x 1200
|
||||
2560 x 1440
|
||||
2560 x 1600
|
||||
2732 x 2048
|
||||
2880 x 1620
|
||||
2880 x 1800
|
||||
3008 x 1692
|
||||
3840 x 2160
|
||||
3840 x 2400
|
||||
4096 x 2304
|
||||
5120 x 2880
|
||||
6016 x 3384
|
||||
7680 x 4320
|
||||
|
||||
### Just Added!
|
||||
|
||||
2732 x 2048
|
||||
2560 x 1080
|
||||
2880 x 1200
|
||||
3440 x 1440
|
||||
3840 x 1600
|
||||
4320 x 1800
|
||||
5120 x 2160
|
||||
5760 x 2400
|
||||
6880 x 2880
|
||||
7680 x 3200
|
||||
8640 x 3600
|
||||
10240 x 432
|
||||
2880 x 900
|
||||
3840 x 1080
|
||||
3840 x 1200
|
||||
4320 x 1200
|
||||
5120 x 1440
|
||||
5120 x 1600
|
||||
5760 x 1600
|
||||
5760 x 1800
|
||||
6400 x 1800
|
||||
6480 x 1800
|
||||
7680 x 2160
|
||||
7680 x 2400
|
||||
8640 x 2400
|
||||
2388 x 1668
|
||||
2400 x 1080
|
||||
3456 x 2234
|
||||
3456 x 2234
|
||||
|
||||
### Refresh Rates:
|
||||
|
||||
30Hz
|
||||
60Hz
|
||||
75Hz
|
||||
90Hz (Great for VR!)
|
||||
120Hz
|
||||
144Hz
|
||||
165Hz
|
||||
240Hz
|
||||
480Hz
|
||||
500Hz
|
||||
|
||||
### Videos
|
||||
|
||||
[](https://youtu.be/nNWpbRUPkn4 "How to install a virtual display")
|
||||
|
||||
[Previous Video: How to install a virtual display](https://youtu.be/byfBWDnToYk "How to install a virtual display")
|
||||
|
||||
### Screenshots:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
> [!IMPORTANT]
|
||||
> Before using the Virtual Display Driver, ensure the following dependencies are installed:
|
||||
> - **Microsoft Visual C++ Redistributable**
|
||||
> If you encounter the error `vcruntime140.dll not found`, download and install the latest version from the [Microsoft Visual C++ Redistributable page](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170).
|
||||
|
||||
|
||||
## Background reading ##
|
||||
## 🛠️ Installation
|
||||
|
||||
Start at the [Indirect Display Driver Model Overview](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx) on MSDN.
|
||||
- Step 1: Download the Virtual Driver Control app.
|
||||
- You can download the installer directly from the [Releases](https://github.com/VirtualDrivers/Virtual-Display-Driver/releases) page.
|
||||
|
||||
### Code structure ###
|
||||
- Step 2: Extract to a folder and run the app
|
||||
- Launch the VDC.
|
||||
- Click the Install button.
|
||||
|
||||
The sample driver code is very simplistic and does nothing more than enumerate a single monitor when its device enters the D0/started power state. The IDD runs in Session 0 without any components running in the user session, so any driver instability will not affect the stability of the system as a whole. The IDD is a user-mode only model with no support for kernel-mode components. As such, the driver is able to use any DirectX APIs in order to process the desktop image. In fact, the IddCx provides the desktop image to encode in a DirectX surface.
|
||||
- Step 3: Verify the Installation (Optional)
|
||||
- Check if the Virtual Display Driver is correctly installed by running the following:
|
||||
- **Device Manager:** Check "Device Manager" under "Display Adapters."
|
||||
- **Settings:** Check display settings under system settings and see if the virtual displays show.
|
||||
|
||||
* `Direct3DDevice` class
|
||||
* Contains logic for enumerating the correct render GPU from DXGI and creating a D3D device.
|
||||
* Manages the lifetime of a DXGI factory and a D3D device created for the render GPU the system is using to render frames for your indirect display device's swap-chain.
|
||||
* `SwapChainProcessor` class
|
||||
* Processes frames for a swap-chain assigned to the monitor object on a dedicated thread.
|
||||
* The sample code does nothing with the frames, but demonstrates a correct processing loop with error handling and notifying the OS of frame completion.
|
||||
* `IndirectDeviceContext` class
|
||||
* Processes device callbacks from IddCx.
|
||||
* Manages the creation and arrival of the sample monitor.
|
||||
* Handles swap-chain arrival and departure by creating a `Direct3DDevice` and handing it off to a `SwapChainProcessor`.
|
||||
While VDC is a good and friendly way to work with VDD, you can also do a a lot manually. Like adding or removing resolutions or enable/disable
|
||||
functions, which is done by editing vdd_settings.xml. You should be able to locate the file at the default location:
|
||||
```C:\VirtualDisplayDriver\vdd_settings.xml ```
|
||||
|
||||
## License
|
||||
For more information about manual installation, uninstallation and "personalization", please check out the [Wiki](https://github.com/VirtualDrivers/Virtual-Display-Driver/wiki) here on
|
||||
the project GitHub repository. If you are into tinkering, check out the Powershell scripts in [Community scripts](https://github.com/VirtualDrivers/Virtual-Display-Driver/tree/master/Community%20Scripts).
|
||||
|
||||
MIT and CC0 or Public Domain (for changes I made, please consult Microsoft for their license), choose the least restrictive option.
|
||||
## 🤔 Comparison with other IDDs
|
||||
|
||||
## Disclaimer:
|
||||
The table below shows a comparison with other popular Indirect Display Driver
|
||||
projects.
|
||||
|
||||
This software is provided "AS IS" with NO IMPLICIT OR EXPLICIT warranty. It's worth noting that while this software functioned without issues on my system, there is no guarantee that it will not impact your computer. It operates in User Mode, which reduces the likelihood of causing system instability, such as the Blue Screen of Death. However, exercise caution when using this software.
|
||||
| Project | Iddcx version | Signed | SDR | HDR | H-Cursor | Tweakable | ARM64 Support | Custom EDID | Floating Point Refresh Rates |
|
||||
| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
||||
| [Virtual-Display-Driver (HDR)] | 1.10 (latest) | ✅ | ✅ (8/10bit) | ✅ (1-/12bit) | ✅ | ✅ | ✅¹ | ✅ | ✅ |
|
||||
| [usbmmid_v2] | | ✅ | ✅ (8bit) | | | | | | |
|
||||
| [virtual-display-rs] | 1.5 | | ✅ (8bit) | | ✅ | ✅ | | | |
|
||||
| [parsec-vdd]| 1.5 | ✅ | ✅ (8bit) | | ✅ | ✅ | | | |
|
||||
| [lddSampleDriver] | 1.2 | | ✅ (8bit) | | | | | | |
|
||||
| [RustDesklddDriver] | 1.2 | | ✅ (8bit) | | | | | | |
|
||||
|
||||
¹ ARM64 Support in Windows 11 24H2 or later may require test signing be enabled.
|
||||
|
||||
HDR Support Now Available for Windows 11 23H2+
|
||||
|
||||
## ▶️ Videos and Tutorials
|
||||
|
||||
### Installation Video
|
||||
|
||||
[](https://youtu.be/jN5YnHlC0fE)
|
||||
|
||||

|
||||
|
||||
## 🤝 Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://github.com/user-attachments/assets/ca93d971-67dc-41dd-b945-ab4f372ea72a" /></td>
|
||||
<td>Free code signing on Windows provided by <a href="https://signpath.io">SignPath.io</a>, certificate by <a href="https://signpath.org">SignPath Foundation</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Advanced 32bit IEEE Float Audio brought to you by **Lune Studios**.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Shoutout to **Roshkins** for the original repo:
|
||||
https://github.com/roshkins/IddSampleDriver
|
||||
|
||||
Shoutout to **Baloukj** for the 8-bit / 10-bit support. (Also, first to push the new Microsoft Driver public!)
|
||||
https://github.com/baloukj/IddSampleDriver
|
||||
|
||||
Shoutout to **Anakngtokwa** for assisting with finding driver sources.
|
||||
|
||||
**Microsoft** Indirect Display Driver/Sample (Driver code):
|
||||
https://github.com/microsoft/Windows-driver-samples/tree/master/video/IndirectDisplay
|
||||
|
||||
Thanks to **AKATrevorJay** https://github.com/akatrevorjay/edid-generator for the hi-res EDID.
|
||||
|
||||
Shoutout to **zjoasan** and **Bud** for the helper scripts and build support!
|
||||
- Shoutout to **[MikeTheTech](https://github.com/itsmikethetech)** Project Manager, Owner, and Programmer
|
||||
- Shoutout to **[zjoasan](https://github.com/zjoasan)** Programmer. For scripts, EDID integration, and parts of installer.
|
||||
- Shoutout to **[Bud](https://github.com/bud3699)** Former Lead Programmer, has since left the project.
|
||||
- Shoutout to **[Roshkins](https://github.com/roshkins/IddSampleDriver)** for the original repo.
|
||||
- Shoutout to **[Baloukj](https://github.com/baloukj/IddSampleDriver)** for the 8-bit / 10-bit support. (Also, first to push the new Microsoft Driver public!)
|
||||
- Shoutout to **[Anakngtokwa](https://github.com/Anakngtokwa)** for assisting with finding driver sources.
|
||||
- **[Microsoft](https://github.com/microsoft/Windows-driver-samples/tree/master/video/IndirectDisplay)** Indirect Display Driver/Sample (Driver code)
|
||||
- Thanks to **[AKATrevorJay](https://github.com/akatrevorjay/edid-generator)** for the hi-res EDID.
|
||||
- Shoutout to **[LexTrack](https://github.com/lextrack/)** for the MiniScreenRecorder script.
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#itsmikethetech/Virtual-Display-Driver&Date)
|
||||
[](https://www.star-history.com/#VirtualDrivers/Virtual-Display-Driver&Date)
|
||||
|
||||
## Disclaimer:
|
||||
|
||||
This software is provided "AS IS" with NO IMPLICIT OR EXPLICIT warranty. It's worth noting that while this software functioned without issues on our systems, there is no guarantee that it will not impact your computer. It operates in User Mode(Session0), which reduces the likelihood of causing system instability, such as the Blue Screen of Death. However, exercise caution when using this software.
|
||||
File renamed without changes.
File renamed without changes.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -0,0 +1,213 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<IddCxMonitorConfig>
|
||||
<MonitorModes>
|
||||
<MonitorMode>
|
||||
<Width>640</Width>
|
||||
<Height>480</Height>
|
||||
<RefreshRate>60.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>720</Width>
|
||||
<Height>480</Height>
|
||||
<RefreshRate>59.940</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>720</Width>
|
||||
<Height>576</Height>
|
||||
<RefreshRate>50.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>50</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>800</Width>
|
||||
<Height>600</Height>
|
||||
<RefreshRate>60.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1024</Width>
|
||||
<Height>768</Height>
|
||||
<RefreshRate>60.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1152</Width>
|
||||
<Height>864</Height>
|
||||
<RefreshRate>75.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>75</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1280</Width>
|
||||
<Height>720</Height>
|
||||
<RefreshRate>50.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>50</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1280</Width>
|
||||
<Height>720</Height>
|
||||
<RefreshRate>59.940</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1280</Width>
|
||||
<Height>1024</Height>
|
||||
<RefreshRate>60.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1600</Width>
|
||||
<Height>900</Height>
|
||||
<RefreshRate>60.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1680</Width>
|
||||
<Height>1050</Height>
|
||||
<RefreshRate>60.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1920</Width>
|
||||
<Height>1080</Height>
|
||||
<RefreshRate>7.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>7</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1920</Width>
|
||||
<Height>1080</Height>
|
||||
<RefreshRate>50.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>50</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>1920</Width>
|
||||
<Height>1080</Height>
|
||||
<RefreshRate>59.940</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>0.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>0</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>4.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>4</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>24.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>24</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>25.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>25</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>29.970</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>30</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>50.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>50</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>59.940</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>100.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>100</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>3840</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>120.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>120</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>4096</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>23.976</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>24</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>4096</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>50.000</RefreshRate>
|
||||
<RefreshRateMultiplier>1000</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>50</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
<MonitorMode>
|
||||
<Width>4096</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>59.940</RefreshRate>
|
||||
<RefreshRateMultiplier>999</RefreshRateMultiplier>
|
||||
<NominalRefreshRate>60</NominalRefreshRate>
|
||||
</MonitorMode>
|
||||
</MonitorModes>
|
||||
<HDRCapabilities>
|
||||
<HDR10Supported>true</HDR10Supported>
|
||||
<DolbyVisionSupported>false</DolbyVisionSupported>
|
||||
<HDR10PlusSupported>false</HDR10PlusSupported>
|
||||
<MaxLuminance>1670.838</MaxLuminance>
|
||||
<MinLuminance>10.615</MinLuminance>
|
||||
</HDRCapabilities>
|
||||
<ColorProfile>
|
||||
<PrimaryColorSpace>sRGB</PrimaryColorSpace>
|
||||
<Gamma>2.200</Gamma>
|
||||
<Chromaticity>
|
||||
<RedX>0.6250</RedX>
|
||||
<RedY>0.3398</RedY>
|
||||
<GreenX>0.2803</GreenX>
|
||||
<GreenY>0.5947</GreenY>
|
||||
<BlueX>0.1553</BlueX>
|
||||
<BlueY>0.0703</BlueY>
|
||||
<WhiteX>0.2832</WhiteX>
|
||||
<WhiteY>0.2979</WhiteY>
|
||||
</Chromaticity>
|
||||
</ColorProfile>
|
||||
<PreferredMode>
|
||||
<Width>4096</Width>
|
||||
<Height>2160</Height>
|
||||
<RefreshRate>59.940</RefreshRate>
|
||||
</PreferredMode>
|
||||
</IddCxMonitorConfig>
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
struct IddCxVersionInfo {
|
||||
std::string windowsVersion;
|
||||
std::string iddcxVersion;
|
||||
ULONG versionValue;
|
||||
};
|
||||
|
||||
std::map<DWORD, IddCxVersionInfo> versionMap = {
|
||||
{26100, {"Windows 11 24H2", "1.10", 0x1A80}},
|
||||
{22631, {"Windows 11 23H2", "1.10", 0x1A00}},
|
||||
{22621, {"Windows 11 22H2", "1.9", 0x1900}},
|
||||
{22000, {"Windows 11 21H2", "1.8", 0x1800}},
|
||||
{19045, {"Windows 10 22H2", "1.5", 0x1500}},
|
||||
{19044, {"Windows 10 21H2", "1.5", 0x1500}},
|
||||
{19043, {"Windows 10 21H1", "1.5", 0x1500}},
|
||||
{19042, {"Windows 10 20H2", "1.5", 0x1500}},
|
||||
{19041, {"Windows 10 20H1", "1.5", 0x1500}},
|
||||
{18363, {"Windows 10 19H2", "1.4", 0x1400}},
|
||||
{18362, {"Windows 10 19H1", "1.4", 0x1400}},
|
||||
{17763, {"Windows 10 RS5", "1.3", 0x1300}},
|
||||
{17134, {"Windows 10 RS4", "1.3", 0x1300}},
|
||||
{16299, {"Windows 10 RS3", "1.3", 0x1300}},
|
||||
{15063, {"Windows 10 Creators Update", "1.2", 0x1200}},
|
||||
{14393, {"Windows 10 Anniversary Update", "1.0", 0x1000}},
|
||||
{10240, {"Windows 10 RTM", "1.0", 0x1000}}
|
||||
};
|
||||
|
||||
DWORD GetWindowsBuildNumber() {
|
||||
OSVERSIONINFOEX osvi;
|
||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
|
||||
HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
|
||||
if (hMod) {
|
||||
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion");
|
||||
|
||||
if (RtlGetVersion) {
|
||||
RTL_OSVERSIONINFOW rovi = { 0 };
|
||||
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
||||
if (RtlGetVersion(&rovi) == 0) {
|
||||
return rovi.dwBuildNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IddCxVersionInfo GetIddCxVersionFromBuild(DWORD buildNumber) {
|
||||
auto it = versionMap.find(buildNumber);
|
||||
if (it != versionMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
for (auto& pair : versionMap) {
|
||||
if (buildNumber >= pair.first) {
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
return {"Unknown Windows Version", "Unknown", 0x0000};
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "IddCx Version Query Tool\n";
|
||||
std::cout << "========================\n\n";
|
||||
|
||||
DWORD buildNumber = GetWindowsBuildNumber();
|
||||
|
||||
if (buildNumber == 0) {
|
||||
std::cout << "Error: Could not retrieve Windows build number.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Windows Build Number: " << buildNumber << "\n";
|
||||
|
||||
IddCxVersionInfo versionInfo = GetIddCxVersionFromBuild(buildNumber);
|
||||
|
||||
std::cout << "Windows Version: " << versionInfo.windowsVersion << "\n";
|
||||
std::cout << "IddCx Version: " << versionInfo.iddcxVersion << "\n";
|
||||
std::cout << "IddCx Version Value: 0x" << std::hex << std::uppercase << versionInfo.versionValue << "\n\n";
|
||||
|
||||
if (versionInfo.iddcxVersion == "Unknown") {
|
||||
std::cout << "Note: This Windows build may not support IddCx or uses an unknown version.\n";
|
||||
std::cout << "IddCx was introduced in Windows 10 Creators Update (build 15063).\n";
|
||||
} else {
|
||||
std::cout << "IddCx Framework Information:\n";
|
||||
std::cout << "- IddCx (Indirect Display Driver Class eXtension) is a framework for\n";
|
||||
std::cout << " developing indirect display drivers in Windows.\n";
|
||||
std::cout << "- This version provides specific capabilities and APIs for indirect\n";
|
||||
std::cout << " display driver development.\n";
|
||||
}
|
||||
|
||||
std::cout << "\nPress any key to exit...";
|
||||
std::cin.get();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
@echo off
|
||||
echo Building IddCx Version Query Tool...
|
||||
echo.
|
||||
|
||||
if exist "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cl /EHsc IddCxVersionQuery.cpp /Fe:IddCxVersionQuery.exe
|
||||
) else if exist "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cl /EHsc IddCxVersionQuery.cpp /Fe:IddCxVersionQuery.exe
|
||||
) else (
|
||||
echo Visual Studio not found. Trying g++...
|
||||
g++ -std=c++11 -o IddCxVersionQuery.exe IddCxVersionQuery.cpp
|
||||
)
|
||||
|
||||
if exist IddCxVersionQuery.exe (
|
||||
echo.
|
||||
echo Build successful! Run IddCxVersionQuery.exe to check IddCx version.
|
||||
) else (
|
||||
echo.
|
||||
echo Build failed. Please ensure you have a C++ compiler installed.
|
||||
echo You can install Visual Studio Community or MinGW-w64.
|
||||
)
|
||||
|
||||
pause
|
||||
@@ -1,46 +1,30 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31129.286
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36717.8
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IddSampleDriver", "IddSampleDriver\IddSampleDriver.vcxproj", "{2D54CB75-8B17-4F11-97DC-847B0244CD46}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MttVDD", "MttVDD\MttVDD.vcxproj", "{2D54CB75-8B17-4F11-97DC-847B0244CD46}"
|
||||
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
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.ActiveCfg = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Build.0 = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Deploy.0 = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Build.0 = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Build.0 = Release|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.ActiveCfg = Release|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Build.0 = Release|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Deploy.0 = Release|x64
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Build.0 = Release|Win32
|
||||
{2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Deploy.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
File diff suppressed because it is too large.
Load diff
@@ -3,7 +3,6 @@
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <bugcodes.h>
|
||||
#include <wudfwdm.h>
|
||||
#include <wdf.h>
|
||||
#include <iddcx.h>
|
||||
|
||||
@@ -14,9 +13,25 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "Trace.h"
|
||||
|
||||
// Utility function declarations
|
||||
std::vector<std::string> split(std::string& input, char delimiter);
|
||||
std::string WStringToString(const std::wstring& wstr);
|
||||
|
||||
// Phase 5: Final Integration function declarations
|
||||
NTSTATUS ValidateEdidIntegration();
|
||||
NTSTATUS PerformanceMonitor();
|
||||
NTSTATUS CreateFallbackConfiguration();
|
||||
NTSTATUS ValidateAndSanitizeConfiguration();
|
||||
NTSTATUS RunComprehensiveDiagnostics();
|
||||
NTSTATUS InitializePhase5Integration();
|
||||
|
||||
namespace Microsoft
|
||||
{
|
||||
namespace WRL
|
||||
@@ -72,6 +87,19 @@ namespace Microsoft
|
||||
Microsoft::WRL::Wrappers::Event m_hTerminateEvent;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Custom comparator for LUID to be used in std::map
|
||||
/// </summary>
|
||||
struct LuidComparator
|
||||
{
|
||||
bool operator()(const LUID& a, const LUID& b) const
|
||||
{
|
||||
if (a.HighPart != b.HighPart)
|
||||
return a.HighPart < b.HighPart;
|
||||
return a.LowPart < b.LowPart;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Provides a sample implementation of an indirect display driver.
|
||||
/// </summary>
|
||||
@@ -86,7 +114,7 @@ namespace Microsoft
|
||||
|
||||
void CreateMonitor(unsigned int index);
|
||||
|
||||
void AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent);
|
||||
void AssignSwapChain(IDDCX_MONITOR& Monitor, IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent);
|
||||
void UnassignSwapChain();
|
||||
|
||||
protected:
|
||||
@@ -100,7 +128,13 @@ namespace Microsoft
|
||||
|
||||
public:
|
||||
static const DISPLAYCONFIG_VIDEO_SIGNAL_INFO s_KnownMonitorModes[];
|
||||
static const BYTE s_KnownMonitorEdid[];
|
||||
static std::vector<BYTE> s_KnownMonitorEdid;
|
||||
|
||||
private:
|
||||
static std::map<LUID, std::shared_ptr<Direct3DDevice>, LuidComparator> s_DeviceCache;
|
||||
static std::mutex s_DeviceCacheMutex;
|
||||
static std::shared_ptr<Direct3DDevice> GetOrCreateDevice(LUID RenderAdapter);
|
||||
static void CleanupExpiredDevices();
|
||||
};
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- Configurations -->
|
||||
<ItemGroup Label="ProjectConfigurations"><!-- Setting Release|x64 first makes it the default selection in VS -->
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Sources -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Driver.h" />
|
||||
<ClInclude Include="Trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="MttVDD.inf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="readme.md" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xml Include="..\vdd_settings.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Bat Include="..\install_experimental_VDD.bat" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Bat Include="..\uninstall.bat" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Globals -->
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{2D54CB75-8B17-4F11-97DC-847B0244CD46}</ProjectGuid>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<DriverType>Display</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<RootNamespace>MttVDD</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
<DriverTargetPlatformVersion>10.0.26100.0</DriverTargetPlatformVersion>
|
||||
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
|
||||
<UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
|
||||
<UMDF_MINIMUM_VERSION_REQUIRED>25</UMDF_MINIMUM_VERSION_REQUIRED>
|
||||
<IndirectDisplayDriver>true</IndirectDisplayDriver>
|
||||
<IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
|
||||
<IDDCX_VERSION_MINOR>10</IDDCX_VERSION_MINOR>
|
||||
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
|
||||
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
<TimeStampServer>http://timestamp.globalsign.com/scripts/timstamp.dll</TimeStampServer>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Imports (CRITICAL: Load WDK properties after default C++ properties) -->
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.props" />
|
||||
|
||||
<Import Project="$(WDKContentRoot)build\inc\WDF.props" Condition="Exists('$(WDKContentRoot)\build\inc\WDF.props')" />
|
||||
<Import Project="$(WDKContentRoot)build\inc\WDF.targets" Condition="Exists('$(WDKContentRoot)\build\inc\WDF.targets')" />
|
||||
|
||||
<!-- Global defaults -->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<EnablePREfast>true</EnablePREfast>
|
||||
<!-- Use this line only for project-specific includes (e.g., Common\Include) -->
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\Common\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=$(IDDCX_VERSION_MAJOR) /DIDDCX_VERSION_MINOR=$(IDDCX_VERSION_MINOR) /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent Condition="Exists('$(WDKContentRoot)\bin\wdf\umdf\WUDFRd.sys')">
|
||||
<Command>copy "$(WDKContentRoot)bin\wdf\umdf\WUDFRd.sys" "$(TargetDir)"</Command>
|
||||
<Command>copy "$(ProjectDir)..\vdd_settings.xml" "$(TargetDir)MttVDD\"</Command>
|
||||
<Command>copy "$(ProjectDir)..\install_experimental_VDD.bat" "$(TargetDir)MttVDD\"</Command>
|
||||
<Command>copy "$(ProjectDir)..\uninstall.bat" "$(TargetDir)MttVDD\"</Command>
|
||||
</PostBuildEvent>
|
||||
<Inf>
|
||||
<DateStamp>11/27/2025</DateStamp>
|
||||
</Inf>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Debug VS Release Configuration -->
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Misc -->
|
||||
<PropertyGroup>
|
||||
<DisableDuplicatesInImportedFiles>true</DisableDuplicatesInImportedFiles>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,73 @@
|
||||
@echo off
|
||||
echo ==================================================
|
||||
echo VDD experimental Installer - Multi-Card Branch
|
||||
echo ==================================================
|
||||
echo.
|
||||
echo Installing test certificate...
|
||||
certutil -addstore root "%~dp0MttVDD.cer" >nul 2>&1
|
||||
certutil -addstore -f TrustedPublisher "%~dp0MttVDD.cer"
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: Failed to install certificate. Are you running as Administrator?
|
||||
pause
|
||||
exit /b 1
|
||||
) else (
|
||||
echo [OK] Test certificate installed (Root store)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Verifying required files...
|
||||
if not exist "%~dp0MttVDD.cat" (
|
||||
if exist "%~dp0mttvdd.cat" (
|
||||
echo Catalog file found with lowercase name, ensuring correct case...
|
||||
copy "%~dp0mttvdd.cat" "%~dp0MttVDD.cat" >nul 2>&1
|
||||
) else (
|
||||
echo ERROR: Catalog file (MttVDD.cat) not found!
|
||||
echo This is required for driver installation with PnpLockdown enabled.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
if not exist "%~dp0MttVDD.dll" (
|
||||
echo ERROR: Driver DLL (MttVDD.dll) not found!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Installing driver...
|
||||
pnputil /add-driver "%~dp0MttVDD.inf" /install
|
||||
if %errorlevel% neq 0 (
|
||||
echo ERROR: Driver installation failed. Reboot might be needed.
|
||||
echo -----
|
||||
echo Try manual installation in DeviceManager, Action, Legacy...
|
||||
pause
|
||||
exit /b 1
|
||||
) else (
|
||||
echo [OK] Driver installed successfully!
|
||||
)
|
||||
set "FOLDER=C:\VirtualDisplayDriver"
|
||||
set "NEWFILE=vdd_settings.xml"
|
||||
set "OLDFILE=old_vdd_settings.xml"
|
||||
|
||||
if exist "%FOLDER%" (
|
||||
if exist "%FOLDER%\%NEWFILE%" (
|
||||
ren "%FOLDER%\%NEWFILE%" "%FOLDER%\%OLDFILE%"
|
||||
) else (
|
||||
copy %NEWFILE%" %FOLDER%\%NEWFILE%
|
||||
)
|
||||
) else (
|
||||
md %FOLDER%
|
||||
copy %NEWFILE%" %FOLDER%\%NEWFILE%
|
||||
)
|
||||
copy "%~dpuninstall.bat" %FOLDER%
|
||||
copy "%~dpMttVDD.inf" %FOLDER%
|
||||
copy "%~dpMttVDD.dll" %FOLDER%
|
||||
copy "%~dpMttVDD.cer" %FOLDER%
|
||||
copy "%~dpmttvdd.cat" %FOLDER%
|
||||
copy "%~dpinstall_experimental_VDD.bat" %FOLDER%
|
||||
|
||||
echo.
|
||||
echo ==================================================
|
||||
echo Feedback is really appricated.
|
||||
echo ==================================================
|
||||
pause
|
||||
File renamed without changes.
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
echo Uninstalling MttVDD test driver...
|
||||
pnputil /enum-drivers | findstr /i "MttVDD"
|
||||
echo.
|
||||
echo Deleting driver package...
|
||||
pnputil /delete-driver oem??_mttvdd.inf /uninstall /force
|
||||
echo Removing test certificate...
|
||||
certutil -delstore Root "MttVDD Test Root" 2>nul
|
||||
echo Done. Reboot recommended.
|
||||
pause
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!-- ===============================================================================
|
||||
Virtual Display Driver (HDR) - Minimal Configuration File
|
||||
Contains ONLY functional settings (unused settings removed)
|
||||
|
||||
Original file contained 63 settings, this minimal version contains 52 functional settings
|
||||
Generated: August 16, 2025 based on driver code analysis
|
||||
=============================================================================== -->
|
||||
<vdd_settings>
|
||||
|
||||
<!-- === BASIC DRIVER CONFIGURATION === -->
|
||||
<monitors>
|
||||
<count>1</count>
|
||||
</monitors>
|
||||
|
||||
<gpu>
|
||||
<friendlyname>default</friendlyname>
|
||||
</gpu>
|
||||
|
||||
<!-- === RESOLUTION CONFIGURATION === -->
|
||||
<global>
|
||||
<!-- Global refresh rates - applied to all resolutions -->
|
||||
<g_refresh_rate>60</g_refresh_rate>
|
||||
<g_refresh_rate>90</g_refresh_rate>
|
||||
<g_refresh_rate>120</g_refresh_rate>
|
||||
<g_refresh_rate>144</g_refresh_rate>
|
||||
<g_refresh_rate>165</g_refresh_rate>
|
||||
<g_refresh_rate>240</g_refresh_rate>
|
||||
</global>
|
||||
|
||||
<resolutions>
|
||||
<resolution>
|
||||
<width>1920</width>
|
||||
<height>1080</height>
|
||||
<refresh_rate>60</refresh_rate>
|
||||
</resolution>
|
||||
<resolution>
|
||||
<width>2560</width>
|
||||
<height>1440</height>
|
||||
<refresh_rate>60</refresh_rate>
|
||||
</resolution>
|
||||
<resolution>
|
||||
<width>3840</width>
|
||||
<height>2160</height>
|
||||
<refresh_rate>60</refresh_rate>
|
||||
</resolution>
|
||||
</resolutions>
|
||||
|
||||
<!-- === LOGGING CONFIGURATION === -->
|
||||
<logging>
|
||||
<SendLogsThroughPipe>true</SendLogsThroughPipe>
|
||||
<logging>false</logging>
|
||||
<debuglogging>false</debuglogging> <!-- WARNING: Debug logging creates large files -->
|
||||
</logging>
|
||||
|
||||
<!-- === COLOR FORMAT CONFIGURATION === -->
|
||||
<colour>
|
||||
<SDR10bit>false</SDR10bit>
|
||||
<HDRPlus>false</HDRPlus>
|
||||
<ColourFormat>RGB</ColourFormat> <!-- Options: RGB, YCbCr444, YCbCr422, YCbCr420 -->
|
||||
</colour>
|
||||
|
||||
<!-- === CURSOR CONFIGURATION === -->
|
||||
<cursor>
|
||||
<HardwareCursor>true</HardwareCursor>
|
||||
<CursorMaxX>128</CursorMaxX>
|
||||
<CursorMaxY>128</CursorMaxY>
|
||||
<AlphaCursorSupport>true</AlphaCursorSupport>
|
||||
<!-- NOTE: XorCursorSupportLevel has implementation bug - loaded but not used -->
|
||||
<XorCursorSupportLevel>2</XorCursorSupportLevel>
|
||||
</cursor>
|
||||
|
||||
<!-- === CUSTOM EDID CONFIGURATION === -->
|
||||
<edid>
|
||||
<CustomEdid>false</CustomEdid> <!-- Use custom "user_edid.bin" file -->
|
||||
<PreventSpoof>false</PreventSpoof> <!-- Prevent manufacturer ID spoofing -->
|
||||
<EdidCeaOverride>false</EdidCeaOverride> <!-- Override CEA extension block -->
|
||||
</edid>
|
||||
|
||||
<!-- === EDID INTEGRATION SYSTEM === -->
|
||||
<edid_integration>
|
||||
<enabled>false</enabled> <!-- DISABLED: Enable when you have monitor_profile.xml -->
|
||||
<auto_configure_from_edid>false</auto_configure_from_edid> <!-- Auto-apply monitor_profile.xml -->
|
||||
<edid_profile_path>EDID/monitor_profile.xml</edid_profile_path>
|
||||
<override_manual_settings>false</override_manual_settings> <!-- false = manual settings take priority -->
|
||||
<fallback_on_error>true</fallback_on_error> <!-- Use manual settings if EDID fails -->
|
||||
</edid_integration>
|
||||
|
||||
<!-- === HDR CONFIGURATION === -->
|
||||
<hdr_advanced>
|
||||
<hdr10_static_metadata>
|
||||
<enabled>false</enabled> <!-- DISABLED: Enable for HDR10 support -->
|
||||
<max_display_mastering_luminance>1000.0</max_display_mastering_luminance>
|
||||
<min_display_mastering_luminance>0.05</min_display_mastering_luminance>
|
||||
<max_content_light_level>1000</max_content_light_level>
|
||||
<max_frame_avg_light_level>400</max_frame_avg_light_level>
|
||||
</hdr10_static_metadata>
|
||||
<color_primaries>
|
||||
<enabled>false</enabled> <!-- DISABLED: Enable for custom color primaries -->
|
||||
<red_x>0.640</red_x> <!-- sRGB color space (safe defaults) -->
|
||||
<red_y>0.330</red_y>
|
||||
<green_x>0.300</green_x>
|
||||
<green_y>0.600</green_y>
|
||||
<blue_x>0.150</blue_x>
|
||||
<blue_y>0.060</blue_y>
|
||||
<white_x>0.3127</white_x> <!-- D65 white point -->
|
||||
<white_y>0.3290</white_y>
|
||||
</color_primaries>
|
||||
<color_space>
|
||||
<enabled>false</enabled> <!-- DISABLED: Enable for advanced gamma -->
|
||||
<gamma_correction>2.2</gamma_correction> <!-- Standard sRGB gamma -->
|
||||
<primary_color_space>sRGB</primary_color_space> <!-- Safe default: sRGB -->
|
||||
<enable_matrix_transform>false</enable_matrix_transform>
|
||||
</color_space>
|
||||
</hdr_advanced>
|
||||
|
||||
<!-- === AUTO RESOLUTION SYSTEM === -->
|
||||
<auto_resolutions>
|
||||
<enabled>false</enabled> <!-- DISABLED: Enable for EDID mode generation -->
|
||||
<source_priority>manual</source_priority> <!-- Use manual resolutions only by default -->
|
||||
<edid_mode_filtering>
|
||||
<min_refresh_rate>24</min_refresh_rate>
|
||||
<max_refresh_rate>240</max_refresh_rate>
|
||||
<exclude_fractional_rates>false</exclude_fractional_rates>
|
||||
<min_resolution_width>640</min_resolution_width>
|
||||
<min_resolution_height>480</min_resolution_height>
|
||||
<max_resolution_width>7680</max_resolution_width>
|
||||
<max_resolution_height>4320</max_resolution_height>
|
||||
</edid_mode_filtering>
|
||||
<preferred_mode>
|
||||
<use_edid_preferred>false</use_edid_preferred> <!-- Use manual preferred mode -->
|
||||
<fallback_width>1920</fallback_width>
|
||||
<fallback_height>1080</fallback_height>
|
||||
<fallback_refresh>60</fallback_refresh>
|
||||
</preferred_mode>
|
||||
</auto_resolutions>
|
||||
|
||||
<!-- === ADVANCED COLOR PROCESSING === -->
|
||||
<color_advanced>
|
||||
<bit_depth_management>
|
||||
<auto_select_from_color_space>false</auto_select_from_color_space> <!-- Manual control -->
|
||||
<force_bit_depth>8</force_bit_depth> <!-- Safe default: 8-bit -->
|
||||
<fp16_surface_support>true</fp16_surface_support> <!-- Keep enabled for compatibility -->
|
||||
</bit_depth_management>
|
||||
<color_format_extended>
|
||||
<!-- NOTE: wide_color_gamut and hdr_tone_mapping are loaded but not implemented -->
|
||||
<sdr_white_level>80.0</sdr_white_level> <!-- Standard SDR white level -->
|
||||
</color_format_extended>
|
||||
</color_advanced>
|
||||
|
||||
<!-- === REMOVED SECTIONS ===
|
||||
|
||||
The following sections were present in the original vdd_settings.xml but have been
|
||||
removed because they are loaded but never used in the driver:
|
||||
|
||||
1. monitor_emulation (8 settings) - All settings loaded but unused
|
||||
- enabled, emulate_physical_dimensions, physical_width_mm, physical_height_mm
|
||||
- manufacturer_emulation/enabled, manufacturer_name, model_name, serial_number
|
||||
|
||||
2. color_format_extended partial (2 settings) - Loaded but unused
|
||||
- wide_color_gamut, hdr_tone_mapping
|
||||
|
||||
Driver uses hardcoded values instead of these XML settings.
|
||||
=== -->
|
||||
|
||||
</vdd_settings>
|
||||
@@ -0,0 +1,401 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
# but not Directory.Build.rsp, as it configures directory-level build defaults
|
||||
!Directory.Build.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
CLAUDE.md
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 MikeTheTech
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Source\Main\Main.vcxproj">
|
||||
<Project>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="PropertySheets">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Utility</ConfigurationType>
|
||||
<DriverType>Package</DriverType>
|
||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||
<Configuration>Debug</Configuration>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}</ProjectGuid>
|
||||
<SampleGuid>{E9D167E6-E633-4284-8F02-FF86DF3B6D7F}</SampleGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup>
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<ImportToStore>False</ImportToStore>
|
||||
<InstallMode>None</InstallMode>
|
||||
<HardwareIdString />
|
||||
<CommandLine />
|
||||
<ScriptPath />
|
||||
<DeployFiles />
|
||||
<ScriptName />
|
||||
<ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>
|
||||
<EnableVerifier>False</EnableVerifier>
|
||||
<AllDrivers>False</AllDrivers>
|
||||
<VerifyProjectOutput>True</VerifyProjectOutput>
|
||||
<VerifyDrivers />
|
||||
<VerifyFlags>133563</VerifyFlags>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
|
||||
<UniqueIdentifier>{0924612D-FBA7-477E-BBB9-B3B6EA7C6B03}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{97311738-0AD8-4F7E-AC88-9C9BEAF53AEE}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
|
||||
<UniqueIdentifier>{8DC1C4F0-C285-400E-A983-77A339891354}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
<UniqueIdentifier>{9F086F34-79D2-4FAA-87FD-C2DBEFCED0BA}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,144 @@
|
||||
> [!WARNING]
|
||||
> This software is in beta and requires test signing to be enabled.
|
||||
# Virtual Audio Driver by MikeTheTech
|
||||
|
||||
Welcome to the **Virtual Audio Driver by MikeTheTech**! This project provides two key drivers based on the Windows Driver Kit (WDK):
|
||||
|
||||
- **Virtual Audio Driver** – Creates a virtual speaker output device and a virtual microphone input device.
|
||||
|
||||
Both features in the driver are suitable for remote desktop sessions, headless configurations, streaming setups, and more. They support Windows 10 and Windows 11, including advanced audio features like Windows Sonic (Spatial Sound), Exclusive Mode, Application Priority, and volume control.
|
||||
|
||||
<div align="center">
|
||||
<img src="https://github.com/user-attachments/assets/1e833f96-5565-4938-a242-b239074012b0" alt="image">
|
||||
<img src="https://github.com/user-attachments/assets/db8c23f3-cf2d-409f-ada8-38d0aa8450a8" width="31%" alt="image">
|
||||
<img src="https://github.com/user-attachments/assets/8cf14cc2-4ab0-41ad-a6b2-5a77b004a943" width="31%" alt="image">
|
||||
<img src="https://github.com/user-attachments/assets/5f2e23cb-75d3-4557-98ff-7c717f47dcdd" width="31%" alt="image">
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||
A virtual audio driver set consists of:
|
||||
|
||||
- **Virtual Audio** ("fake" speaker output)
|
||||
- Essential for headless servers, remote desktop streaming, testing audio in environments without physical speakers, etc.
|
||||
|
||||
- **Virtual Microphone** ("fake" mic input)
|
||||
- Ideal for streaming setups, voice chat tests, combining or routing audio internally, or feeding software-generated audio to apps expecting a microphone input.
|
||||
|
||||
By installing these drivers, you can process or forward audio without physical hardware present, making them incredibly useful for various development, testing, and media production scenarios.
|
||||
|
||||
---
|
||||
|
||||
## Key Features
|
||||
|
||||
| Feature | Virtual Speaker | Virtual Microphone |
|
||||
|----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Emulated Device** | Emulates a speaker device recognized by Windows. | Emulates a microphone device recognized by Windows. |
|
||||
| **Supported Audio Formats** | **8-bit, 8000 Hz** (lowest quality) up to **32-bit, 192,000 Hz** (studio quality). This includes various presets such as Telephone Quality (8-bit, 11025 Hz) and DVD/Studio Quality (16/24/32-bit, up to 192 kHz). | **16-bit 44,100 Hz**, **16-bit 48,000 Hz**, **24-bit 96,000 Hz**, **24-bit 192,000 Hz**, **32-bit 48,000 Hz** (for testing or specialized scenarios). |
|
||||
| **Spatial Sound Support** (Speaker Only) | Integrates with Windows Sonic, enabling immersive 3D audio features. | Integrated with Audio Enhancements such as Voice Focus and Background Noise Reduction. |
|
||||
| **Exclusive Mode and App Priority** | Applications can claim exclusive control of the device. | Same WDK architecture applies, allowing exclusive access in supported workflows. |
|
||||
| **Volume Level Handling** | Handles global and per-application volume changes (Windows mixer). | Microphone level adjustments accessible via Windows Sound Settings or audio software. |
|
||||
| **High Customizability** | Built to be extended with future features and audio enhancements. | Allows flexible configuration of sampling rates and bit depths for specialized audio requirements. |
|
||||
|
||||
---
|
||||
|
||||
## Compatibility
|
||||
|
||||
- **OS**: Windows 10 (Build 1903 and above) and Windows 11
|
||||
- **Architecture**: x64 (tested); ARM64
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Enable Test Signing (Optional)**
|
||||
If you have a test-signed driver, you may need to enable test signing mode:
|
||||
```powershell
|
||||
bcdedit /set testsigning on
|
||||
```
|
||||
*Note: A production-signed driver can skip this step.*
|
||||
|
||||
2. **Open Device Manager**
|
||||
- Choose **Audio inputs and outputs**, then in the top **Action** menu, choose **Add Legacy Hardware**.
|
||||
- Choose **Install the hardware that I manually select from a list (Advanced)**
|
||||
- Choose **Sound, video and game controllers**
|
||||
- Choose "Have Disk..." and locate the **VirtualAudioDriver.inf**
|
||||
- Continue with the installation.
|
||||
|
||||
3. **Verify Installation**
|
||||
- Open **Device Manager**.
|
||||
- Check under **Sound, video and game controllers** for “Virtual Audio Driver” (speaker).
|
||||
- Check under **Audio inputs and outputs** for “Virtual Mic Driver” (microphone).
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Using the Virtual Speaker
|
||||
|
||||
1. **Select as Default Device**
|
||||
- Open **Sound Settings** → **Output** → Choose “Virtual Audio Driver” as your default output device.
|
||||
- Or use the **Volume Mixer** to route specific apps to the virtual speaker.
|
||||
|
||||
2. **Remote Desktop or Streaming**
|
||||
- When initiating a remote desktop session, the virtual speaker device can appear as a valid playback device.
|
||||
- Streaming or capture apps can detect the virtual speaker for capturing system audio.
|
||||
|
||||
3. **Choosing Quality Settings**
|
||||
- In **Sound Settings**, under **Playback Devices**, right-click the “Virtual Audio Driver” and select **Properties** → **Advanced** tab.
|
||||
- Choose from the newly added sample rates and bit depths (ranging from 8-bit, 8000 Hz to 32-bit, 192,000 Hz) to match your desired use case (e.g., “Telephone Quality,” “DVD Quality,” or “Studio Quality”).
|
||||
|
||||
4. **Spatial Sound**
|
||||
- In **Sound Settings**, right-click the device, select **Properties** → **Spatial Sound** tab, and enable **Windows Sonic for Headphones** or another supported format.
|
||||
|
||||
### Using the Virtual Microphone
|
||||
|
||||
1. **Select as Default Recording Device**
|
||||
- Open **Sound Settings** → **Input** → Choose “Virtual Mic Driver” as your default input device.
|
||||
- Alternatively, in the **Volume Mixer** or your specific application’s audio settings, route or select the “Virtual Mic Driver” for input.
|
||||
|
||||
2. **Supported Formats**
|
||||
- The Virtual Microphone Driver supports:
|
||||
- **16-bit, 44,100 Hz**
|
||||
- **16-bit, 48,000 Hz**
|
||||
- **24-bit, 96,000 Hz**
|
||||
- **24-bit, 192,000 Hz**
|
||||
- **32-bit, 48,000 Hz**
|
||||
|
||||
3. **Use Cases**
|
||||
- **Voice Chat / Conference Apps**: Emulate or inject audio into Zoom, Teams, Discord, etc.
|
||||
- **Streaming / Broadcasting**: Feed application-generated audio to OBS, XSplit, or other streaming tools.
|
||||
- **Audio Testing**: Confirm that your software or game engine’s microphone-handling logic works without real hardware.
|
||||
|
||||
4. **Volume & Level Controls**
|
||||
- Adjust input levels in **Sound Settings** → **Recording** tab.
|
||||
- Per-app mic levels can be configured in certain software or system volume mixers (where supported).
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Exclusive Mode** (Speaker and Mic)
|
||||
By default, shared mode is enabled. For real-time, low-latency usage, open device properties, go to the **Advanced** tab, and uncheck “Allow applications to take exclusive control.”
|
||||
|
||||
- **Application Priority**
|
||||
Supported through Windows APIs. To prioritize a specific application for either the speaker or microphone, configure it via Windows advanced sound options or in your audio software.
|
||||
|
||||
- **Volume/Level Management**
|
||||
- For the Virtual Speaker, adjust in the main Sound Settings or the Volume Mixer.
|
||||
- For the Virtual Microphone, adjust input levels in the Recording tab of Sound Settings or in your audio software’s device preferences.
|
||||
|
||||
---
|
||||
|
||||
## Future Plans
|
||||
|
||||
- **Advanced Diagnostics**: Logging and debugging tools
|
||||
- **New Modes & Additional Formats**: Continued expansion of supported audio qualities.
|
||||
- **Additional Features**: Such as Automatic Volume Leveling (AVL), further spatial audio improvements, and custom routing tools.
|
||||
|
||||
> This project is maintained and actively improved. We welcome contributions, suggestions, and issue reports!
|
||||
|
||||
---
|
||||
|
||||
**Thank you for using the Virtual Audio Driver!**
|
||||
Feel free to open issues or submit pull requests if you encounter any problems or have ideas to share. Happy audio routing!
|
||||
@@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{771312CF-E5A2-4676-8142-86CEBDF99E2B}</ProjectGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">x64</Platform>
|
||||
<SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</SampleGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(IntDir)</OutDir>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ItemGroup Label="WrappedTaskItems" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>Filters</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<TargetName>Filters</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>Filters</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<TargetName>Filters</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="micarraytopo.cpp" />
|
||||
<ClCompile Include="speakertopo.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Exclude="@(Inf)" Include="*.inf" />
|
||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
|
||||
<None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
|
||||
<None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
|
||||
<UniqueIdentifier>{75C3E63D-04EA-4EB3-B9F1-505497C51F71}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{5E8F8D4C-2886-4109-9E78-CE5EA6DB4AC4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
|
||||
<UniqueIdentifier>{75D3016A-4ED8-4FAF-9817-394BE1112534}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="*.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,210 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
micarray1toptable.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of topology tables for the mic array.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_MICARRAY1TOPTABLE_H_
|
||||
#define _VIRTUALAUDIODRIVER_MICARRAY1TOPTABLE_H_
|
||||
|
||||
//
|
||||
// {6ae81ff4-203e-4fe1-88aa-f2d57775cd4a}
|
||||
DEFINE_GUID(MICARRAY1_CUSTOM_NAME,
|
||||
0x6ae81ff4, 0x203e, 0x4fe1, 0x88, 0xaa, 0xf2, 0xd5, 0x77, 0x75, 0xcd, 0x4a);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
KSDATARANGE MicArray1TopoPinDataRangesBridge[] =
|
||||
{
|
||||
{
|
||||
sizeof(KSDATARANGE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PKSDATARANGE MicArray1TopoPinDataRangePointersBridge[] =
|
||||
{
|
||||
&MicArray1TopoPinDataRangesBridge[0]
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPIN_DESCRIPTOR MicArray1TopoMiniportPins[] =
|
||||
{
|
||||
// KSPIN_TOPO_MIC_ELEMENTS
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0, // InstanceCount
|
||||
NULL, // AutomationTable
|
||||
{ // KsPinDescriptor
|
||||
0, // InterfacesCount
|
||||
NULL, // Interfaces
|
||||
0, // MediumsCount
|
||||
NULL, // Mediums
|
||||
SIZEOF_ARRAY(MicArray1TopoPinDataRangePointersBridge), // DataRangesCount
|
||||
MicArray1TopoPinDataRangePointersBridge, // DataRanges
|
||||
KSPIN_DATAFLOW_IN, // DataFlow
|
||||
KSPIN_COMMUNICATION_NONE, // Communication
|
||||
&KSNODETYPE_MICROPHONE_ARRAY, // Category
|
||||
&MICARRAY1_CUSTOM_NAME, // Name
|
||||
0 // Reserved
|
||||
}
|
||||
},
|
||||
|
||||
// KSPIN_TOPO_BRIDGE
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0, // InstanceCount
|
||||
NULL, // AutomationTable
|
||||
{ // KsPinDescriptor
|
||||
0, // InterfacesCount
|
||||
NULL, // Interfaces
|
||||
0, // MediumsCount
|
||||
NULL, // Mediums
|
||||
SIZEOF_ARRAY(MicArray1TopoPinDataRangePointersBridge), // DataRangesCount
|
||||
MicArray1TopoPinDataRangePointersBridge, // DataRanges
|
||||
KSPIN_DATAFLOW_OUT, // DataFlow
|
||||
KSPIN_COMMUNICATION_NONE, // Communication
|
||||
&KSCATEGORY_AUDIO, // Category
|
||||
NULL, // Name
|
||||
0 // Reserved
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPROPERTY_ITEM MicArray1PropertiesVolume[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_VOLUMELEVEL,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopology
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArray1Volume, MicArray1PropertiesVolume);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPROPERTY_ITEM MicArray1PropertiesMute[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_MUTE,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopology
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArray1Mute, MicArray1PropertiesMute);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCNODE_DESCRIPTOR MicArray1TopologyNodes[] =
|
||||
{
|
||||
// KSNODE_TOPO_VOLUME
|
||||
{
|
||||
0, // Flags
|
||||
&AutomationMicArray1Volume, // AutomationTable
|
||||
&KSNODETYPE_VOLUME, // Type
|
||||
&KSAUDFNAME_MIC_VOLUME // Name
|
||||
},
|
||||
// KSNODE_TOPO_MUTE
|
||||
{
|
||||
0, // Flags
|
||||
&AutomationMicArray1Mute, // AutomationTable
|
||||
&KSNODETYPE_MUTE, // Type
|
||||
&KSAUDFNAME_MIC_MUTE // Name
|
||||
}
|
||||
};
|
||||
|
||||
C_ASSERT(KSNODE_TOPO_VOLUME == 0);
|
||||
C_ASSERT(KSNODE_TOPO_MUTE == 1);
|
||||
|
||||
static
|
||||
PCCONNECTION_DESCRIPTOR MicArray1TopoMiniportConnections[] =
|
||||
{
|
||||
// FromNode, FromPin, ToNode, ToPin
|
||||
{ PCFILTER_NODE, KSPIN_TOPO_MIC_ELEMENTS, KSNODE_TOPO_VOLUME, 1 },
|
||||
{ KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 },
|
||||
{ KSNODE_TOPO_MUTE, 0, PCFILTER_NODE, KSPIN_TOPO_BRIDGE }
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPROPERTY_ITEM MicArray1PropertiesTopoFilter[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Jack,
|
||||
KSPROPERTY_JACK_DESCRIPTION,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopoFilter
|
||||
},
|
||||
{
|
||||
&KSPROPSETID_Jack,
|
||||
KSPROPERTY_JACK_DESCRIPTION2,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopoFilter
|
||||
},
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopoFilter
|
||||
},
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_MIC_SNR,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopoFilter
|
||||
},
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_MIC_SENSITIVITY2,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_MicArrayTopoFilter
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArray1TopoFilter, MicArray1PropertiesTopoFilter);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCFILTER_DESCRIPTOR MicArray1TopoMiniportFilterDescriptor =
|
||||
{
|
||||
0, // Version
|
||||
&AutomationMicArray1TopoFilter, // AutomationTable
|
||||
sizeof(PCPIN_DESCRIPTOR), // PinSize
|
||||
SIZEOF_ARRAY(MicArray1TopoMiniportPins), // PinCount
|
||||
MicArray1TopoMiniportPins, // Pins
|
||||
sizeof(PCNODE_DESCRIPTOR), // NodeSize
|
||||
SIZEOF_ARRAY(MicArray1TopologyNodes), // NodeCount
|
||||
MicArray1TopologyNodes, // Nodes
|
||||
SIZEOF_ARRAY(MicArray1TopoMiniportConnections),// ConnectionCount
|
||||
MicArray1TopoMiniportConnections, // Connections
|
||||
0, // CategoryCount
|
||||
NULL // Categories
|
||||
};
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_MICARRAY1TOPTABLE_H_
|
||||
@@ -0,0 +1,824 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
micarraytopo.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of topology miniport for the mic array.
|
||||
|
||||
--*/
|
||||
|
||||
#pragma warning (disable : 4127)
|
||||
|
||||
#include "definitions.h"
|
||||
#include "endpoints.h"
|
||||
#include "common.h"
|
||||
#include "kshelper.h"
|
||||
#include "micarraytopo.h"
|
||||
#include "micarray1toptable.h"
|
||||
|
||||
constexpr float MICARRAY_SENSITIVITY = -46.5f;
|
||||
constexpr float MICARRAY_SENSITIVITY2 = -23.5f;
|
||||
constexpr float MICARRAY_SNR = 66.0f;
|
||||
|
||||
constexpr inline LONG FloatToFixedPoint16_16(float fl)
|
||||
{
|
||||
return (static_cast<LONG>((fl) * (65536.0f)));
|
||||
}
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
CreateMicArrayMiniportTopology
|
||||
(
|
||||
_Out_ PUNKNOWN* Unknown,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ POOL_FLAGS PoolFlags,
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_opt_ PVOID DeviceContext,
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Creates a new topology miniport.
|
||||
|
||||
Arguments:
|
||||
|
||||
Unknown -
|
||||
|
||||
RefclsId -
|
||||
|
||||
UnknownOuter -
|
||||
|
||||
PoolType -
|
||||
|
||||
UnknownAdapter -
|
||||
|
||||
DeviceContext -
|
||||
|
||||
MiniportPair -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(Unknown);
|
||||
ASSERT(MiniportPair);
|
||||
|
||||
UNREFERENCED_PARAMETER(UnknownAdapter);
|
||||
UNREFERENCED_PARAMETER(DeviceContext);
|
||||
|
||||
CMicArrayMiniportTopology* obj =
|
||||
new (PoolFlags, MINTOPORT_POOLTAG)
|
||||
CMicArrayMiniportTopology(UnknownOuter,
|
||||
MiniportPair->TopoDescriptor,
|
||||
MiniportPair->DeviceMaxChannels,
|
||||
MiniportPair->DeviceType);
|
||||
if (NULL == obj)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
obj->AddRef();
|
||||
|
||||
*Unknown = reinterpret_cast<IUnknown*>(obj);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
} // CreateMicArrayMiniportTopology
|
||||
|
||||
//=============================================================================
|
||||
CMicArrayMiniportTopology::~CMicArrayMiniportTopology
|
||||
(
|
||||
void
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Topology miniport destructor
|
||||
|
||||
Arguments:
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[CMicArrayMiniportTopology::~CMicArrayMiniportTopology]"));
|
||||
} // ~CMicArrayMiniportTopology
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
CMicArrayMiniportTopology::DataRangeIntersection
|
||||
(
|
||||
_In_ ULONG PinId,
|
||||
_In_ PKSDATARANGE ClientDataRange,
|
||||
_In_ PKSDATARANGE MyDataRange,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
|
||||
PVOID ResultantFormat OPTIONAL,
|
||||
_Out_ PULONG ResultantFormatLength
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The DataRangeIntersection function determines the highest quality
|
||||
intersection of two data ranges.
|
||||
|
||||
Arguments:
|
||||
|
||||
PinId - Pin for which data intersection is being determined.
|
||||
|
||||
ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
|
||||
submitted by client in the data range intersection property
|
||||
request.
|
||||
|
||||
MyDataRange - Pin's data range to be compared with client's data range.
|
||||
|
||||
OutputBufferLength - Size of the buffer pointed to by the resultant format
|
||||
parameter.
|
||||
|
||||
ResultantFormat - Pointer to value where the resultant format should be
|
||||
returned.
|
||||
|
||||
ResultantFormatLength - Actual length of the resultant format that is placed
|
||||
at ResultantFormat. This should be less than or equal
|
||||
to OutputBufferLength.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
return
|
||||
CMiniportTopologyVirtualAudioDriver::DataRangeIntersection
|
||||
(
|
||||
PinId,
|
||||
ClientDataRange,
|
||||
MyDataRange,
|
||||
OutputBufferLength,
|
||||
ResultantFormat,
|
||||
ResultantFormatLength
|
||||
);
|
||||
} // DataRangeIntersection
|
||||
|
||||
//=============================================================================
|
||||
STDMETHODIMP
|
||||
CMicArrayMiniportTopology::GetDescription
|
||||
(
|
||||
_Out_ PPCFILTER_DESCRIPTOR* OutFilterDescriptor
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The GetDescription function gets a pointer to a filter description.
|
||||
It provides a location to deposit a pointer in miniport's description
|
||||
structure. This is the placeholder for the FromNode or ToNode fields in
|
||||
connections which describe connections to the filter's pins.
|
||||
|
||||
Arguments:
|
||||
|
||||
OutFilterDescriptor - Pointer to the filter description.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(OutFilterDescriptor);
|
||||
|
||||
return CMiniportTopologyVirtualAudioDriver::GetDescription(OutFilterDescriptor);
|
||||
} // GetDescription
|
||||
|
||||
//=============================================================================
|
||||
STDMETHODIMP
|
||||
CMicArrayMiniportTopology::Init
|
||||
(
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_ PRESOURCELIST ResourceList,
|
||||
_In_ PPORTTOPOLOGY Port_
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The Init function initializes the miniport. Callers of this function
|
||||
should run at IRQL PASSIVE_LEVEL
|
||||
|
||||
Arguments:
|
||||
|
||||
UnknownAdapter - A pointer to the IUnknown interface of the adapter object.
|
||||
|
||||
ResourceList - Pointer to the resource list to be supplied to the miniport
|
||||
during initialization. The port driver is free to examine the
|
||||
contents of the ResourceList. The port driver will not be
|
||||
modify the ResourceList contents.
|
||||
|
||||
Port - Pointer to the topology port object that is linked with this miniport.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ResourceList);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(UnknownAdapter);
|
||||
ASSERT(Port_);
|
||||
|
||||
DPF_ENTER(("[CMicArrayMiniportTopology::Init]"));
|
||||
|
||||
NTSTATUS ntStatus;
|
||||
|
||||
ntStatus =
|
||||
CMiniportTopologyVirtualAudioDriver::Init
|
||||
(
|
||||
UnknownAdapter,
|
||||
Port_
|
||||
);
|
||||
|
||||
return ntStatus;
|
||||
} // Init
|
||||
|
||||
//=============================================================================
|
||||
STDMETHODIMP
|
||||
CMicArrayMiniportTopology::NonDelegatingQueryInterface
|
||||
(
|
||||
_In_ REFIID Interface,
|
||||
_COM_Outptr_ PVOID* Object
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
QueryInterface for MiniportTopology
|
||||
|
||||
Arguments:
|
||||
|
||||
Interface - GUID of the interface
|
||||
|
||||
Object - interface object to be returned.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(Object);
|
||||
|
||||
if (IsEqualGUIDAligned(Interface, IID_IUnknown))
|
||||
{
|
||||
*Object = PVOID(PUNKNOWN(this));
|
||||
}
|
||||
else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
|
||||
{
|
||||
*Object = PVOID(PMINIPORT(this));
|
||||
}
|
||||
else if (IsEqualGUIDAligned(Interface, IID_IMiniportTopology))
|
||||
{
|
||||
*Object = PVOID(PMINIPORTTOPOLOGY(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
*Object = NULL;
|
||||
}
|
||||
|
||||
if (*Object)
|
||||
{
|
||||
// We reference the interface for the caller.
|
||||
PUNKNOWN(*Object)->AddRef();
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
return(STATUS_INVALID_PARAMETER);
|
||||
} // NonDelegatingQueryInterface
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
CMicArrayMiniportTopology::PropertyHandlerMicArrayGeometry
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY )
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandlerMicArrayGeometry]"));
|
||||
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
ULONG nPinId = (ULONG)-1;
|
||||
|
||||
if (PropertyRequest->InstanceSize >= sizeof(ULONG))
|
||||
{
|
||||
nPinId = *(PULONG(PropertyRequest->Instance));
|
||||
|
||||
if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
|
||||
{
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
|
||||
{
|
||||
ntStatus =
|
||||
PropertyHandler_BasicSupport
|
||||
(
|
||||
PropertyRequest,
|
||||
KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
|
||||
VT_ILLEGAL
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG cElements = 2;
|
||||
ULONG cbNeeded = FIELD_OFFSET(KSAUDIO_MIC_ARRAY_GEOMETRY, KsMicCoord) +
|
||||
cElements * sizeof(KSAUDIO_MICROPHONE_COORDINATES);
|
||||
|
||||
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)
|
||||
{
|
||||
PKSAUDIO_MIC_ARRAY_GEOMETRY pMAG = (PKSAUDIO_MIC_ARRAY_GEOMETRY)PropertyRequest->Value;
|
||||
const SHORT MicArray_45_Degrees = 7854; // 10000 * pi / 4
|
||||
|
||||
// fill in mic array geometry fields
|
||||
pMAG->usVersion = 0x0100; // Version of Mic array specification (0x0100)
|
||||
pMAG->usMicArrayType = (USHORT)KSMICARRAY_MICARRAYTYPE_LINEAR; // Type of Mic Array
|
||||
pMAG->wVerticalAngleBegin = -MicArray_45_Degrees; // Work Volume Vertical Angle Begin
|
||||
pMAG->wVerticalAngleEnd = MicArray_45_Degrees; // Work Volume Vertical Angle End
|
||||
pMAG->wHorizontalAngleBegin = 0; // Work Volume HorizontalAngle Begin
|
||||
pMAG->wHorizontalAngleEnd = 0; // Work Volume HorizontalAngle End
|
||||
pMAG->usFrequencyBandLo = 100; // Low end of Freq Range
|
||||
pMAG->usFrequencyBandHi = 8000; // High end of Freq Range
|
||||
|
||||
pMAG->usNumberOfMicrophones = 2; // Count of microphone coordinate structures to follow.
|
||||
|
||||
pMAG->KsMicCoord[0].usType = (USHORT)KSMICARRAY_MICTYPE_CARDIOID;
|
||||
pMAG->KsMicCoord[0].wXCoord = 0;
|
||||
pMAG->KsMicCoord[0].wYCoord = 100;
|
||||
pMAG->KsMicCoord[0].wZCoord = 0;
|
||||
pMAG->KsMicCoord[0].wVerticalAngle = 0;
|
||||
pMAG->KsMicCoord[0].wHorizontalAngle = 0;
|
||||
|
||||
pMAG->KsMicCoord[1].usType = (USHORT)KSMICARRAY_MICTYPE_CARDIOID;
|
||||
pMAG->KsMicCoord[1].wXCoord = 0;
|
||||
pMAG->KsMicCoord[1].wYCoord = -100;
|
||||
pMAG->KsMicCoord[1].wZCoord = 0;
|
||||
pMAG->KsMicCoord[1].wVerticalAngle = 0;
|
||||
pMAG->KsMicCoord[1].wHorizontalAngle = 0;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
CMicArrayMiniportTopology::PropertyHandlerMicProperties
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_SNR )
|
||||
Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_SENSITIVITY2 )
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandlerMicProperties]"));
|
||||
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
ULONG nPinId = (ULONG)-1;
|
||||
KFLOATING_SAVE saveData;
|
||||
NTSTATUS fstatus;
|
||||
|
||||
if (PropertyRequest->InstanceSize >= sizeof(ULONG))
|
||||
{
|
||||
nPinId = *(PULONG(PropertyRequest->Instance));
|
||||
|
||||
if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
|
||||
{
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
|
||||
{
|
||||
ntStatus =
|
||||
PropertyHandler_BasicSupport
|
||||
(
|
||||
PropertyRequest,
|
||||
KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
|
||||
VT_ILLEGAL
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ntStatus =
|
||||
ValidatePropertyParams
|
||||
(
|
||||
PropertyRequest,
|
||||
sizeof(LONG),
|
||||
0
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
|
||||
{
|
||||
if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SNR)
|
||||
{
|
||||
LONG* micSNR = (LONG*)PropertyRequest->Value;
|
||||
fstatus = KeSaveFloatingPointState(&saveData);
|
||||
if (NT_SUCCESS(fstatus))
|
||||
{
|
||||
// Return microphone SNR information.
|
||||
*micSNR = FloatToFixedPoint16_16(MICARRAY_SNR); // convert float dB to fixed point arithmetic
|
||||
KeRestoreFloatingPointState(&saveData);
|
||||
}
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SENSITIVITY2)
|
||||
{
|
||||
LONG* micSensitivity2 = (LONG*)PropertyRequest->Value;
|
||||
fstatus = KeSaveFloatingPointState(&saveData);
|
||||
if (NT_SUCCESS(fstatus))
|
||||
{
|
||||
// Return microphone SNR information.
|
||||
*micSensitivity2 = FloatToFixedPoint16_16(MICARRAY_SENSITIVITY2); // convert float dB to fixed point arithmetic
|
||||
KeRestoreFloatingPointState(&saveData);
|
||||
}
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
CMicArrayMiniportTopology::PropertyHandlerJackDescription
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandlerJackDescription]"));
|
||||
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
ULONG nPinId = (ULONG)-1;
|
||||
|
||||
if (PropertyRequest->InstanceSize >= sizeof(ULONG))
|
||||
{
|
||||
nPinId = *(PULONG(PropertyRequest->Instance));
|
||||
|
||||
if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
|
||||
{
|
||||
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_DESCRIPTION);
|
||||
|
||||
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_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI + 1);
|
||||
|
||||
pMI->Size = cbNeeded;
|
||||
pMI->Count = 1;
|
||||
|
||||
pDesc->ChannelMapping = 0; // Don't specify channel mask for array mic
|
||||
pDesc->Color = 0x00000000; // Black. This is an integrated device
|
||||
pDesc->ConnectionType = eConnTypeUnknown; // Integrated.
|
||||
pDesc->GenLocation = eGenLocPrimaryBox;
|
||||
pDesc->GeoLocation = eGeoLocFront;
|
||||
pDesc->PortConnection = ePortConnIntegratedDevice;
|
||||
pDesc->IsConnected = TRUE; // This is an integrated device, so it's always "connected"
|
||||
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
CMicArrayMiniportTopology::PropertyHandlerJackDescription2
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandlerJackDescription2]"));
|
||||
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
ULONG nPinId = (ULONG)-1;
|
||||
|
||||
if (PropertyRequest->InstanceSize >= sizeof(ULONG))
|
||||
{
|
||||
nPinId = *(PULONG(PropertyRequest->Instance));
|
||||
|
||||
if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
|
||||
{
|
||||
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_DESCRIPTION2);
|
||||
|
||||
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_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI + 1);
|
||||
|
||||
pMI->Size = cbNeeded;
|
||||
pMI->Count = 1;
|
||||
|
||||
RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
|
||||
|
||||
//
|
||||
// Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
|
||||
// the jack is currently active, streaming, idle, or hardware not ready.
|
||||
//
|
||||
pDesc->DeviceStateInfo = 0;
|
||||
|
||||
//
|
||||
// From MSDN:
|
||||
// "If an audio device lacks jack presence detection, the IsConnected member of
|
||||
// the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
|
||||
// ambiguity that results from this dual meaning of the TRUE value for IsConnected,
|
||||
// a client application can call IKsJackDescription2::GetJackDescription2 to read
|
||||
// the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
|
||||
// the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
|
||||
// does in fact support jack presence detection. In that case, the return value of
|
||||
// the IsConnected member can be interpreted to accurately reflect the insertion status
|
||||
// of the jack."
|
||||
//
|
||||
// Bit definitions:
|
||||
// 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
|
||||
// 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
|
||||
//
|
||||
pDesc->JackCapabilities = 0;
|
||||
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
PropertyHandler_MicArrayTopoFilter
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Redirects property request to miniport object
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandler_MicArrayTopoFilter]"));
|
||||
|
||||
// PropertryRequest structure is filled by portcls.
|
||||
// MajorTarget is a pointer to miniport object for miniports.
|
||||
//
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
PCMicArrayMiniportTopology pMiniport = (PCMicArrayMiniportTopology)PropertyRequest->MajorTarget;
|
||||
|
||||
if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Audio))
|
||||
{
|
||||
if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerMicArrayGeometry(PropertyRequest);
|
||||
}
|
||||
else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SENSITIVITY2)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerMicProperties(PropertyRequest);
|
||||
}
|
||||
else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SNR)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerMicProperties(PropertyRequest);
|
||||
}
|
||||
}
|
||||
else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
|
||||
{
|
||||
if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerJackDescription(PropertyRequest);
|
||||
}
|
||||
else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerJackDescription2(PropertyRequest);
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // PropertyHandler_TopoFilter
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
PropertyHandler_MicArrayTopology
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Redirects property request to miniport object
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandler_MicArrayTopology]"));
|
||||
|
||||
// PropertryRequest structure is filled by portcls.
|
||||
// MajorTarget is a pointer to miniport object for miniports.
|
||||
//
|
||||
PCMicArrayMiniportTopology pMiniport = (PCMicArrayMiniportTopology)PropertyRequest->MajorTarget;
|
||||
|
||||
return pMiniport->PropertyHandlerGeneric(PropertyRequest);
|
||||
} // PropertyHandler_MicArrayTopology
|
||||
|
||||
#pragma code_seg()
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
micarraytopo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of mic array topology miniport.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_MICARRAYTOPO_H_
|
||||
#define _VIRTUALAUDIODRIVER_MICARRAYTOPO_H_
|
||||
|
||||
#include "basetopo.h"
|
||||
|
||||
//=============================================================================
|
||||
// Classes
|
||||
//=============================================================================
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CMicArrayMiniportTopology
|
||||
//
|
||||
|
||||
#pragma code_seg()
|
||||
class CMicArrayMiniportTopology :
|
||||
public CMiniportTopologyVirtualAudioDriver,
|
||||
public IMiniportTopology,
|
||||
public CUnknown
|
||||
{
|
||||
public:
|
||||
DECLARE_STD_UNKNOWN();
|
||||
CMicArrayMiniportTopology
|
||||
(
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ PCFILTER_DESCRIPTOR* FilterDesc,
|
||||
_In_ USHORT DeviceMaxChannels,
|
||||
_In_ eDeviceType DeviceType
|
||||
)
|
||||
: CUnknown(UnknownOuter),
|
||||
CMiniportTopologyVirtualAudioDriver(FilterDesc, DeviceMaxChannels),
|
||||
m_DeviceType(DeviceType)
|
||||
{
|
||||
ASSERT(m_DeviceType == eMicArrayDevice1);
|
||||
}
|
||||
|
||||
~CMicArrayMiniportTopology();
|
||||
|
||||
IMP_IMiniportTopology;
|
||||
|
||||
NTSTATUS PropertyHandlerMicArrayGeometry
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandlerMicProperties
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandlerJackDescription
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandlerJackDescription2
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
protected:
|
||||
eDeviceType m_DeviceType;
|
||||
|
||||
};
|
||||
|
||||
typedef CMicArrayMiniportTopology* PCMicArrayMiniportTopology;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CreateMicArrayMiniportTopology(
|
||||
_Out_ PUNKNOWN* Unknown,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ POOL_FLAGS PoolFlags,
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_opt_ PVOID DeviceContext,
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandler_MicArrayTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
|
||||
NTSTATUS PropertyHandler_MicArrayTopology(_In_ PPCPROPERTY_REQUEST PropertyRequest);
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_MICARRAYTOPO_H_
|
||||
@@ -0,0 +1,489 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
micarraywavtable.h
|
||||
|
||||
Abstract:-
|
||||
|
||||
Declaration of wave miniport tables for the mic array.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_MICARRAYWAVTABLE_H_
|
||||
#define _VIRTUALAUDIODRIVER_MICARRAYWAVTABLE_H_
|
||||
|
||||
//
|
||||
// Mic array range.
|
||||
//
|
||||
#define MICARRAY_RAW_CHANNELS 2 // Channels for raw mode
|
||||
#define MICARRAY_DEVICE_MAX_CHANNELS 2 // Max channels overall
|
||||
#define MICARRAY_32_BITS_PER_SAMPLE_PCM 32 // 32 Bits Per Sample
|
||||
#define MICARRAY_RAW_SAMPLE_RATE 48000 // Raw sample rate
|
||||
|
||||
//
|
||||
// Max # of pin instances.
|
||||
//
|
||||
#define MICARRAY_MAX_INPUT_STREAMS 1
|
||||
|
||||
//=============================================================================
|
||||
// Extended array of supported device formats.
|
||||
//=============================================================================
|
||||
static
|
||||
KSDATAFORMAT_WAVEFORMATEXTENSIBLE MicArrayPinSupportedDeviceFormats[] =
|
||||
{
|
||||
//------------------------------------------------------------------------
|
||||
// 48 KHz, 32-bit, 2 channels (Stereo)
|
||||
//------------------------------------------------------------------------
|
||||
{
|
||||
{
|
||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
{
|
||||
{
|
||||
WAVE_FORMAT_EXTENSIBLE, // wFormatTag
|
||||
2, // nChannels
|
||||
48000, // nSamplesPerSec
|
||||
48000 * 2 * 4, // nAvgBytesPerSec = 48000 * channels * bytes_per_sample
|
||||
2 * 4, // nBlockAlign = channels * bytes_per_sample
|
||||
32, // wBitsPerSample
|
||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||||
},
|
||||
32, // Samples (wValidBitsPerSample)
|
||||
KSAUDIO_SPEAKER_STEREO, // dwChannelMask
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
|
||||
}
|
||||
},
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 44.1 KHz, 16-bit, 2 channels (Stereo)
|
||||
//------------------------------------------------------------------------
|
||||
{
|
||||
{
|
||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
{
|
||||
{
|
||||
WAVE_FORMAT_EXTENSIBLE,
|
||||
2,
|
||||
44100,
|
||||
44100 * 2 * 2, // nAvgBytesPerSec = 44100 * channels * bytes_per_sample
|
||||
2 * 2, // nBlockAlign = channels * bytes_per_sample
|
||||
16,
|
||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||||
},
|
||||
16, // wValidBitsPerSample
|
||||
KSAUDIO_SPEAKER_STEREO,
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
|
||||
}
|
||||
},
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 48 KHz, 16-bit, 2 channels (Stereo)
|
||||
//------------------------------------------------------------------------
|
||||
{
|
||||
{
|
||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
{
|
||||
{
|
||||
WAVE_FORMAT_EXTENSIBLE,
|
||||
2,
|
||||
48000,
|
||||
48000 * 2 * 2, // nAvgBytesPerSec = 48000 * channels * bytes_per_sample
|
||||
2 * 2, // nBlockAlign = channels * bytes_per_sample
|
||||
16,
|
||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||||
},
|
||||
16,
|
||||
KSAUDIO_SPEAKER_STEREO,
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
|
||||
}
|
||||
},
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 96 KHz, 24-bit, 2 channels (Stereo)
|
||||
//------------------------------------------------------------------------
|
||||
{
|
||||
{
|
||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
{
|
||||
{
|
||||
WAVE_FORMAT_EXTENSIBLE,
|
||||
2,
|
||||
96000,
|
||||
96000 * 2 * 3, // nAvgBytesPerSec = 96000 * channels * bytes_per_sample
|
||||
2 * 3, // nBlockAlign = channels * bytes_per_sample
|
||||
24,
|
||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||||
},
|
||||
24,
|
||||
KSAUDIO_SPEAKER_STEREO,
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
|
||||
}
|
||||
},
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// 192 KHz, 24-bit, 2 channels (Stereo)
|
||||
//------------------------------------------------------------------------
|
||||
{
|
||||
{
|
||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
{
|
||||
{
|
||||
WAVE_FORMAT_EXTENSIBLE,
|
||||
2,
|
||||
192000,
|
||||
192000 * 2 * 3, // nAvgBytesPerSec = 192000 * channels * bytes_per_sample
|
||||
2 * 3, // nBlockAlign = channels * bytes_per_sample
|
||||
24,
|
||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||||
},
|
||||
24,
|
||||
KSAUDIO_SPEAKER_STEREO,
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
|
||||
}
|
||||
},
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Example: 48 KHz, 32-bit float, 2 channels (Stereo)
|
||||
// Uses FLOAT subtype instead of PCM.
|
||||
//------------------------------------------------------------------------
|
||||
{
|
||||
{
|
||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
{
|
||||
{
|
||||
WAVE_FORMAT_EXTENSIBLE,
|
||||
2,
|
||||
48000,
|
||||
48000 * 2 * 4, // 4 bytes per float sample
|
||||
2 * 4, // nBlockAlign
|
||||
32, // wBitsPerSample
|
||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||||
},
|
||||
32,
|
||||
KSAUDIO_SPEAKER_STEREO,
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// Supported modes (only on streaming pins).
|
||||
// Add references to each format you want to expose in a particular mode.
|
||||
//=============================================================================
|
||||
static
|
||||
MODE_AND_DEFAULT_FORMAT MicArrayPinSupportedDeviceModes[] =
|
||||
{
|
||||
// If you only have one signal processing mode (e.g., RAW),
|
||||
// you can list each supported format under it.
|
||||
{
|
||||
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
|
||||
&MicArrayPinSupportedDeviceFormats[0].DataFormat
|
||||
},
|
||||
{
|
||||
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
|
||||
&MicArrayPinSupportedDeviceFormats[1].DataFormat
|
||||
},
|
||||
{
|
||||
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
|
||||
&MicArrayPinSupportedDeviceFormats[2].DataFormat
|
||||
},
|
||||
{
|
||||
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
|
||||
&MicArrayPinSupportedDeviceFormats[3].DataFormat
|
||||
},
|
||||
{
|
||||
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
|
||||
&MicArrayPinSupportedDeviceFormats[4].DataFormat
|
||||
},
|
||||
{
|
||||
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
|
||||
&MicArrayPinSupportedDeviceFormats[5].DataFormat
|
||||
},
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// Notes on extension:
|
||||
//
|
||||
// 1. Adjust nChannels, nSamplesPerSec, wBitsPerSample, and the SUBTYPE_GUID
|
||||
// as appropriate. For example, floating-point (IEEE_FLOAT) is common for
|
||||
// advanced processing or higher-fidelity capture.
|
||||
//
|
||||
// 2. If you have multiple signal processing modes (like RAW, Speech, etc.),
|
||||
// you may add new MODE_AND_DEFAULT_FORMAT entries pointing to different
|
||||
// subsets of the MicArrayPinSupportedDeviceFormats array.
|
||||
//
|
||||
// 3. Make sure the size of KSDATAFORMAT_WAVEFORMATEXTENSIBLE (DataFormat.FormatSize)
|
||||
// matches the actual structure size, and that WAVEFORMATEXTENSIBLE is
|
||||
// used properly (e.g., wValidBitsPerSample must align with wBitsPerSample).
|
||||
//
|
||||
// 4. The GUID for KSDATAFORMAT_SUBTYPE_PCM or KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
|
||||
// must be used correctly if you are advertising PCM or float formats.
|
||||
//
|
||||
// 5. KSAUDIO_SPEAKER_STEREO is a standard channel mask for 2 channels.
|
||||
// If you have more channels (e.g., 4, 5.1, 7.1), use the appropriate
|
||||
// speaker channel masks (e.g. KSAUDIO_SPEAKER_5POINT1).
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//
|
||||
// The entries here must follow the same order as the filter's pin
|
||||
// descriptor array.
|
||||
//
|
||||
static
|
||||
PIN_DEVICE_FORMATS_AND_MODES MicArrayPinDeviceFormatsAndModes[] =
|
||||
{
|
||||
{
|
||||
BridgePin,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0
|
||||
},
|
||||
{
|
||||
SystemCapturePin,
|
||||
MicArrayPinSupportedDeviceFormats,
|
||||
SIZEOF_ARRAY(MicArrayPinSupportedDeviceFormats),
|
||||
MicArrayPinSupportedDeviceModes,
|
||||
SIZEOF_ARRAY(MicArrayPinSupportedDeviceModes)
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// Data ranges
|
||||
//
|
||||
// See CMiniportWaveRT::DataRangeIntersection.
|
||||
//
|
||||
static
|
||||
KSDATARANGE_AUDIO MicArrayPinDataRangesRawStream[] =
|
||||
{
|
||||
{
|
||||
{
|
||||
sizeof(KSDATARANGE_AUDIO),
|
||||
KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
|
||||
},
|
||||
MICARRAY_RAW_CHANNELS,
|
||||
MICARRAY_32_BITS_PER_SAMPLE_PCM,
|
||||
MICARRAY_32_BITS_PER_SAMPLE_PCM,
|
||||
MICARRAY_RAW_SAMPLE_RATE,
|
||||
MICARRAY_RAW_SAMPLE_RATE
|
||||
},
|
||||
};
|
||||
|
||||
static
|
||||
PKSDATARANGE MicArrayPinDataRangePointersStream[] =
|
||||
{
|
||||
// All supported device formats should be listed in the DataRange.
|
||||
PKSDATARANGE(&MicArrayPinDataRangesRawStream[0]),
|
||||
PKSDATARANGE(&PinDataRangeAttributeList),
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
KSDATARANGE MicArrayPinDataRangesBridge[] =
|
||||
{
|
||||
{
|
||||
sizeof(KSDATARANGE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
|
||||
}
|
||||
};
|
||||
|
||||
static
|
||||
PKSDATARANGE MicArrayPinDataRangePointersBridge[] =
|
||||
{
|
||||
&MicArrayPinDataRangesBridge[0]
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPIN_DESCRIPTOR MicArrayWaveMiniportPins[] =
|
||||
{
|
||||
// Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
{
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
SIZEOF_ARRAY(MicArrayPinDataRangePointersBridge),
|
||||
MicArrayPinDataRangePointersBridge,
|
||||
KSPIN_DATAFLOW_IN,
|
||||
KSPIN_COMMUNICATION_NONE,
|
||||
&KSCATEGORY_AUDIO,
|
||||
NULL,
|
||||
0
|
||||
}
|
||||
},
|
||||
// Wave In Streaming Pin (Capture) KSPIN_WAVE_HOST
|
||||
{
|
||||
MICARRAY_MAX_INPUT_STREAMS,
|
||||
MICARRAY_MAX_INPUT_STREAMS,
|
||||
0,
|
||||
NULL,
|
||||
{
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
SIZEOF_ARRAY(MicArrayPinDataRangePointersStream),
|
||||
MicArrayPinDataRangePointersStream,
|
||||
KSPIN_DATAFLOW_OUT,
|
||||
KSPIN_COMMUNICATION_SINK,
|
||||
&KSCATEGORY_AUDIO,
|
||||
&KSAUDFNAME_RECORDING_CONTROL,
|
||||
0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCNODE_DESCRIPTOR MicArrayWaveMiniportNodes[] =
|
||||
{
|
||||
// KSNODE_WAVE_ADC
|
||||
{
|
||||
0, // Flags
|
||||
NULL, // AutomationTable
|
||||
&KSNODETYPE_ADC, // Type
|
||||
NULL // Name
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCCONNECTION_DESCRIPTOR MicArrayWaveMiniportConnections[] =
|
||||
{
|
||||
{ PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 },
|
||||
{ KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST },
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
static
|
||||
VIRTUALAUDIODRIVER_PROPERTY_ITEM PropertiesMicArrayWaveFilter[] =
|
||||
{
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_General,
|
||||
KSPROPERTY_GENERAL_COMPONENTID,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_WaveFilter,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0
|
||||
},
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Pin,
|
||||
KSPROPERTY_PIN_PROPOSEDATAFORMAT,
|
||||
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_WaveFilter,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0
|
||||
},
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Pin,
|
||||
KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_WaveFilter,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArrayWaveFilter, PropertiesMicArrayWaveFilter);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCFILTER_DESCRIPTOR MicArrayWaveMiniportFilterDescriptor =
|
||||
{
|
||||
0, // Version
|
||||
&AutomationMicArrayWaveFilter, // AutomationTable
|
||||
sizeof(PCPIN_DESCRIPTOR), // PinSize
|
||||
SIZEOF_ARRAY(MicArrayWaveMiniportPins), // PinCount
|
||||
MicArrayWaveMiniportPins, // Pins
|
||||
sizeof(PCNODE_DESCRIPTOR), // NodeSize
|
||||
SIZEOF_ARRAY(MicArrayWaveMiniportNodes), // NodeCount
|
||||
MicArrayWaveMiniportNodes, // Nodes
|
||||
SIZEOF_ARRAY(MicArrayWaveMiniportConnections), // ConnectionCount
|
||||
MicArrayWaveMiniportConnections, // Connections
|
||||
0, // CategoryCount
|
||||
NULL // Categories - use defaults (audio, render, capture)
|
||||
};
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_MICARRAYWAVTABLE_H_
|
||||
@@ -0,0 +1,177 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
minipairs.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Local audio endpoint filter definitions.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_MINIPAIRS_H_
|
||||
#define _VIRTUALAUDIODRIVER_MINIPAIRS_H_
|
||||
|
||||
#include "speakertopo.h"
|
||||
#include "speakertoptable.h"
|
||||
#include "speakerwavtable.h"
|
||||
|
||||
#include "micarraytopo.h"
|
||||
#include "micarray1toptable.h"
|
||||
#include "micarraywavtable.h"
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CreateMiniportWaveRTVirtualAudioDriver
|
||||
(
|
||||
_Out_ PUNKNOWN *,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN,
|
||||
_In_ POOL_FLAGS,
|
||||
_In_ PUNKNOWN,
|
||||
_In_opt_ PVOID,
|
||||
_In_ PENDPOINT_MINIPAIR
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
CreateMiniportTopologyVirtualAudioDriver
|
||||
(
|
||||
_Out_ PUNKNOWN *,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN,
|
||||
_In_ POOL_FLAGS,
|
||||
_In_ PUNKNOWN,
|
||||
_In_opt_ PVOID,
|
||||
_In_ PENDPOINT_MINIPAIR
|
||||
);
|
||||
|
||||
//
|
||||
// Render miniports.
|
||||
//
|
||||
|
||||
/*********************************************************************
|
||||
* Topology/Wave bridge connection for speaker (internal) *
|
||||
* *
|
||||
* +------+ +------+ *
|
||||
* | Wave | | Topo | *
|
||||
* | | | | *
|
||||
* System --->|0 1|--------------->|0 1|---> Line Out *
|
||||
* | | | | *
|
||||
* +------+ +------+ *
|
||||
*********************************************************************/
|
||||
static
|
||||
PHYSICALCONNECTIONTABLE SpeakerTopologyPhysicalConnections[] =
|
||||
{
|
||||
{
|
||||
KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn
|
||||
KSPIN_WAVE_RENDER3_SOURCE, // WaveOut
|
||||
CONNECTIONTYPE_WAVE_OUTPUT
|
||||
}
|
||||
};
|
||||
|
||||
static
|
||||
ENDPOINT_MINIPAIR SpeakerMiniports =
|
||||
{
|
||||
eSpeakerDevice,
|
||||
L"TopologySpeaker", // make sure this or the template name matches with KSNAME_TopologySpeaker in the inf's [Strings] section
|
||||
NULL, // optional template name
|
||||
CreateMiniportTopologyVirtualAudioDriver,
|
||||
&SpeakerTopoMiniportFilterDescriptor,
|
||||
0, NULL, // Interface properties
|
||||
L"WaveSpeaker", // make sure this or the template name matches with KSNAME_WaveSpeaker in the inf's [Strings] section
|
||||
NULL, // optional template name
|
||||
CreateMiniportWaveRTVirtualAudioDriver,
|
||||
&SpeakerWaveMiniportFilterDescriptor,
|
||||
0, // Interface properties
|
||||
NULL,
|
||||
SPEAKER_DEVICE_MAX_CHANNELS,
|
||||
SpeakerPinDeviceFormatsAndModes,
|
||||
SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes),
|
||||
SpeakerTopologyPhysicalConnections,
|
||||
SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections),
|
||||
ENDPOINT_NO_FLAGS,
|
||||
};
|
||||
|
||||
//
|
||||
// Capture miniports.
|
||||
//
|
||||
|
||||
/*********************************************************************
|
||||
* Topology/Wave bridge connection for mic array 1 (front) *
|
||||
* *
|
||||
* +------+ +------+ *
|
||||
* | Topo | | Wave | *
|
||||
* | | | | *
|
||||
* Mic in --->|0 1|===>|0 1|---> Capture Host Pin *
|
||||
* | | | | *
|
||||
* +------+ +------+ *
|
||||
*********************************************************************/
|
||||
static
|
||||
PHYSICALCONNECTIONTABLE MicArray1TopologyPhysicalConnections[] =
|
||||
{
|
||||
{
|
||||
KSPIN_TOPO_BRIDGE, // TopologyOut
|
||||
KSPIN_WAVE_BRIDGE, // WaveIn
|
||||
CONNECTIONTYPE_TOPOLOGY_OUTPUT
|
||||
}
|
||||
};
|
||||
|
||||
static
|
||||
ENDPOINT_MINIPAIR MicArray1Miniports =
|
||||
{
|
||||
eMicArrayDevice1,
|
||||
L"TopologyMicArray1", // make sure this or the template name matches with KSNAME_TopologyMicArray1 in the inf's [Strings] section
|
||||
NULL, // optional template name
|
||||
CreateMicArrayMiniportTopology,
|
||||
&MicArray1TopoMiniportFilterDescriptor,
|
||||
0, NULL, // Interface properties
|
||||
L"WaveMicArray1", // make sure this or the tempalte name matches with KSNAME_WaveMicArray1 in the inf's [Strings] section
|
||||
NULL, // optional template name
|
||||
CreateMiniportWaveRTVirtualAudioDriver,
|
||||
&MicArrayWaveMiniportFilterDescriptor,
|
||||
0, // Interface properties
|
||||
NULL,
|
||||
MICARRAY_DEVICE_MAX_CHANNELS,
|
||||
MicArrayPinDeviceFormatsAndModes,
|
||||
SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes),
|
||||
MicArray1TopologyPhysicalConnections,
|
||||
SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections),
|
||||
ENDPOINT_NO_FLAGS,
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Render miniport pairs. NOTE: the split of render and capture is arbitrary and
|
||||
// unnessary, this array could contain capture endpoints.
|
||||
//
|
||||
static
|
||||
PENDPOINT_MINIPAIR g_RenderEndpoints[] =
|
||||
{
|
||||
&SpeakerMiniports,
|
||||
};
|
||||
|
||||
#define g_cRenderEndpoints (SIZEOF_ARRAY(g_RenderEndpoints))
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Capture miniport pairs. NOTE: the split of render and capture is arbitrary and
|
||||
// unnessary, this array could contain render endpoints.
|
||||
//
|
||||
static
|
||||
PENDPOINT_MINIPAIR g_CaptureEndpoints[] =
|
||||
{
|
||||
&MicArray1Miniports,
|
||||
};
|
||||
|
||||
#define g_cCaptureEndpoints (SIZEOF_ARRAY(g_CaptureEndpoints))
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Total miniports = # endpoints * 2 (topology + wave).
|
||||
//
|
||||
#define g_MaxMiniports ((g_cRenderEndpoints + g_cCaptureEndpoints) * 2)
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_MINIPAIRS_H_
|
||||
@@ -0,0 +1,118 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
speakertopo.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of topology miniport for the speaker (internal).
|
||||
--*/
|
||||
|
||||
#pragma warning (disable : 4127)
|
||||
|
||||
#include "definitions.h"
|
||||
#include "endpoints.h"
|
||||
#include "mintopo.h"
|
||||
#include "speakertopo.h"
|
||||
#include "speakertoptable.h"
|
||||
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
PropertyHandler_SpeakerTopoFilter
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Redirects property request to miniport object
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandler_SpeakerTopoFilter]"));
|
||||
|
||||
// PropertryRequest structure is filled by portcls.
|
||||
// MajorTarget is a pointer to miniport object for miniports.
|
||||
//
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
|
||||
|
||||
if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
|
||||
{
|
||||
if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerJackDescription(
|
||||
PropertyRequest,
|
||||
ARRAYSIZE(SpeakerJackDescriptions),
|
||||
SpeakerJackDescriptions
|
||||
);
|
||||
}
|
||||
else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
|
||||
{
|
||||
ntStatus = pMiniport->PropertyHandlerJackDescription2(
|
||||
PropertyRequest,
|
||||
ARRAYSIZE(SpeakerJackDescriptions),
|
||||
SpeakerJackDescriptions,
|
||||
0 // jack capabilities
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // PropertyHandler_SpeakerTopoFilter
|
||||
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
PropertyHandler_SpeakerTopology
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Redirects property request to miniport object
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandler_SpeakerTopology]"));
|
||||
|
||||
// PropertryRequest structure is filled by portcls.
|
||||
// MajorTarget is a pointer to miniport object for miniports.
|
||||
//
|
||||
PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
|
||||
|
||||
return pMiniport->PropertyHandlerGeneric(PropertyRequest);
|
||||
} // PropertyHandler_SpeakerTopology
|
||||
|
||||
#pragma code_seg()
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
speakertopo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of topology miniport for the speaker (internal).
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_SPEAKERTOPO_H_
|
||||
#define _VIRTUALAUDIODRIVER_SPEAKERTOPO_H_
|
||||
|
||||
NTSTATUS PropertyHandler_SpeakerTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
|
||||
|
||||
NTSTATUS PropertyHandler_SpeakerTopology(_In_ PPCPROPERTY_REQUEST PropertyRequest);
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_SPEAKERTOPO_H_
|
||||
@@ -0,0 +1,206 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
speakertoptable.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of topology tables.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_SPEAKERTOPTABLE_H_
|
||||
#define _VIRTUALAUDIODRIVER_SPEAKERTOPTABLE_H_
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
KSDATARANGE SpeakerTopoPinDataRangesBridge[] =
|
||||
{
|
||||
{
|
||||
sizeof(KSDATARANGE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
|
||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PKSDATARANGE SpeakerTopoPinDataRangePointersBridge[] =
|
||||
{
|
||||
&SpeakerTopoPinDataRangesBridge[0]
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPIN_DESCRIPTOR SpeakerTopoMiniportPins[] =
|
||||
{
|
||||
// KSPIN_TOPO_WAVEOUT_SOURCE
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0, // InstanceCount
|
||||
NULL, // AutomationTable
|
||||
{ // KsPinDescriptor
|
||||
0, // InterfacesCount
|
||||
NULL, // Interfaces
|
||||
0, // MediumsCount
|
||||
NULL, // Mediums
|
||||
SIZEOF_ARRAY(SpeakerTopoPinDataRangePointersBridge),// DataRangesCount
|
||||
SpeakerTopoPinDataRangePointersBridge, // DataRanges
|
||||
KSPIN_DATAFLOW_IN, // DataFlow
|
||||
KSPIN_COMMUNICATION_NONE, // Communication
|
||||
&KSCATEGORY_AUDIO, // Category
|
||||
NULL, // Name
|
||||
0 // Reserved
|
||||
}
|
||||
},
|
||||
// KSPIN_TOPO_LINEOUT_DEST
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0, // InstanceCount
|
||||
NULL, // AutomationTable
|
||||
{ // KsPinDescriptor
|
||||
0, // InterfacesCount
|
||||
NULL, // Interfaces
|
||||
0, // MediumsCount
|
||||
NULL, // Mediums
|
||||
SIZEOF_ARRAY(SpeakerTopoPinDataRangePointersBridge),// DataRangesCount
|
||||
SpeakerTopoPinDataRangePointersBridge, // DataRanges
|
||||
KSPIN_DATAFLOW_OUT, // DataFlow
|
||||
KSPIN_COMMUNICATION_NONE, // Communication
|
||||
&KSNODETYPE_SPEAKER, // Category
|
||||
NULL, // Name
|
||||
0 // Reserved
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
KSJACK_DESCRIPTION SpeakerJackDescBridge =
|
||||
{
|
||||
KSAUDIO_SPEAKER_STEREO,
|
||||
JACKDESC_RGB(0xB3,0xC9,0x8C), // Color spec for green
|
||||
eConnTypeUnknown,
|
||||
eGeoLocFront,
|
||||
eGenLocPrimaryBox,
|
||||
ePortConnIntegratedDevice,
|
||||
TRUE
|
||||
};
|
||||
|
||||
// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
|
||||
static
|
||||
PKSJACK_DESCRIPTION SpeakerJackDescriptions[] =
|
||||
{
|
||||
NULL,
|
||||
&SpeakerJackDescBridge
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPROPERTY_ITEM SpeakerPropertiesVolume[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_VOLUMELEVEL,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_SpeakerTopology
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerVolume, SpeakerPropertiesVolume);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPROPERTY_ITEM SpeakerPropertiesMute[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Audio,
|
||||
KSPROPERTY_AUDIO_MUTE,
|
||||
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_SpeakerTopology
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerMute, SpeakerPropertiesMute);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCNODE_DESCRIPTOR SpeakerTopologyNodes[] =
|
||||
{
|
||||
// KSNODE_TOPO_VOLUME
|
||||
{
|
||||
0, // Flags
|
||||
&AutomationSpeakerVolume, // AutomationTable
|
||||
&KSNODETYPE_VOLUME, // Type
|
||||
&KSAUDFNAME_MASTER_VOLUME // Name
|
||||
},
|
||||
// KSNODE_TOPO_MUTE
|
||||
{
|
||||
0, // Flags
|
||||
&AutomationSpeakerMute, // AutomationTable
|
||||
&KSNODETYPE_MUTE, // Type
|
||||
&KSAUDFNAME_MASTER_MUTE // Name
|
||||
}
|
||||
};
|
||||
|
||||
C_ASSERT(KSNODE_TOPO_VOLUME == 0);
|
||||
C_ASSERT(KSNODE_TOPO_MUTE == 1);
|
||||
|
||||
static
|
||||
PCCONNECTION_DESCRIPTOR SpeakerTopoMiniportConnections[] =
|
||||
{
|
||||
// FromNode, FromPin, ToNode, ToPin
|
||||
{ PCFILTER_NODE, KSPIN_TOPO_WAVEOUT_SOURCE, KSNODE_TOPO_VOLUME, 1 },
|
||||
{ KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 },
|
||||
{ KSNODE_TOPO_MUTE, 0, PCFILTER_NODE, KSPIN_TOPO_LINEOUT_DEST }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCPROPERTY_ITEM PropertiesSpeakerTopoFilter[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Jack,
|
||||
KSPROPERTY_JACK_DESCRIPTION,
|
||||
KSPROPERTY_TYPE_GET |
|
||||
KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_SpeakerTopoFilter
|
||||
},
|
||||
{
|
||||
&KSPROPSETID_Jack,
|
||||
KSPROPERTY_JACK_DESCRIPTION2,
|
||||
KSPROPERTY_TYPE_GET |
|
||||
KSPROPERTY_TYPE_BASICSUPPORT,
|
||||
PropertyHandler_SpeakerTopoFilter
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerTopoFilter, PropertiesSpeakerTopoFilter);
|
||||
|
||||
//=============================================================================
|
||||
static
|
||||
PCFILTER_DESCRIPTOR SpeakerTopoMiniportFilterDescriptor =
|
||||
{
|
||||
0, // Version
|
||||
&AutomationSpeakerTopoFilter, // AutomationTable
|
||||
sizeof(PCPIN_DESCRIPTOR), // PinSize
|
||||
SIZEOF_ARRAY(SpeakerTopoMiniportPins), // PinCount
|
||||
SpeakerTopoMiniportPins, // Pins
|
||||
sizeof(PCNODE_DESCRIPTOR), // NodeSize
|
||||
SIZEOF_ARRAY(SpeakerTopologyNodes), // NodeCount
|
||||
SpeakerTopologyNodes, // Nodes
|
||||
SIZEOF_ARRAY(SpeakerTopoMiniportConnections), // ConnectionCount
|
||||
SpeakerTopoMiniportConnections, // Connections
|
||||
0, // CategoryCount
|
||||
NULL // Categories
|
||||
};
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_SPEAKERTOPTABLE_H_
|
||||
File diff suppressed because it is too large.
Load diff
+91
-116
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -19,44 +19,45 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D3C62015-3845-4DA8-8522-5DC45B735063}</ProjectGuid>
|
||||
<ProjectGuid>{4B664BA5-057A-41B8-B365-2C99065C4DFA}</ProjectGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<SampleGuid>{4E49D9DD-F772-41AD-9367-F225BF8261D3}</SampleGuid>
|
||||
<Platform Condition="'$(Platform)' == ''">x64</Platform>
|
||||
<SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</SampleGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<DriverType>WDM</DriverType>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<DriverType>WDM</DriverType>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<DriverType>WDM</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<DriverType>WDM</DriverType>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
@@ -65,134 +66,108 @@
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ItemGroup Label="WrappedTaskItems" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>SampleDisplay</TargetName>
|
||||
<TargetName>Inc</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<TargetName>Inc</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>SampleDisplay</TargetName>
|
||||
<TargetName>Inc</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<TargetName>SampleDisplay</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<TargetName>SampleDisplay</TargetName>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<TargetName>Inc</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\BDD.cxx" />
|
||||
<ClCompile Include="..\BDD_DDI.cxx" />
|
||||
<ClCompile Include="..\BDD_DMM.cxx" />
|
||||
<ClCompile Include="..\BDD_Util.cxx" />
|
||||
<ClCompile Include="..\BltFuncs.cxx" />
|
||||
<ClCompile Include="..\BltHw.cxx" />
|
||||
<ClCompile Include="..\memory.cxx" />
|
||||
<ResourceCompile Include="..\sampledisplay.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Exclude="@(Inf)" Include="*.inf" />
|
||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
|
||||
<UniqueIdentifier>{54BE0AAC-642F-4D50-80D1-CA3C4BB4BB4C}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{6A00B9EC-DB03-4D51-B351-60DE9C0C51A1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
|
||||
<UniqueIdentifier>{887357BD-50C0-40E6-85E8-87E0F45862DB}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="*.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,104 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
NewDelete.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of placement new and delete operators.
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#ifdef _NEW_DELETE_OPERATORS_
|
||||
|
||||
/*****************************************************************************
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* ::new()
|
||||
*****************************************************************************
|
||||
* New function for creating objects with a specified allocation tag and
|
||||
* pool type
|
||||
*/
|
||||
PVOID operator new
|
||||
(
|
||||
size_t iSize,
|
||||
POOL_FLAGS poolFlags,
|
||||
ULONG tag
|
||||
);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::new()
|
||||
*****************************************************************************
|
||||
* New function for creating objects with a specified pool type.
|
||||
*/
|
||||
PVOID operator new
|
||||
(
|
||||
size_t iSize,
|
||||
POOL_FLAGS poolFlags
|
||||
);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Delete with tag function.
|
||||
*/
|
||||
void __cdecl operator delete
|
||||
(
|
||||
PVOID pVoid,
|
||||
ULONG tag
|
||||
);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Sized Delete function.
|
||||
*/
|
||||
void __cdecl operator delete
|
||||
(
|
||||
_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
|
||||
_In_ size_t cbSize
|
||||
);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Basic Delete function.
|
||||
*/
|
||||
void __cdecl operator delete
|
||||
(
|
||||
PVOID pVoid
|
||||
);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Sized Array Delete function.
|
||||
*/
|
||||
void __cdecl operator delete[]
|
||||
(
|
||||
_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
|
||||
_In_ size_t cbSize
|
||||
);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Array Delete function.
|
||||
*/
|
||||
void __cdecl operator delete[]
|
||||
(
|
||||
_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid
|
||||
);
|
||||
|
||||
#endif//_NEW_DELETE_OPERATORS_
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
basetopo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of topology miniport.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_BASETOPO_H_
|
||||
#define _VIRTUALAUDIODRIVER_BASETOPO_H_
|
||||
|
||||
//=============================================================================
|
||||
// Classes
|
||||
//=============================================================================
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CMiniportTopologyVirtualAudioDriver
|
||||
//
|
||||
|
||||
class CMiniportTopologyVirtualAudioDriver
|
||||
{
|
||||
protected:
|
||||
PADAPTERCOMMON m_AdapterCommon; // Adapter common object.
|
||||
PPCFILTER_DESCRIPTOR m_FilterDescriptor; // Filter descriptor.
|
||||
PPORTEVENTS m_PortEvents; // Event interface.
|
||||
USHORT m_DeviceMaxChannels; // Max device channels.
|
||||
|
||||
public:
|
||||
CMiniportTopologyVirtualAudioDriver(
|
||||
_In_ PCFILTER_DESCRIPTOR *FilterDesc,
|
||||
_In_ USHORT DeviceMaxChannels
|
||||
);
|
||||
|
||||
~CMiniportTopologyVirtualAudioDriver();
|
||||
|
||||
NTSTATUS GetDescription
|
||||
(
|
||||
_Out_ PPCFILTER_DESCRIPTOR * Description
|
||||
);
|
||||
|
||||
NTSTATUS DataRangeIntersection
|
||||
(
|
||||
_In_ ULONG PinId,
|
||||
_In_ PKSDATARANGE ClientDataRange,
|
||||
_In_ PKSDATARANGE MyDataRange,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
|
||||
PVOID ResultantFormat OPTIONAL,
|
||||
_Out_ PULONG ResultantFormatLength
|
||||
);
|
||||
|
||||
NTSTATUS Init
|
||||
(
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_ PPORTTOPOLOGY Port_
|
||||
);
|
||||
|
||||
// PropertyHandlers.
|
||||
NTSTATUS PropertyHandlerGeneric
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandlerMuxSource
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandlerDevSpecific
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
VOID AddEventToEventList
|
||||
(
|
||||
_In_ PKSEVENT_ENTRY EventEntry
|
||||
);
|
||||
|
||||
VOID GenerateEventList
|
||||
(
|
||||
_In_opt_ GUID *Set,
|
||||
_In_ ULONG EventId,
|
||||
_In_ BOOL PinEvent,
|
||||
_In_ ULONG PinId,
|
||||
_In_ BOOL NodeEvent,
|
||||
_In_ ULONG NodeId
|
||||
);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,477 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Common.h
|
||||
|
||||
Abstract:
|
||||
|
||||
CAdapterCommon class declaration.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_COMMON_H_
|
||||
#define _VIRTUALAUDIODRIVER_COMMON_H_
|
||||
|
||||
#define HNSTIME_PER_MILLISECOND 10000
|
||||
|
||||
//=============================================================================
|
||||
// Macros
|
||||
//=============================================================================
|
||||
|
||||
#define UNREFERENCED_VAR(status) \
|
||||
status = status
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Description:
|
||||
//
|
||||
// jump to the given label.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// label - [in] label to jump if condition is met
|
||||
//
|
||||
#define JUMP(label) \
|
||||
goto label;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Description:
|
||||
//
|
||||
// If the condition evaluates to TRUE, jump to the given label.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// condition - [in] Code that fits in if statement
|
||||
// label - [in] label to jump if condition is met
|
||||
//
|
||||
#define IF_TRUE_JUMP(condition, label) \
|
||||
if (condition) \
|
||||
{ \
|
||||
goto label; \
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Description:
|
||||
//
|
||||
// If the condition evaluates to TRUE, perform the given statement
|
||||
// then jump to the given label.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// condition - [in] Code that fits in if statement
|
||||
// action - [in] action to perform in body of if statement
|
||||
// label - [in] label to jump if condition is met
|
||||
//
|
||||
#define IF_TRUE_ACTION_JUMP(condition, action, label) \
|
||||
if (condition) \
|
||||
{ \
|
||||
action; \
|
||||
goto label; \
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Description:
|
||||
//
|
||||
// If the ntStatus is not NT_SUCCESS, perform the given statement then jump to
|
||||
// the given label.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// ntStatus - [in] Value to check
|
||||
// action - [in] action to perform in body of if statement
|
||||
// label - [in] label to jump if condition is met
|
||||
//
|
||||
#define IF_FAILED_ACTION_JUMP(ntStatus, action, label) \
|
||||
if (!NT_SUCCESS(ntStatus)) \
|
||||
{ \
|
||||
action; \
|
||||
goto label; \
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Description:
|
||||
//
|
||||
// If the ntStatus passed is not NT_SUCCESS, jump to the given label.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// ntStatus - [in] Value to check
|
||||
// label - [in] label to jump if condition is met
|
||||
//
|
||||
#define IF_FAILED_JUMP(ntStatus, label) \
|
||||
if (!NT_SUCCESS(ntStatus)) \
|
||||
{ \
|
||||
goto label; \
|
||||
}
|
||||
|
||||
#define SAFE_RELEASE(p) {if (p) { (p)->Release(); (p) = nullptr; } }
|
||||
#define SAFE_DELETE_PTR_WITH_TAG(ptr, tag) if(ptr) { ExFreePoolWithTag((ptr), tag); (ptr) = NULL; }
|
||||
|
||||
// JACKDESC_RGB(r, g, b)
|
||||
#define JACKDESC_RGB(r, g, b) \
|
||||
((COLORREF)((r << 16) | (g << 8) | (b)))
|
||||
|
||||
// Min/Max defines.
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
#define MINWAVERT_POOLTAG 'RWNM'
|
||||
#define MINTOPORT_POOLTAG 'RTNM'
|
||||
#define MINADAPTER_POOLTAG 'uAyS'
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eSpeakerDevice = 0,
|
||||
eMicArrayDevice1,
|
||||
eMaxDeviceType,
|
||||
} eDeviceType;
|
||||
|
||||
//
|
||||
// Signal processing modes and default formats structs.
|
||||
//
|
||||
typedef struct _MODE_AND_DEFAULT_FORMAT {
|
||||
GUID Mode;
|
||||
KSDATAFORMAT* DefaultFormat;
|
||||
} MODE_AND_DEFAULT_FORMAT, *PMODE_AND_DEFAULT_FORMAT;
|
||||
|
||||
//
|
||||
// Enumeration of the various types of pins implemented in this driver.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
NoPin,
|
||||
BridgePin,
|
||||
SystemRenderPin,
|
||||
SystemCapturePin,
|
||||
} PINTYPE;
|
||||
|
||||
//
|
||||
// PIN_DEVICE_FORMATS_AND_MODES
|
||||
//
|
||||
// Used to specify a pin's type (e.g. system, offload, etc.), formats, and
|
||||
// modes. Conceptually serves similar purpose as the PCPIN_DESCRIPTOR to
|
||||
// define a pin, but is more specific to driver implementation.
|
||||
//
|
||||
// Arrays of these structures follow the same order as the filter's
|
||||
// pin descriptor array so that KS pin IDs can serve as an index.
|
||||
//
|
||||
typedef struct _PIN_DEVICE_FORMATS_AND_MODES
|
||||
{
|
||||
PINTYPE PinType;
|
||||
|
||||
KSDATAFORMAT_WAVEFORMATEXTENSIBLE * WaveFormats;
|
||||
ULONG WaveFormatsCount;
|
||||
|
||||
MODE_AND_DEFAULT_FORMAT * ModeAndDefaultFormat;
|
||||
ULONG ModeAndDefaultFormatCount;
|
||||
|
||||
} PIN_DEVICE_FORMATS_AND_MODES, *PPIN_DEVICE_FORMATS_AND_MODES;
|
||||
|
||||
// forward declaration.
|
||||
typedef struct _ENDPOINT_MINIPAIR *PENDPOINT_MINIPAIR;
|
||||
|
||||
// both wave & topology miniport create function prototypes have this form:
|
||||
typedef HRESULT (*PFNCREATEMINIPORT)(
|
||||
_Out_ PUNKNOWN * Unknown,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ POOL_FLAGS PoolFlags,
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_opt_ PVOID DeviceContext,
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//=============================================================================
|
||||
typedef struct _VIRTUALAUDIODRIVER_DEVPROPERTY {
|
||||
const DEVPROPKEY *PropertyKey;
|
||||
DEVPROPTYPE Type;
|
||||
ULONG BufferSize;
|
||||
__field_bcount_opt(BufferSize) PVOID Buffer;
|
||||
} VIRTUALAUDIODRIVER_DEVPROPERTY, PVIRTUALAUDIODRIVER_DEVPROPERTY;
|
||||
|
||||
#define ENDPOINT_NO_FLAGS 0x00000000
|
||||
#define ENDPOINT_CELLULAR_PROVIDER1 0x00000008
|
||||
#define ENDPOINT_CELLULAR_PROVIDER2 0x00000010
|
||||
|
||||
//
|
||||
// Endpoint miniport pair (wave/topology) descriptor.
|
||||
//
|
||||
typedef struct _ENDPOINT_MINIPAIR
|
||||
{
|
||||
eDeviceType DeviceType;
|
||||
|
||||
// Topology miniport.
|
||||
PWSTR TopoName; // make sure this or the template name matches with VIRTUALAUDIODRIVER.<TopoName>.szPname in the inf's [Strings] section
|
||||
PWSTR TemplateTopoName; // optional template name
|
||||
PFNCREATEMINIPORT TopoCreateCallback;
|
||||
PCFILTER_DESCRIPTOR* TopoDescriptor;
|
||||
ULONG TopoInterfacePropertyCount;
|
||||
const VIRTUALAUDIODRIVER_DEVPROPERTY* TopoInterfaceProperties;
|
||||
|
||||
// Wave RT miniport.
|
||||
PWSTR WaveName; // make sure this or the template name matches with VIRTUALAUDIODRIVER.<WaveName>.szPname in the inf's [Strings] section
|
||||
PWSTR TemplateWaveName; // optional template name
|
||||
PFNCREATEMINIPORT WaveCreateCallback;
|
||||
PCFILTER_DESCRIPTOR* WaveDescriptor;
|
||||
ULONG WaveInterfacePropertyCount;
|
||||
const VIRTUALAUDIODRIVER_DEVPROPERTY* WaveInterfaceProperties;
|
||||
|
||||
USHORT DeviceMaxChannels;
|
||||
PIN_DEVICE_FORMATS_AND_MODES* PinDeviceFormatsAndModes;
|
||||
ULONG PinDeviceFormatsAndModesCount;
|
||||
|
||||
// Miniport physical connections.
|
||||
PHYSICALCONNECTIONTABLE* PhysicalConnections;
|
||||
ULONG PhysicalConnectionCount;
|
||||
|
||||
// General endpoint flags (one of more ENDPOINT_<flag-type>, see above)
|
||||
ULONG DeviceFlags;
|
||||
} ENDPOINT_MINIPAIR;
|
||||
|
||||
//=============================================================================
|
||||
// Defines
|
||||
//=============================================================================
|
||||
|
||||
DEFINE_GUID(IID_IAdapterCommon,
|
||||
0x7eda2950, 0xbf9f, 0x11d0, 0x87, 0x1f, 0x0, 0xa0, 0xc9, 0x11, 0xb5, 0x44);
|
||||
|
||||
//=============================================================================
|
||||
// Interfaces
|
||||
//=============================================================================
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IAdapterCommon
|
||||
//
|
||||
DECLARE_INTERFACE_(IAdapterCommon, IUnknown)
|
||||
{
|
||||
STDMETHOD_(NTSTATUS, Init)
|
||||
(
|
||||
THIS_
|
||||
_In_ PDEVICE_OBJECT DeviceObject
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(PDEVICE_OBJECT, GetDeviceObject)
|
||||
(
|
||||
THIS
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(PDEVICE_OBJECT, GetPhysicalDeviceObject)
|
||||
(
|
||||
THIS
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(WDFDEVICE, GetWdfDevice)
|
||||
(
|
||||
THIS
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, SetWaveServiceGroup)
|
||||
(
|
||||
THIS_
|
||||
_In_ PSERVICEGROUP ServiceGroup
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(BOOL, bDevSpecificRead)
|
||||
(
|
||||
THIS_
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, bDevSpecificWrite)
|
||||
(
|
||||
THIS_
|
||||
_In_ BOOL bDevSpecific
|
||||
);
|
||||
|
||||
STDMETHOD_(INT, iDevSpecificRead)
|
||||
(
|
||||
THIS_
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, iDevSpecificWrite)
|
||||
(
|
||||
THIS_
|
||||
_In_ INT iDevSpecific
|
||||
);
|
||||
|
||||
STDMETHOD_(UINT, uiDevSpecificRead)
|
||||
(
|
||||
THIS_
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, uiDevSpecificWrite)
|
||||
(
|
||||
THIS_
|
||||
_In_ UINT uiDevSpecific
|
||||
);
|
||||
|
||||
STDMETHOD_(BOOL, MixerMuteRead)
|
||||
(
|
||||
THIS_
|
||||
_In_ ULONG Index,
|
||||
_In_ ULONG Channel
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, MixerMuteWrite)
|
||||
(
|
||||
THIS_
|
||||
_In_ ULONG Index,
|
||||
_In_ ULONG Channel,
|
||||
_In_ BOOL Value
|
||||
);
|
||||
|
||||
STDMETHOD_(ULONG, MixerMuxRead)
|
||||
(
|
||||
THIS
|
||||
);
|
||||
|
||||
STDMETHOD_(VOID, MixerMuxWrite)
|
||||
(
|
||||
THIS_
|
||||
_In_ ULONG Index
|
||||
);
|
||||
|
||||
STDMETHOD_(LONG, MixerVolumeRead)
|
||||
(
|
||||
THIS_
|
||||
_In_ ULONG Index,
|
||||
_In_ ULONG Channel
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, MixerVolumeWrite)
|
||||
(
|
||||
THIS_
|
||||
_In_ ULONG Index,
|
||||
_In_ ULONG Channel,
|
||||
_In_ LONG Value
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(LONG, MixerPeakMeterRead)
|
||||
(
|
||||
THIS_
|
||||
_In_ ULONG Index,
|
||||
_In_ ULONG Channel
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, MixerReset)
|
||||
(
|
||||
THIS
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, WriteEtwEvent)
|
||||
(
|
||||
THIS_
|
||||
_In_ EPcMiniportEngineEvent miniportEventType,
|
||||
_In_ ULONGLONG ullData1,
|
||||
_In_ ULONGLONG ullData2,
|
||||
_In_ ULONGLONG ullData3,
|
||||
_In_ ULONGLONG ullData4
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(VOID, SetEtwHelper)
|
||||
(
|
||||
THIS_
|
||||
PPORTCLSETWHELPER _pPortClsEtwHelper
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, InstallSubdevice)
|
||||
(
|
||||
_In_opt_ PIRP Irp,
|
||||
_In_ PWSTR Name,
|
||||
_In_opt_ PWSTR TemplateName,
|
||||
_In_ REFGUID PortClassId,
|
||||
_In_ REFGUID MiniportClassId,
|
||||
_In_opt_ PFNCREATEMINIPORT MiniportCreate,
|
||||
_In_ ULONG cPropertyCount,
|
||||
_In_reads_opt_(cPropertyCount) const VIRTUALAUDIODRIVER_DEVPROPERTY * pProperties,
|
||||
_In_opt_ PVOID DeviceContext,
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
||||
_In_opt_ PRESOURCELIST ResourceList,
|
||||
_In_ REFGUID PortInterfaceId,
|
||||
_Out_opt_ PUNKNOWN * OutPortInterface,
|
||||
_Out_opt_ PUNKNOWN * OutPortUnknown,
|
||||
_Out_opt_ PUNKNOWN * OutMiniportUnknown
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, UnregisterSubdevice)
|
||||
(
|
||||
THIS_
|
||||
_In_opt_ PUNKNOWN UnknownPort
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, ConnectTopologies)
|
||||
(
|
||||
THIS_
|
||||
_In_ PUNKNOWN UnknownTopology,
|
||||
_In_ PUNKNOWN UnknownWave,
|
||||
_In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
|
||||
_In_ ULONG PhysicalConnectionCount
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, DisconnectTopologies)
|
||||
(
|
||||
THIS_
|
||||
_In_ PUNKNOWN UnknownTopology,
|
||||
_In_ PUNKNOWN UnknownWave,
|
||||
_In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
|
||||
_In_ ULONG PhysicalConnectionCount
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, InstallEndpointFilters)
|
||||
(
|
||||
THIS_
|
||||
_In_opt_ PIRP Irp,
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
||||
_In_opt_ PVOID DeviceContext,
|
||||
_Out_opt_ PUNKNOWN * UnknownTopology,
|
||||
_Out_opt_ PUNKNOWN * UnknownWave,
|
||||
_Out_opt_ PUNKNOWN * UnknownMiniportTopology,
|
||||
_Out_opt_ PUNKNOWN * UnknownMiniportWave
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, RemoveEndpointFilters)
|
||||
(
|
||||
THIS_
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
||||
_In_opt_ PUNKNOWN UnknownTopology,
|
||||
_In_opt_ PUNKNOWN UnknownWave
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, GetFilters)
|
||||
(
|
||||
THIS_
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
||||
_Out_opt_ PUNKNOWN *UnknownTopologyPort,
|
||||
_Out_opt_ PUNKNOWN *UnknownTopologyMiniport,
|
||||
_Out_opt_ PUNKNOWN *UnknownWavePort,
|
||||
_Out_opt_ PUNKNOWN *UnknownWaveMiniport
|
||||
);
|
||||
|
||||
STDMETHOD_(NTSTATUS, SetIdlePowerManagement)
|
||||
(
|
||||
THIS_
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
||||
_In_ BOOL bEnable
|
||||
);
|
||||
|
||||
STDMETHOD_(VOID, Cleanup)();
|
||||
|
||||
};
|
||||
|
||||
typedef IAdapterCommon *PADAPTERCOMMON;
|
||||
|
||||
//=============================================================================
|
||||
// Function Prototypes
|
||||
//=============================================================================
|
||||
NTSTATUS
|
||||
NewAdapterCommon
|
||||
(
|
||||
_Out_ PUNKNOWN * Unknown,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ POOL_FLAGS PoolFlags
|
||||
);
|
||||
|
||||
#endif //_VIRTUALAUDIODRIVER_COMMON_H_
|
||||
@@ -0,0 +1,198 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
Definitions.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Header file for common stuff.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_DEFINITIONS_H_
|
||||
#define _VIRTUALAUDIODRIVER_DEFINITIONS_H_
|
||||
|
||||
#include <portcls.h>
|
||||
#include <stdunk.h>
|
||||
#include <ksdebug.h>
|
||||
#include <ntintsafe.h>
|
||||
#include <wdf.h>
|
||||
#include <wdfminiport.h>
|
||||
#include <Ntstrsafe.h>
|
||||
#include "NewDelete.h"
|
||||
|
||||
//=============================================================================
|
||||
// Defines
|
||||
//=============================================================================
|
||||
|
||||
// Product Id
|
||||
// {836BA6D1-3FF7-4411-8BCD-469553452DCE}
|
||||
#define STATIC_PID_VIRTUALAUDIODRIVER\
|
||||
0x836ba6d1, 0x3ff7, 0x4411, 0x8b, 0xcd, 0x46, 0x95, 0x53, 0x45, 0x2d, 0xce
|
||||
DEFINE_GUIDSTRUCT("836BA6D1-3FF7-4411-8BCD-469553452DCE", PID_VIRTUALAUDIODRIVER);
|
||||
#define PID_VIRTUALAUDIODRIVER DEFINE_GUIDNAMED(PID_VIRTUALAUDIODRIVER)
|
||||
|
||||
// Pool tag used for VIRTUALAUDIODRIVER allocations
|
||||
#define VIRTUALAUDIODRIVER_POOLTAG 'SASM'
|
||||
|
||||
// Debug module name
|
||||
#define STR_MODULENAME "VIRTUALAUDIODRIVER: "
|
||||
|
||||
// Debug utility macros
|
||||
#define D_FUNC 4
|
||||
#define D_BLAB DEBUGLVL_BLAB
|
||||
#define D_VERBOSE DEBUGLVL_VERBOSE
|
||||
#define D_TERSE DEBUGLVL_TERSE
|
||||
#define D_ERROR DEBUGLVL_ERROR
|
||||
#define DPF _DbgPrintF
|
||||
#define DPF_ENTER(x) DPF(D_FUNC, x)
|
||||
|
||||
// Channel orientation
|
||||
#define CHAN_LEFT 0
|
||||
#define CHAN_RIGHT 1
|
||||
#define CHAN_MASTER (-1)
|
||||
|
||||
// Dma Settings.
|
||||
#define DMA_BUFFER_SIZE 0x16000
|
||||
|
||||
#define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \
|
||||
KSPROPERTY_TYPE_GET | \
|
||||
KSPROPERTY_TYPE_SET
|
||||
|
||||
// Specific node numbers
|
||||
#define DEV_SPECIFIC_VT_BOOL 9
|
||||
#define DEV_SPECIFIC_VT_I4 10
|
||||
#define DEV_SPECIFIC_VT_UI4 11
|
||||
|
||||
#define _100NS_PER_MILLISECOND 10000 // number of 100ns units per millisecond
|
||||
|
||||
// Default volume settings.
|
||||
#define VOLUME_STEPPING_DELTA 0x8000
|
||||
#define VOLUME_SIGNED_MAXIMUM 0x00000000
|
||||
#define VOLUME_SIGNED_MINIMUM (-96 * 0x10000)
|
||||
|
||||
// Default peak meter settings
|
||||
#define PEAKMETER_STEPPING_DELTA 0x1000
|
||||
#define PEAKMETER_SIGNED_MAXIMUM LONG_MAX
|
||||
#define PEAKMETER_SIGNED_MINIMUM LONG_MIN
|
||||
|
||||
#define VALUE_NORMALIZE_P(v, step) \
|
||||
((((v) + (step)/2) / (step)) * (step))
|
||||
|
||||
#define VALUE_NORMALIZE(v, step) \
|
||||
((v) > 0 ? VALUE_NORMALIZE_P((v), (step)) : -(VALUE_NORMALIZE_P(-(v), (step))))
|
||||
|
||||
#define VALUE_NORMALIZE_IN_RANGE_EX(v, min, max, step) \
|
||||
((v) > (max) ? (max) : \
|
||||
(v) < (min) ? (min) : \
|
||||
VALUE_NORMALIZE((v), (step)))
|
||||
|
||||
// to normalize volume values.
|
||||
#define VOLUME_NORMALIZE_IN_RANGE(v) \
|
||||
VALUE_NORMALIZE_IN_RANGE_EX((v), VOLUME_SIGNED_MINIMUM, VOLUME_SIGNED_MAXIMUM, VOLUME_STEPPING_DELTA)
|
||||
|
||||
// to normalize sample peak meter.
|
||||
#define PEAKMETER_NORMALIZE_IN_RANGE(v) \
|
||||
VALUE_NORMALIZE_IN_RANGE_EX((v), PEAKMETER_SIGNED_MINIMUM, PEAKMETER_SIGNED_MAXIMUM, PEAKMETER_STEPPING_DELTA)
|
||||
|
||||
#define ALL_CHANNELS_ID UINT32_MAX
|
||||
|
||||
// Macros to assist with pin instance counting
|
||||
#define VERIFY_PIN_INSTANCE_RESOURCES_AVAILABLE(status, allocated, max) \
|
||||
status = (allocated < max) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES
|
||||
|
||||
#define ALLOCATE_PIN_INSTANCE_RESOURCES(allocated) \
|
||||
allocated++
|
||||
|
||||
#define FREE_PIN_INSTANCE_RESOURCES(allocated) \
|
||||
allocated--
|
||||
|
||||
// Define the value data type for supported sound detector patterns. Only
|
||||
// one pattern type is supported in this sample.
|
||||
typedef struct {
|
||||
KSMULTIPLE_ITEM MultipleItem;
|
||||
GUID PatternType[1];
|
||||
} CONTOSO_SUPPORTEDPATTERNSVALUE;
|
||||
|
||||
//=============================================================================
|
||||
// Typedefs
|
||||
//=============================================================================
|
||||
|
||||
// Flags to identify stream processing mode
|
||||
typedef enum {
|
||||
CONNECTIONTYPE_TOPOLOGY_OUTPUT = 0,
|
||||
CONNECTIONTYPE_WAVE_OUTPUT = 1
|
||||
} CONNECTIONTYPE;
|
||||
|
||||
// Connection table for registering topology/wave bridge connection
|
||||
typedef struct _PHYSICALCONNECTIONTABLE
|
||||
{
|
||||
ULONG ulTopology;
|
||||
ULONG ulWave;
|
||||
CONNECTIONTYPE eType;
|
||||
} PHYSICALCONNECTIONTABLE, *PPHYSICALCONNECTIONTABLE;
|
||||
|
||||
//
|
||||
// This is the structure of the portclass FDO device extension Nt has created
|
||||
// for us. We keep the adapter common object here.
|
||||
//
|
||||
struct IAdapterCommon;
|
||||
typedef struct _PortClassDeviceContext // 32 64 Byte offsets for 32 and 64 bit architectures
|
||||
{
|
||||
ULONG_PTR m_pulReserved1[2]; // 0-7 0-15 First two pointers are reserved.
|
||||
PDEVICE_OBJECT m_DoNotUsePhysicalDeviceObject; // 8-11 16-23 Reserved pointer to our Physical Device Object (PDO).
|
||||
PVOID m_pvReserved2; // 12-15 24-31 Reserved pointer to our Start Device function.
|
||||
PVOID m_pvReserved3; // 16-19 32-39 "Out Memory" according to DDK.
|
||||
IAdapterCommon* m_pCommon; // 20-23 40-47 Pointer to our adapter common object.
|
||||
PVOID m_pvUnused1; // 24-27 48-55 Unused space.
|
||||
PVOID m_pvUnused2; // 28-31 56-63 Unused space.
|
||||
|
||||
// Anything after above line should not be used.
|
||||
// This actually goes on for (64*sizeof(ULONG_PTR)) but it is all opaque.
|
||||
} PortClassDeviceContext;
|
||||
|
||||
//
|
||||
// Major/MinorTarget to object casting.
|
||||
//
|
||||
#define MajorTarget_to_Obj(ptr) \
|
||||
reinterpret_cast<CMiniportWaveRT*>(ptr)
|
||||
|
||||
#define MinorTarget_to_Obj(ptr) \
|
||||
static_cast<CMiniportWaveRTStream*>(reinterpret_cast<PMINIPORTWAVERTSTREAM>(ptr))
|
||||
|
||||
//
|
||||
// Global settings.
|
||||
//
|
||||
extern DWORD g_DoNotCreateDataFiles;
|
||||
extern DWORD g_DisableBthScoBypass;
|
||||
extern UNICODE_STRING g_RegistryPath;
|
||||
|
||||
//=============================================================================
|
||||
// Function prototypes
|
||||
//=============================================================================
|
||||
|
||||
// Generic topology handler
|
||||
NTSTATUS PropertyHandler_Topology
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
// Default WaveFilter automation table.
|
||||
// Handles the GeneralComponentId request.
|
||||
NTSTATUS PropertyHandler_WaveFilter
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandler_GenericPin
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
// common.h uses some of the above definitions.
|
||||
#include "common.h"
|
||||
#include "kshelper.h"
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_DEFINITIONS_H_
|
||||
@@ -0,0 +1,133 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
endpoints.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Node and Pin numbers and other common definitions for simple audio sample.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_ENDPOINTS_H_
|
||||
#define _VIRTUALAUDIODRIVER_ENDPOINTS_H_
|
||||
|
||||
// Name Guid
|
||||
// {0104947F-82AE-4291-A6F3-5E2DE1AD7DC2}
|
||||
#define STATIC_NAME_SIMPLE_AUDIO_SAMPLE\
|
||||
0x104947f, 0x82ae, 0x4291, 0xa6, 0xf3, 0x5e, 0x2d, 0xe1, 0xad, 0x7d, 0xc2
|
||||
DEFINE_GUIDSTRUCT("0104947F-82AE-4291-A6F3-5E2DE1AD7DC2", NAME_SIMPLE_AUDIO_SAMPLE);
|
||||
#define NAME_SIMPLE_AUDIO_SAMPLE DEFINE_GUIDNAMED(NAME_SIMPLE_AUDIO_SAMPLE)
|
||||
|
||||
//----------------------------------------------------
|
||||
// New defines for the render endpoints.
|
||||
//----------------------------------------------------
|
||||
|
||||
// Default pin instances.
|
||||
#define MAX_INPUT_SYSTEM_STREAMS 1
|
||||
|
||||
// Wave pins - no mix, no offload
|
||||
enum
|
||||
{
|
||||
KSPIN_WAVE_RENDER3_SINK_SYSTEM = 0,
|
||||
KSPIN_WAVE_RENDER3_SOURCE
|
||||
};
|
||||
|
||||
// Wave pins - offloading is NOT supported.
|
||||
enum
|
||||
{
|
||||
KSPIN_WAVE_RENDER2_SINK_SYSTEM = 0,
|
||||
KSPIN_WAVE_RENDER2_SINK_LOOPBACK,
|
||||
KSPIN_WAVE_RENDER2_SOURCE
|
||||
};
|
||||
|
||||
// Wave Topology nodes - offloading is NOT supported.
|
||||
enum
|
||||
{
|
||||
KSNODE_WAVE_SUM = 0,
|
||||
KSNODE_WAVE_VOLUME,
|
||||
KSNODE_WAVE_MUTE,
|
||||
KSNODE_WAVE_PEAKMETER
|
||||
};
|
||||
|
||||
// Topology pins.
|
||||
enum
|
||||
{
|
||||
KSPIN_TOPO_WAVEOUT_SOURCE = 0,
|
||||
KSPIN_TOPO_LINEOUT_DEST,
|
||||
};
|
||||
|
||||
// Topology nodes.
|
||||
enum
|
||||
{
|
||||
KSNODE_TOPO_WAVEOUT_VOLUME = 0,
|
||||
KSNODE_TOPO_WAVEOUT_MUTE,
|
||||
KSNODE_TOPO_WAVEOUT_PEAKMETER
|
||||
};
|
||||
|
||||
//----------------------------------------------------
|
||||
// New defines for the capture endpoints.
|
||||
//----------------------------------------------------
|
||||
|
||||
// Default pin instances.
|
||||
#define MAX_INPUT_STREAMS 1 // Number of capture streams.
|
||||
|
||||
// Wave pins
|
||||
enum
|
||||
{
|
||||
KSPIN_WAVE_BRIDGE = 0,
|
||||
KSPIN_WAVEIN_HOST,
|
||||
};
|
||||
|
||||
// Wave Topology nodes.
|
||||
enum
|
||||
{
|
||||
KSNODE_WAVE_ADC = 0
|
||||
};
|
||||
|
||||
// Wave Topology nodes.
|
||||
enum
|
||||
{
|
||||
KSNODE_WAVE_DAC = 0
|
||||
};
|
||||
|
||||
// topology pins.
|
||||
enum
|
||||
{
|
||||
KSPIN_TOPO_MIC_ELEMENTS,
|
||||
KSPIN_TOPO_BRIDGE
|
||||
};
|
||||
|
||||
// topology nodes.
|
||||
enum
|
||||
{
|
||||
KSNODE_TOPO_VOLUME,
|
||||
KSNODE_TOPO_MUTE,
|
||||
KSNODE_TOPO_PEAKMETER
|
||||
};
|
||||
|
||||
// data format attribute range definitions.
|
||||
static
|
||||
KSATTRIBUTE PinDataRangeSignalProcessingModeAttribute =
|
||||
{
|
||||
sizeof(KSATTRIBUTE),
|
||||
0,
|
||||
STATICGUIDOF(KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE),
|
||||
};
|
||||
|
||||
static
|
||||
PKSATTRIBUTE PinDataRangeAttributes[] =
|
||||
{
|
||||
&PinDataRangeSignalProcessingModeAttribute,
|
||||
};
|
||||
|
||||
static
|
||||
KSATTRIBUTE_LIST PinDataRangeAttributeList =
|
||||
{
|
||||
ARRAYSIZE(PinDataRangeAttributes),
|
||||
PinDataRangeAttributes,
|
||||
};
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_ENDPOINTS_H_
|
||||
@@ -0,0 +1,159 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
kshelper.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Helper functions for simple audio sample
|
||||
--*/
|
||||
#ifndef _VIRTUALAUDIODRIVER_KSHELPER_H_
|
||||
#define _VIRTUALAUDIODRIVER_KSHELPER_H_
|
||||
|
||||
#include <portcls.h>
|
||||
#include <ksdebug.h>
|
||||
|
||||
PWAVEFORMATEX
|
||||
GetWaveFormatEx
|
||||
(
|
||||
_In_ PKSDATAFORMAT pDataFormat
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
ValidatePropertyParams
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG cbValueSize,
|
||||
_In_ ULONG cbInstanceSize = 0
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_BasicSupport
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG Flags,
|
||||
_In_ DWORD PropTypeSetId
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_BasicSupportVolume
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG MaxChannels
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_BasicSupportMute
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG MaxChannels
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_BasicSupportPeakMeter2
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG MaxChannels
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_CpuResources
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_Volume
|
||||
(
|
||||
_In_ PADAPTERCOMMON AdapterCommon,
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG MaxChannels
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_Mute
|
||||
(
|
||||
_In_ PADAPTERCOMMON AdapterCommon,
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG MaxChannels
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
PropertyHandler_PeakMeter2
|
||||
(
|
||||
_In_ PADAPTERCOMMON AdapterCommon,
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG MaxChannels
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
// Property helpers
|
||||
//=============================================================================
|
||||
|
||||
NTSTATUS
|
||||
VirtualAudioDriverPropertyDispatch
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
);
|
||||
|
||||
// Use this structure to define property items with extra data allowing easier
|
||||
// definition of separate get, set, and support handlers dispatched through
|
||||
// VirtualAudioDriverPropertyDispatch.
|
||||
typedef struct
|
||||
{
|
||||
PCPROPERTY_ITEM PropertyItem; // Standard PCPROPERTY_ITEM
|
||||
ULONG MinProperty; // Minimum size of the property instance data
|
||||
ULONG MinData; // Minimum size of the property value
|
||||
PCPFNPROPERTY_HANDLER GetHandler; // Property get handler (NULL if GET not supported)
|
||||
PCPFNPROPERTY_HANDLER SetHandler; // Property set handler (NULL if SET not supported)
|
||||
PCPFNPROPERTY_HANDLER SupportHandler; // Property support handler (NULL for common handler)
|
||||
VOID *ContextData; // Optional context information for the handler, NULL for unused
|
||||
ULONG ContextDataSize; // Size of the data held at ContextData, 0 for unused
|
||||
} VIRTUALAUDIODRIVER_PROPERTY_ITEM;
|
||||
|
||||
// The following macros facilitate adding property handlers to a class, allowing
|
||||
// easier declaration and definition of a "thunk" routine that directly handles
|
||||
// the property request and calls into a class instance method. Note that as
|
||||
// written, the thunk routine assumes PAGED_CODE.
|
||||
#define DECLARE_CLASSPROPERTYHANDLER(theClass, theMethod) \
|
||||
NTSTATUS theClass##_##theMethod \
|
||||
( \
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest \
|
||||
);
|
||||
|
||||
#define DECLARE_PROPERTYHANDLER(theMethod) \
|
||||
NTSTATUS theMethod \
|
||||
( \
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest \
|
||||
);
|
||||
|
||||
#define DEFINE_CLASSPROPERTYHANDLER(theClass, theMethod) \
|
||||
NTSTATUS theClass##_##theMethod \
|
||||
( \
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest \
|
||||
) \
|
||||
{ \
|
||||
NTSTATUS status; \
|
||||
\
|
||||
PAGED_CODE(); \
|
||||
\
|
||||
theClass* p = reinterpret_cast<theClass*>(PropertyRequest->MajorTarget); \
|
||||
\
|
||||
p->AddRef(); \
|
||||
status = p->theMethod(PropertyRequest); \
|
||||
p->Release(); \
|
||||
\
|
||||
return status; \
|
||||
} \
|
||||
NTSTATUS theClass::theMethod \
|
||||
( \
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest \
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_KSHELPER_H_
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
minitopo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Declaration of topology miniport.
|
||||
--*/
|
||||
|
||||
#ifndef _VIRTUALAUDIODRIVER_MINTOPO_H_
|
||||
#define _VIRTUALAUDIODRIVER_MINTOPO_H_
|
||||
|
||||
#include "basetopo.h"
|
||||
|
||||
//=============================================================================
|
||||
// Classes
|
||||
//=============================================================================
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CMiniportTopology
|
||||
//
|
||||
|
||||
class CMiniportTopology :
|
||||
public CMiniportTopologyVirtualAudioDriver,
|
||||
public IMiniportTopology,
|
||||
public CUnknown
|
||||
{
|
||||
private:
|
||||
eDeviceType m_DeviceType;
|
||||
|
||||
union {
|
||||
PVOID m_DeviceContext;
|
||||
};
|
||||
|
||||
public:
|
||||
DECLARE_STD_UNKNOWN();
|
||||
CMiniportTopology
|
||||
(
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ PCFILTER_DESCRIPTOR *FilterDesc,
|
||||
_In_ USHORT DeviceMaxChannels,
|
||||
_In_ eDeviceType DeviceType,
|
||||
_In_opt_ PVOID DeviceContext
|
||||
)
|
||||
: CUnknown(UnknownOuter),
|
||||
CMiniportTopologyVirtualAudioDriver(FilterDesc, DeviceMaxChannels),
|
||||
m_DeviceType(DeviceType),
|
||||
m_DeviceContext(DeviceContext)
|
||||
{
|
||||
}
|
||||
|
||||
~CMiniportTopology();
|
||||
|
||||
IMP_IMiniportTopology;
|
||||
|
||||
NTSTATUS PropertyHandlerJackDescription
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG cJackDescriptions,
|
||||
_In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions
|
||||
);
|
||||
|
||||
NTSTATUS PropertyHandlerJackDescription2
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG cJackDescriptions,
|
||||
_In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions,
|
||||
_In_ DWORD JackCapabilities
|
||||
);
|
||||
|
||||
PVOID GetDeviceContext() { return m_DeviceContext; }
|
||||
};
|
||||
|
||||
typedef CMiniportTopology *PCMiniportTopology;
|
||||
|
||||
#endif // _VIRTUALAUDIODRIVER_MINTOPO_H_
|
||||
@@ -0,0 +1,336 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</ProjectGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<SupportsPackaging>false</SupportsPackaging>
|
||||
<RequiresPackageProject>true</RequiresPackageProject>
|
||||
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">x64</Platform>
|
||||
<SampleGuid>{2A9A946E-F017-4E0D-BF75-AD81E7E97D64}</SampleGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Windows Driver</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(IntDir)</OutDir>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ItemGroup Label="WrappedTaskItems" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
|
||||
</Midl>
|
||||
<DriverSign>
|
||||
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
|
||||
</DriverSign>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>VirtualAudioDriver</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<TargetName>VirtualAudioDriver</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>VirtualAudioDriver</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<TargetName>VirtualAudioDriver</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<!--
|
||||
Use one of the following pre-processor defines to select the right power management:
|
||||
- _USE_IPortClsRuntimePower
|
||||
- _USE_SingleComponentMultiFxStates
|
||||
Note that the single-component/multi-state feature requires also a registry
|
||||
value set via the INF. The name of the registry value is SingleComponentMultiFxStates.
|
||||
see INF file for more info.
|
||||
-->
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="adapter.cpp" />
|
||||
<ClCompile Include="basetopo.cpp" />
|
||||
<ClCompile Include="common.cpp" />
|
||||
<ClCompile Include="mintopo.cpp" />
|
||||
<ClCompile Include="minwavert.cpp" />
|
||||
<ClCompile Include="minwavertstream.cpp" />
|
||||
<ClCompile Include="newdelete.cpp" />
|
||||
<ResourceCompile Include="VirtualAudioDriver.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Exclude="@(Inx)" Include="*.inx" />
|
||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
|
||||
<None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
|
||||
<None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
|
||||
<UniqueIdentifier>{7FE326AE-6214-4FE0-A27B-F229A098BDBC}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
<UniqueIdentifier>{64C16D2B-849C-4264-A615-18A8E8AC9505}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
|
||||
<UniqueIdentifier>{46FAF4E8-F18C-4797-9CFA-2F3473BCB316}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
<UniqueIdentifier>{EE8F0A00-C1F0-4CB4-80E3-5FCC378E0BF4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\*.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="*.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="VirtualAudioDriver.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="*.inx">
|
||||
<Filter>Driver Files</Filter>
|
||||
</Inf>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,141 @@
|
||||
/*****************************************************************************
|
||||
* NewDelete.cpp - CPP placement new and delete operators implementation
|
||||
*****************************************************************************
|
||||
* Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
*
|
||||
* Module Name:
|
||||
*
|
||||
* NewDelete.cpp
|
||||
*
|
||||
* Abstract:
|
||||
*
|
||||
* Definition of placement new and delete operators.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _NEW_DELETE_OPERATORS_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include <wdm.h>
|
||||
}
|
||||
#else
|
||||
#include <wdm.h>
|
||||
#endif
|
||||
|
||||
#include "newDelete.h"
|
||||
#include "definitions.h"
|
||||
|
||||
#pragma code_seg()
|
||||
/*****************************************************************************
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* ::new()
|
||||
*****************************************************************************
|
||||
* New function for creating objects with a specified allocation tag.
|
||||
*/
|
||||
PVOID operator new
|
||||
(
|
||||
size_t iSize,
|
||||
POOL_FLAGS poolFlags,
|
||||
ULONG tag
|
||||
)
|
||||
{
|
||||
PVOID result = ExAllocatePool2(poolFlags, iSize, tag);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::new()
|
||||
*****************************************************************************
|
||||
* New function for creating objects with a specified allocation tag.
|
||||
*/
|
||||
PVOID operator new
|
||||
(
|
||||
size_t iSize,
|
||||
POOL_FLAGS poolFlags
|
||||
)
|
||||
{
|
||||
PVOID result = ExAllocatePool2(poolFlags, iSize, VIRTUALAUDIODRIVER_POOLTAG);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Delete with tag function.
|
||||
*/
|
||||
void __cdecl operator delete
|
||||
(
|
||||
PVOID pVoid,
|
||||
ULONG tag
|
||||
)
|
||||
{
|
||||
if (pVoid)
|
||||
{
|
||||
ExFreePoolWithTag(pVoid, tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Sized Delete function.
|
||||
*/
|
||||
void __cdecl operator delete
|
||||
(
|
||||
_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
|
||||
_In_ size_t cbSize
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(cbSize);
|
||||
|
||||
if (pVoid)
|
||||
{
|
||||
ExFreePoolWithTag(pVoid, VIRTUALAUDIODRIVER_POOLTAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Sized Array Delete function.
|
||||
*/
|
||||
void __cdecl operator delete[]
|
||||
(
|
||||
_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
|
||||
_In_ size_t cbSize
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(cbSize);
|
||||
|
||||
if (pVoid)
|
||||
{
|
||||
ExFreePoolWithTag(pVoid, VIRTUALAUDIODRIVER_POOLTAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ::delete()
|
||||
*****************************************************************************
|
||||
* Array Delete function.
|
||||
*/
|
||||
void __cdecl operator delete[]
|
||||
(
|
||||
_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid
|
||||
)
|
||||
{
|
||||
if (pVoid)
|
||||
{
|
||||
ExFreePoolWithTag(pVoid, VIRTUALAUDIODRIVER_POOLTAG);
|
||||
}
|
||||
}
|
||||
#endif//_NEW_DELETE_OPERATORS_
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
VirtualAudioDriver.rc
|
||||
|
||||
Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_SOUND
|
||||
#define VER_FILEDESCRIPTION_STR "Microsoft Virtual Simple Audio Sample Driver"
|
||||
#define VER_INTERNALNAME_STR "VirtualAudioDriver.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "VirtualAudioDriver.sys"
|
||||
|
||||
#define VER_LEGALCOPYRIGHT_YEARS "2013"
|
||||
#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Microsoft Corp." VER_LEGALCOPYRIGHT_YEARS
|
||||
|
||||
#include "common.ver"
|
||||
|
||||
|
||||
@@ -0,0 +1,845 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
adapter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Setup and miniport installation. No resources are used by simple audio sample.
|
||||
This sample is to demonstrate how to develop a full featured audio miniport driver.
|
||||
--*/
|
||||
|
||||
#pragma warning (disable : 4127)
|
||||
|
||||
//
|
||||
// All the GUIDS for all the miniports end up in this object.
|
||||
//
|
||||
#define PUT_GUIDS_HERE
|
||||
|
||||
#include "definitions.h"
|
||||
#include "endpoints.h"
|
||||
#include "minipairs.h"
|
||||
|
||||
typedef void (*fnPcDriverUnload) (PDRIVER_OBJECT);
|
||||
fnPcDriverUnload gPCDriverUnloadRoutine = NULL;
|
||||
extern "C" DRIVER_UNLOAD DriverUnload;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Referenced forward.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DRIVER_ADD_DEVICE AddDevice;
|
||||
|
||||
NTSTATUS
|
||||
StartDevice
|
||||
(
|
||||
_In_ PDEVICE_OBJECT,
|
||||
_In_ PIRP,
|
||||
_In_ PRESOURCELIST
|
||||
);
|
||||
|
||||
_Dispatch_type_(IRP_MJ_PNP)
|
||||
DRIVER_DISPATCH PnpHandler;
|
||||
|
||||
//
|
||||
// Rendering streams are not saved to a file by default. Use the registry value
|
||||
// DoNotCreateDataFiles (DWORD) = 0 to override this default.
|
||||
//
|
||||
DWORD g_DoNotCreateDataFiles = 1; // default is off.
|
||||
DWORD g_DisableToneGenerator = 1; // default is to not generate tones.
|
||||
UNICODE_STRING g_RegistryPath; // This is used to store the registry settings path for the driver
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
void ReleaseRegistryStringBuffer()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (g_RegistryPath.Buffer != NULL)
|
||||
{
|
||||
ExFreePool(g_RegistryPath.Buffer);
|
||||
g_RegistryPath.Buffer = NULL;
|
||||
g_RegistryPath.Length = 0;
|
||||
g_RegistryPath.MaximumLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
extern "C"
|
||||
void DriverUnload
|
||||
(
|
||||
_In_ PDRIVER_OBJECT DriverObject
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Our driver unload routine. This just frees the WDF driver object.
|
||||
|
||||
Arguments:
|
||||
|
||||
DriverObject - pointer to the driver object
|
||||
|
||||
Environment:
|
||||
|
||||
PASSIVE_LEVEL
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF(D_TERSE, ("[DriverUnload]"));
|
||||
|
||||
ReleaseRegistryStringBuffer();
|
||||
|
||||
if (DriverObject == NULL)
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Invoke first the port unload.
|
||||
//
|
||||
if (gPCDriverUnloadRoutine != NULL)
|
||||
{
|
||||
gPCDriverUnloadRoutine(DriverObject);
|
||||
}
|
||||
|
||||
//
|
||||
// Unload WDF driver object.
|
||||
//
|
||||
if (WdfGetDriver() != NULL)
|
||||
{
|
||||
WdfDriverMiniportUnload(WdfGetDriver());
|
||||
}
|
||||
Done:
|
||||
return;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("INIT")
|
||||
__drv_requiresIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
CopyRegistrySettingsPath(
|
||||
_In_ PUNICODE_STRING RegistryPath
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Copies the following registry path to a global variable.
|
||||
|
||||
\REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters
|
||||
|
||||
Arguments:
|
||||
|
||||
RegistryPath - Registry path passed to DriverEntry
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS - SUCCESS if able to configure the framework
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
// Initializing the unicode string, so that if it is not allocated it will not be deallocated too.
|
||||
RtlInitUnicodeString(&g_RegistryPath, NULL);
|
||||
|
||||
g_RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
|
||||
|
||||
g_RegistryPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, g_RegistryPath.MaximumLength, MINADAPTER_POOLTAG);
|
||||
|
||||
if (g_RegistryPath.Buffer == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("INIT")
|
||||
__drv_requiresIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
GetRegistrySettings(
|
||||
_In_ PUNICODE_STRING RegistryPath
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize Driver Framework settings from the driver
|
||||
specific registry settings under
|
||||
|
||||
\REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters
|
||||
|
||||
Arguments:
|
||||
|
||||
RegistryPath - Registry path passed to DriverEntry
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS - SUCCESS if able to configure the framework
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
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"DoNotCreateDataFiles", &g_DoNotCreateDataFiles, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DoNotCreateDataFiles, sizeof(ULONG)},
|
||||
{ NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DisableToneGenerator", &g_DisableToneGenerator, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DisableToneGenerator, sizeof(ULONG)},
|
||||
{ NULL, 0, NULL, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
DPF(D_TERSE, ("[GetRegistrySettings]"));
|
||||
|
||||
PAGED_CODE();
|
||||
UNREFERENCED_PARAMETER(RegistryPath);
|
||||
|
||||
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 (!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.
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// Dump settings.
|
||||
//
|
||||
DPF(D_VERBOSE, ("DoNotCreateDataFiles: %u", g_DoNotCreateDataFiles));
|
||||
DPF(D_VERBOSE, ("DisableToneGenerator: %u", g_DisableToneGenerator));
|
||||
|
||||
if (DriverKey)
|
||||
{
|
||||
ZwClose(DriverKey);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma code_seg("INIT")
|
||||
extern "C" DRIVER_INITIALIZE DriverEntry;
|
||||
extern "C" NTSTATUS
|
||||
DriverEntry
|
||||
(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PUNICODE_STRING RegistryPathName
|
||||
)
|
||||
{
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Installable driver initialization entry point.
|
||||
This entry point is called directly by the I/O system.
|
||||
|
||||
All audio adapter drivers can use this code without change.
|
||||
|
||||
Arguments:
|
||||
|
||||
DriverObject - pointer to the driver object
|
||||
|
||||
RegistryPath - pointer to a unicode string representing the path,
|
||||
to driver-specific key in the registry.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_UNSUCCESSFUL otherwise.
|
||||
|
||||
--*/
|
||||
NTSTATUS ntStatus;
|
||||
WDF_DRIVER_CONFIG config;
|
||||
|
||||
DPF(D_TERSE, ("[DriverEntry]"));
|
||||
|
||||
// Copy registry Path name in a global variable to be used by modules inside driver.
|
||||
// !! NOTE !! Inside this function we are initializing the registrypath, so we MUST NOT add any failing calls
|
||||
// before the following call.
|
||||
ntStatus = CopyRegistrySettingsPath(RegistryPathName);
|
||||
IF_FAILED_ACTION_JUMP(
|
||||
ntStatus,
|
||||
DPF(D_ERROR, ("Registry path copy error 0x%x", ntStatus)),
|
||||
Done);
|
||||
|
||||
WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
|
||||
//
|
||||
// Set WdfDriverInitNoDispatchOverride flag to tell the framework
|
||||
// not to provide dispatch routines for the driver. In other words,
|
||||
// the framework must not intercept IRPs that the I/O manager has
|
||||
// directed to the driver. In this case, they will be handled by Audio
|
||||
// port driver.
|
||||
//
|
||||
config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
|
||||
config.DriverPoolTag = MINADAPTER_POOLTAG;
|
||||
|
||||
ntStatus = WdfDriverCreate(DriverObject,
|
||||
RegistryPathName,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&config,
|
||||
WDF_NO_HANDLE);
|
||||
IF_FAILED_ACTION_JUMP(
|
||||
ntStatus,
|
||||
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.
|
||||
//
|
||||
ntStatus = PcInitializeAdapterDriver(DriverObject,
|
||||
RegistryPathName,
|
||||
(PDRIVER_ADD_DEVICE)AddDevice);
|
||||
IF_FAILED_ACTION_JUMP(
|
||||
ntStatus,
|
||||
DPF(D_ERROR, ("PcInitializeAdapterDriver failed, 0x%x", ntStatus)),
|
||||
Done);
|
||||
|
||||
//
|
||||
// To intercept stop/remove/surprise-remove.
|
||||
//
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = PnpHandler;
|
||||
|
||||
//
|
||||
// Hook the port class unload function
|
||||
//
|
||||
gPCDriverUnloadRoutine = DriverObject->DriverUnload;
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
//
|
||||
// All done.
|
||||
//
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
|
||||
Done:
|
||||
|
||||
if (!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
if (WdfGetDriver() != NULL)
|
||||
{
|
||||
WdfDriverMiniportUnload(WdfGetDriver());
|
||||
}
|
||||
|
||||
ReleaseRegistryStringBuffer();
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // DriverEntry
|
||||
|
||||
#pragma code_seg()
|
||||
// disable prefast warning 28152 because
|
||||
// DO_DEVICE_INITIALIZING is cleared in PcAddAdapterDevice
|
||||
#pragma warning(disable:28152)
|
||||
#pragma code_seg("PAGE")
|
||||
//=============================================================================
|
||||
NTSTATUS AddDevice
|
||||
(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ PDEVICE_OBJECT PhysicalDeviceObject
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The Plug & Play subsystem is handing us a brand new PDO, for which we
|
||||
(by means of INF registration) have been asked to provide a driver.
|
||||
|
||||
We need to determine if we need to be in the driver stack for the device.
|
||||
Create a function device object to attach to the stack
|
||||
Initialize that device object
|
||||
Return status success.
|
||||
|
||||
All audio adapter drivers can use this code without change.
|
||||
|
||||
Arguments:
|
||||
|
||||
DriverObject - pointer to a driver object
|
||||
|
||||
PhysicalDeviceObject - pointer to a device object created by the
|
||||
underlying bus driver.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS ntStatus;
|
||||
ULONG maxObjects;
|
||||
|
||||
DPF(D_TERSE, ("[AddDevice]"));
|
||||
|
||||
maxObjects = g_MaxMiniports;
|
||||
|
||||
// Tell the class driver to add the device.
|
||||
//
|
||||
ntStatus =
|
||||
PcAddAdapterDevice
|
||||
(
|
||||
DriverObject,
|
||||
PhysicalDeviceObject,
|
||||
PCPFNSTARTDEVICE(StartDevice),
|
||||
maxObjects,
|
||||
0
|
||||
);
|
||||
|
||||
return ntStatus;
|
||||
} // AddDevice
|
||||
|
||||
#pragma code_seg()
|
||||
NTSTATUS
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
PowerControlCallback
|
||||
(
|
||||
_In_ LPCGUID PowerControlCode,
|
||||
_In_opt_ PVOID InBuffer,
|
||||
_In_ SIZE_T InBufferSize,
|
||||
_Out_writes_bytes_to_(OutBufferSize, *BytesReturned) PVOID OutBuffer,
|
||||
_In_ SIZE_T OutBufferSize,
|
||||
_Out_opt_ PSIZE_T BytesReturned,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PowerControlCode);
|
||||
UNREFERENCED_PARAMETER(InBuffer);
|
||||
UNREFERENCED_PARAMETER(InBufferSize);
|
||||
UNREFERENCED_PARAMETER(OutBuffer);
|
||||
UNREFERENCED_PARAMETER(OutBufferSize);
|
||||
UNREFERENCED_PARAMETER(BytesReturned);
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
InstallEndpointRenderFilters(
|
||||
_In_ PDEVICE_OBJECT _pDeviceObject,
|
||||
_In_ PIRP _pIrp,
|
||||
_In_ PADAPTERCOMMON _pAdapterCommon,
|
||||
_In_ PENDPOINT_MINIPAIR _pAeMiniports
|
||||
)
|
||||
{
|
||||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||||
PUNKNOWN unknownTopology = NULL;
|
||||
PUNKNOWN unknownWave = NULL;
|
||||
PPORTCLSETWHELPER pPortClsEtwHelper = NULL;
|
||||
#ifdef _USE_IPortClsRuntimePower
|
||||
PPORTCLSRUNTIMEPOWER pPortClsRuntimePower = NULL;
|
||||
#endif // _USE_IPortClsRuntimePower
|
||||
PPORTCLSStreamResourceManager pPortClsResMgr = NULL;
|
||||
PPORTCLSStreamResourceManager2 pPortClsResMgr2 = NULL;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(_pDeviceObject);
|
||||
|
||||
ntStatus = _pAdapterCommon->InstallEndpointFilters(
|
||||
_pIrp,
|
||||
_pAeMiniports,
|
||||
NULL,
|
||||
&unknownTopology,
|
||||
&unknownWave,
|
||||
NULL, NULL);
|
||||
|
||||
if (unknownWave) // IID_IPortClsEtwHelper and IID_IPortClsRuntimePower interfaces are only exposed on the WaveRT port.
|
||||
{
|
||||
ntStatus = unknownWave->QueryInterface (IID_IPortClsEtwHelper, (PVOID *)&pPortClsEtwHelper);
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
_pAdapterCommon->SetEtwHelper(pPortClsEtwHelper);
|
||||
ASSERT(pPortClsEtwHelper != NULL);
|
||||
pPortClsEtwHelper->Release();
|
||||
}
|
||||
|
||||
#ifdef _USE_IPortClsRuntimePower
|
||||
// Let's get the runtime power interface on PortCls.
|
||||
ntStatus = unknownWave->QueryInterface(IID_IPortClsRuntimePower, (PVOID *)&pPortClsRuntimePower);
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
// This interface would typically be stashed away for later use. Instead,
|
||||
// let's just send an empty control with GUID_NULL.
|
||||
NTSTATUS ntStatusTest =
|
||||
pPortClsRuntimePower->SendPowerControl
|
||||
(
|
||||
_pDeviceObject,
|
||||
&GUID_NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(ntStatusTest) || STATUS_NOT_IMPLEMENTED == ntStatusTest || STATUS_NOT_SUPPORTED == ntStatusTest)
|
||||
{
|
||||
ntStatus = pPortClsRuntimePower->RegisterPowerControlCallback(_pDeviceObject, &PowerControlCallback, NULL);
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
ntStatus = pPortClsRuntimePower->UnregisterPowerControlCallback(_pDeviceObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ntStatus = ntStatusTest;
|
||||
}
|
||||
|
||||
pPortClsRuntimePower->Release();
|
||||
}
|
||||
#endif // _USE_IPortClsRuntimePower
|
||||
|
||||
//
|
||||
// Test: add and remove current thread as streaming audio resource.
|
||||
// In a real driver you should only add interrupts and driver-owned threads
|
||||
// (i.e., do NOT add the current thread as streaming resource).
|
||||
//
|
||||
// testing IPortClsStreamResourceManager:
|
||||
ntStatus = unknownWave->QueryInterface(IID_IPortClsStreamResourceManager, (PVOID *)&pPortClsResMgr);
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
PCSTREAMRESOURCE_DESCRIPTOR res;
|
||||
PCSTREAMRESOURCE hRes = NULL;
|
||||
PDEVICE_OBJECT pdo = NULL;
|
||||
|
||||
PcGetPhysicalDeviceObject(_pDeviceObject, &pdo);
|
||||
PCSTREAMRESOURCE_DESCRIPTOR_INIT(&res);
|
||||
res.Pdo = pdo;
|
||||
res.Type = ePcStreamResourceThread;
|
||||
res.Resource.Thread = PsGetCurrentThread();
|
||||
|
||||
NTSTATUS ntStatusTest = pPortClsResMgr->AddStreamResource(NULL, &res, &hRes);
|
||||
if (NT_SUCCESS(ntStatusTest))
|
||||
{
|
||||
pPortClsResMgr->RemoveStreamResource(hRes);
|
||||
hRes = NULL;
|
||||
}
|
||||
|
||||
pPortClsResMgr->Release();
|
||||
pPortClsResMgr = NULL;
|
||||
}
|
||||
|
||||
// testing IPortClsStreamResourceManager2:
|
||||
ntStatus = unknownWave->QueryInterface(IID_IPortClsStreamResourceManager2, (PVOID *)&pPortClsResMgr2);
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
PCSTREAMRESOURCE_DESCRIPTOR res;
|
||||
PCSTREAMRESOURCE hRes = NULL;
|
||||
PDEVICE_OBJECT pdo = NULL;
|
||||
|
||||
PcGetPhysicalDeviceObject(_pDeviceObject, &pdo);
|
||||
PCSTREAMRESOURCE_DESCRIPTOR_INIT(&res);
|
||||
res.Pdo = pdo;
|
||||
res.Type = ePcStreamResourceThread;
|
||||
res.Resource.Thread = PsGetCurrentThread();
|
||||
|
||||
NTSTATUS ntStatusTest = pPortClsResMgr2->AddStreamResource2(pdo, NULL, &res, &hRes);
|
||||
if (NT_SUCCESS(ntStatusTest))
|
||||
{
|
||||
pPortClsResMgr2->RemoveStreamResource(hRes);
|
||||
hRes = NULL;
|
||||
}
|
||||
|
||||
pPortClsResMgr2->Release();
|
||||
pPortClsResMgr2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_RELEASE(unknownTopology);
|
||||
SAFE_RELEASE(unknownWave);
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
InstallAllRenderFilters(
|
||||
_In_ PDEVICE_OBJECT _pDeviceObject,
|
||||
_In_ PIRP _pIrp,
|
||||
_In_ PADAPTERCOMMON _pAdapterCommon
|
||||
)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
PENDPOINT_MINIPAIR* ppAeMiniports = g_RenderEndpoints;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
for(ULONG i = 0; i < g_cRenderEndpoints; ++i, ++ppAeMiniports)
|
||||
{
|
||||
ntStatus = InstallEndpointRenderFilters(_pDeviceObject, _pIrp, _pAdapterCommon, *ppAeMiniports);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
}
|
||||
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
|
||||
Exit:
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
InstallEndpointCaptureFilters(
|
||||
_In_ PDEVICE_OBJECT _pDeviceObject,
|
||||
_In_ PIRP _pIrp,
|
||||
_In_ PADAPTERCOMMON _pAdapterCommon,
|
||||
_In_ PENDPOINT_MINIPAIR _pAeMiniports
|
||||
)
|
||||
{
|
||||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(_pDeviceObject);
|
||||
|
||||
ntStatus = _pAdapterCommon->InstallEndpointFilters(
|
||||
_pIrp,
|
||||
_pAeMiniports,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, NULL);
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
InstallAllCaptureFilters(
|
||||
_In_ PDEVICE_OBJECT _pDeviceObject,
|
||||
_In_ PIRP _pIrp,
|
||||
_In_ PADAPTERCOMMON _pAdapterCommon
|
||||
)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
PENDPOINT_MINIPAIR* ppAeMiniports = g_CaptureEndpoints;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
for (ULONG i = 0; i < g_cCaptureEndpoints; ++i, ++ppAeMiniports)
|
||||
{
|
||||
ntStatus = InstallEndpointCaptureFilters(_pDeviceObject, _pIrp, _pAdapterCommon, *ppAeMiniports);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
}
|
||||
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
|
||||
Exit:
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
StartDevice
|
||||
(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIRP Irp,
|
||||
_In_ PRESOURCELIST ResourceList
|
||||
)
|
||||
{
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This function is called by the operating system when the device is
|
||||
started.
|
||||
It is responsible for starting the miniports. This code is specific to
|
||||
the adapter because it calls out miniports for functions that are specific
|
||||
to the adapter.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - pointer to the driver object
|
||||
|
||||
Irp - pointer to the irp
|
||||
|
||||
ResourceList - pointer to the resource list assigned by PnP manager
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
UNREFERENCED_PARAMETER(ResourceList);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
ASSERT(ResourceList);
|
||||
|
||||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||||
|
||||
PADAPTERCOMMON pAdapterCommon = NULL;
|
||||
PUNKNOWN pUnknownCommon = NULL;
|
||||
PortClassDeviceContext* pExtension = static_cast<PortClassDeviceContext*>(DeviceObject->DeviceExtension);
|
||||
|
||||
DPF_ENTER(("[StartDevice]"));
|
||||
|
||||
//
|
||||
// create a new adapter common object
|
||||
//
|
||||
ntStatus = NewAdapterCommon(
|
||||
&pUnknownCommon,
|
||||
IID_IAdapterCommon,
|
||||
NULL,
|
||||
POOL_FLAG_NON_PAGED
|
||||
);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
|
||||
ntStatus = pUnknownCommon->QueryInterface( IID_IAdapterCommon,(PVOID *) &pAdapterCommon);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
|
||||
ntStatus = pAdapterCommon->Init(DeviceObject);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
|
||||
//
|
||||
// register with PortCls for power-management services
|
||||
ntStatus = PcRegisterAdapterPowerManagement( PUNKNOWN(pAdapterCommon), DeviceObject);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
|
||||
//
|
||||
// Install wave+topology filters for render devices
|
||||
//
|
||||
ntStatus = InstallAllRenderFilters(DeviceObject, Irp, pAdapterCommon);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
|
||||
//
|
||||
// Install wave+topology filters for capture devices
|
||||
//
|
||||
ntStatus = InstallAllCaptureFilters(DeviceObject, Irp, pAdapterCommon);
|
||||
IF_FAILED_JUMP(ntStatus, Exit);
|
||||
|
||||
Exit:
|
||||
|
||||
//
|
||||
// Stash the adapter common object in the device extension so
|
||||
// we can access it for cleanup on stop/removal.
|
||||
//
|
||||
if (pAdapterCommon)
|
||||
{
|
||||
ASSERT(pExtension != NULL);
|
||||
pExtension->m_pCommon = pAdapterCommon;
|
||||
}
|
||||
|
||||
//
|
||||
// Release the adapter IUnknown interface.
|
||||
//
|
||||
SAFE_RELEASE(pUnknownCommon);
|
||||
|
||||
return ntStatus;
|
||||
} // StartDevice
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
PnpHandler
|
||||
(
|
||||
_In_ DEVICE_OBJECT *_DeviceObject,
|
||||
_Inout_ IRP *_Irp
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles PnP IRPs
|
||||
|
||||
Arguments:
|
||||
|
||||
_DeviceObject - Functional Device object pointer.
|
||||
|
||||
_Irp - The Irp being passed
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
|
||||
IO_STACK_LOCATION *stack;
|
||||
PortClassDeviceContext *ext;
|
||||
|
||||
// Documented https://msdn.microsoft.com/en-us/library/windows/hardware/ff544039(v=vs.85).aspx
|
||||
// This method will be called in IRQL PASSIVE_LEVEL
|
||||
#pragma warning(suppress: 28118)
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(_DeviceObject);
|
||||
ASSERT(_Irp);
|
||||
|
||||
//
|
||||
// Check for the REMOVE_DEVICE irp. If we're being unloaded,
|
||||
// uninstantiate our devices and release the adapter common
|
||||
// object.
|
||||
//
|
||||
stack = IoGetCurrentIrpStackLocation(_Irp);
|
||||
|
||||
switch (stack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
ext = static_cast<PortClassDeviceContext*>(_DeviceObject->DeviceExtension);
|
||||
|
||||
if (ext->m_pCommon != NULL)
|
||||
{
|
||||
ext->m_pCommon->Cleanup();
|
||||
|
||||
ext->m_pCommon->Release();
|
||||
ext->m_pCommon = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ntStatus = PcDispatchIrp(_DeviceObject, _Irp);
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
#pragma code_seg()
|
||||
|
||||
@@ -0,0 +1,688 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
basetopo.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of topology miniport. This the base class for
|
||||
all simple audio sample drivers
|
||||
--*/
|
||||
|
||||
//4127: conditional expression is constant
|
||||
#pragma warning (disable : 4127)
|
||||
|
||||
#include "definitions.h"
|
||||
#include "basetopo.h"
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
CMiniportTopologyVirtualAudioDriver::CMiniportTopologyVirtualAudioDriver
|
||||
(
|
||||
_In_ PCFILTER_DESCRIPTOR *FilterDesc,
|
||||
_In_ USHORT DeviceMaxChannels
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Topology miniport constructor
|
||||
|
||||
Arguments:
|
||||
|
||||
FilterDesc -
|
||||
|
||||
DeviceMaxChannels -
|
||||
|
||||
Return Value:
|
||||
|
||||
void
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[%s]",__FUNCTION__));
|
||||
|
||||
m_AdapterCommon = NULL;
|
||||
|
||||
ASSERT(FilterDesc != NULL);
|
||||
m_FilterDescriptor = FilterDesc;
|
||||
m_PortEvents = NULL;
|
||||
|
||||
ASSERT(DeviceMaxChannels > 0);
|
||||
m_DeviceMaxChannels = DeviceMaxChannels;
|
||||
} // CMiniportTopologyVirtualAudioDriver
|
||||
|
||||
CMiniportTopologyVirtualAudioDriver::~CMiniportTopologyVirtualAudioDriver
|
||||
(
|
||||
void
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Topology miniport destructor
|
||||
|
||||
Arguments:
|
||||
|
||||
Return Value:
|
||||
|
||||
void
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[%s]",__FUNCTION__));
|
||||
|
||||
SAFE_RELEASE(m_AdapterCommon);
|
||||
SAFE_RELEASE(m_PortEvents);
|
||||
} // ~CMiniportTopologyVirtualAudioDriver
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopologyVirtualAudioDriver::DataRangeIntersection
|
||||
(
|
||||
_In_ ULONG PinId,
|
||||
_In_ PKSDATARANGE ClientDataRange,
|
||||
_In_ PKSDATARANGE MyDataRange,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
|
||||
PVOID ResultantFormat OPTIONAL,
|
||||
_Out_ PULONG ResultantFormatLength
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The DataRangeIntersection function determines the highest
|
||||
quality intersection of two data ranges. Topology miniport does nothing.
|
||||
|
||||
Arguments:
|
||||
|
||||
PinId - Pin for which data intersection is being determined.
|
||||
|
||||
ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
|
||||
submitted by client in the data range intersection property
|
||||
request
|
||||
|
||||
MyDataRange - Pin's data range to be compared with client's data range
|
||||
|
||||
OutputBufferLength - Size of the buffer pointed to by the resultant format
|
||||
parameter
|
||||
|
||||
ResultantFormat - Pointer to value where the resultant format should be
|
||||
returned
|
||||
|
||||
ResultantFormatLength - Actual length of the resultant format that is placed
|
||||
at ResultantFormat. This should be less than or equal
|
||||
to OutputBufferLength
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PinId);
|
||||
UNREFERENCED_PARAMETER(ClientDataRange);
|
||||
UNREFERENCED_PARAMETER(MyDataRange);
|
||||
UNREFERENCED_PARAMETER(OutputBufferLength);
|
||||
UNREFERENCED_PARAMETER(ResultantFormat);
|
||||
UNREFERENCED_PARAMETER(ResultantFormatLength);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[%s]",__FUNCTION__));
|
||||
|
||||
return (STATUS_NOT_IMPLEMENTED);
|
||||
} // DataRangeIntersection
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopologyVirtualAudioDriver::GetDescription
|
||||
(
|
||||
_Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The GetDescription function gets a pointer to a filter description.
|
||||
It provides a location to deposit a pointer in miniport's description
|
||||
structure. This is the placeholder for the FromNode or ToNode fields in
|
||||
connections which describe connections to the filter's pins
|
||||
|
||||
Arguments:
|
||||
|
||||
OutFilterDescriptor - Pointer to the filter description.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(OutFilterDescriptor);
|
||||
|
||||
DPF_ENTER(("[%s]",__FUNCTION__));
|
||||
|
||||
*OutFilterDescriptor = m_FilterDescriptor;
|
||||
|
||||
return (STATUS_SUCCESS);
|
||||
} // GetDescription
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopologyVirtualAudioDriver::Init
|
||||
(
|
||||
_In_ PUNKNOWN UnknownAdapter_,
|
||||
_In_ PPORTTOPOLOGY Port_
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes the topology miniport.
|
||||
|
||||
Arguments:
|
||||
|
||||
UnknownAdapter -
|
||||
|
||||
Port_ - Pointer to topology port
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(UnknownAdapter_);
|
||||
ASSERT(Port_);
|
||||
|
||||
DPF_ENTER(("[CMiniportTopologyVirtualAudioDriver::Init]"));
|
||||
|
||||
NTSTATUS ntStatus;
|
||||
|
||||
ntStatus =
|
||||
UnknownAdapter_->QueryInterface(
|
||||
IID_IAdapterCommon,
|
||||
(PVOID *) &m_AdapterCommon);
|
||||
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
//
|
||||
// Get the port event interface.
|
||||
//
|
||||
ntStatus = Port_->QueryInterface(
|
||||
IID_IPortEvents,
|
||||
(PVOID *)&m_PortEvents);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
m_AdapterCommon->MixerReset();
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
// clean up AdapterCommon
|
||||
SAFE_RELEASE(m_AdapterCommon);
|
||||
SAFE_RELEASE(m_PortEvents);
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // Init
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopologyVirtualAudioDriver::PropertyHandlerGeneric
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles all properties for this miniport.
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest - property request structure
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
switch (PropertyRequest->PropertyItem->Id)
|
||||
{
|
||||
case KSPROPERTY_AUDIO_VOLUMELEVEL:
|
||||
ntStatus = PropertyHandler_Volume(
|
||||
m_AdapterCommon,
|
||||
PropertyRequest,
|
||||
m_DeviceMaxChannels);
|
||||
break;
|
||||
|
||||
case KSPROPERTY_AUDIO_MUTE:
|
||||
ntStatus = PropertyHandler_Mute(
|
||||
m_AdapterCommon,
|
||||
PropertyRequest,
|
||||
m_DeviceMaxChannels);
|
||||
break;
|
||||
|
||||
case KSPROPERTY_AUDIO_PEAKMETER2:
|
||||
ntStatus = PropertyHandler_PeakMeter2(
|
||||
m_AdapterCommon,
|
||||
PropertyRequest,
|
||||
m_DeviceMaxChannels);
|
||||
break;
|
||||
|
||||
case KSPROPERTY_AUDIO_CPU_RESOURCES:
|
||||
ntStatus = PropertyHandler_CpuResources(PropertyRequest);
|
||||
break;
|
||||
|
||||
case KSPROPERTY_AUDIO_MUX_SOURCE:
|
||||
ntStatus = PropertyHandlerMuxSource(PropertyRequest);
|
||||
break;
|
||||
|
||||
case KSPROPERTY_AUDIO_DEV_SPECIFIC:
|
||||
ntStatus = PropertyHandlerDevSpecific(PropertyRequest);
|
||||
break;
|
||||
|
||||
default:
|
||||
DPF(D_TERSE, ("[PropertyHandlerGeneric: Invalid Device Request]"));
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // PropertyHandlerGeneric
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopologyVirtualAudioDriver::PropertyHandlerMuxSource
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
PropertyHandler for KSPROPERTY_AUDIO_MUX_SOURCE.
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest - property request structure
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[%s]",__FUNCTION__));
|
||||
|
||||
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
//
|
||||
// Validate node
|
||||
// This property is only valid for WAVEIN_MUX node.
|
||||
//
|
||||
// TODO if (WAVEIN_MUX == PropertyRequest->Node)
|
||||
{
|
||||
if (PropertyRequest->ValueSize >= sizeof(ULONG))
|
||||
{
|
||||
PULONG pulMuxValue = PULONG(PropertyRequest->Value);
|
||||
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
|
||||
{
|
||||
*pulMuxValue = m_AdapterCommon->MixerMuxRead();
|
||||
PropertyRequest->ValueSize = sizeof(ULONG);
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
|
||||
{
|
||||
m_AdapterCommon->MixerMuxWrite(*pulMuxValue);
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
|
||||
{
|
||||
ntStatus =
|
||||
PropertyHandler_BasicSupport
|
||||
(
|
||||
PropertyRequest,
|
||||
KSPROPERTY_TYPE_ALL,
|
||||
VT_I4
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPF(D_TERSE, ("[PropertyHandlerMuxSource - Invalid parameter]"));
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // PropertyHandlerMuxSource
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopologyVirtualAudioDriver::PropertyHandlerDevSpecific(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Property handler for KSPROPERTY_AUDIO_DEV_SPECIFIC
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest - property request structure
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[%s]",__FUNCTION__));
|
||||
|
||||
NTSTATUS ntStatus=STATUS_SUCCESS;
|
||||
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
|
||||
{
|
||||
if( DEV_SPECIFIC_VT_BOOL == PropertyRequest->Node )
|
||||
{
|
||||
ntStatus = PropertyHandler_BasicSupport(PropertyRequest,KSPROPERTY_TYPE_ALL,VT_BOOL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG ExpectedSize = sizeof( KSPROPERTY_DESCRIPTION ) +
|
||||
sizeof( KSPROPERTY_MEMBERSHEADER ) +
|
||||
sizeof( KSPROPERTY_BOUNDS_LONG );
|
||||
DWORD ulPropTypeSetId;
|
||||
|
||||
if( DEV_SPECIFIC_VT_I4 == PropertyRequest->Node )
|
||||
{
|
||||
ulPropTypeSetId = VT_I4;
|
||||
}
|
||||
else if ( DEV_SPECIFIC_VT_UI4 == PropertyRequest->Node )
|
||||
{
|
||||
ulPropTypeSetId = VT_UI4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulPropTypeSetId = VT_ILLEGAL;
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if( NT_SUCCESS(ntStatus))
|
||||
{
|
||||
if ( !PropertyRequest->ValueSize )
|
||||
{
|
||||
PropertyRequest->ValueSize = ExpectedSize;
|
||||
ntStatus = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION))
|
||||
{
|
||||
// if return buffer can hold a KSPROPERTY_DESCRIPTION, return it
|
||||
//
|
||||
PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
|
||||
|
||||
PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL;
|
||||
PropDesc->DescriptionSize = ExpectedSize;
|
||||
PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
|
||||
PropDesc->PropTypeSet.Id = ulPropTypeSetId;
|
||||
PropDesc->PropTypeSet.Flags = 0;
|
||||
PropDesc->MembersListCount = 0;
|
||||
PropDesc->Reserved = 0;
|
||||
|
||||
if ( PropertyRequest->ValueSize >= ExpectedSize )
|
||||
{
|
||||
// Extra information to return
|
||||
PropDesc->MembersListCount = 1;
|
||||
|
||||
PKSPROPERTY_MEMBERSHEADER MembersHeader = ( PKSPROPERTY_MEMBERSHEADER )( PropDesc + 1);
|
||||
MembersHeader->MembersFlags = KSPROPERTY_MEMBER_RANGES;
|
||||
MembersHeader->MembersCount = 1;
|
||||
MembersHeader->MembersSize = sizeof( KSPROPERTY_BOUNDS_LONG );
|
||||
MembersHeader->Flags = 0;
|
||||
|
||||
PKSPROPERTY_BOUNDS_LONG PeakMeterBounds = (PKSPROPERTY_BOUNDS_LONG)( MembersHeader + 1);
|
||||
if(VT_I4 == ulPropTypeSetId )
|
||||
{
|
||||
PeakMeterBounds->SignedMinimum = 0;
|
||||
PeakMeterBounds->SignedMaximum = 0x7fffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
PeakMeterBounds->UnsignedMinimum = 0;
|
||||
PeakMeterBounds->UnsignedMaximum = 0xffffffff;
|
||||
}
|
||||
|
||||
// set the return value size
|
||||
PropertyRequest->ValueSize = ExpectedSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No extra information to return.
|
||||
PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
|
||||
}
|
||||
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else if (PropertyRequest->ValueSize >= sizeof(ULONG))
|
||||
{
|
||||
// if return buffer can hold a ULONG, return the access flags
|
||||
//
|
||||
*(PULONG(PropertyRequest->Value)) = KSPROPERTY_TYPE_ALL;
|
||||
|
||||
PropertyRequest->ValueSize = sizeof(ULONG);
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyRequest->ValueSize = 0;
|
||||
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// switch on node id
|
||||
switch( PropertyRequest->Node )
|
||||
{
|
||||
case DEV_SPECIFIC_VT_BOOL:
|
||||
{
|
||||
PBOOL pbDevSpecific;
|
||||
|
||||
ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(BOOL), 0);
|
||||
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
pbDevSpecific = PBOOL (PropertyRequest->Value);
|
||||
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
|
||||
{
|
||||
*pbDevSpecific = m_AdapterCommon->bDevSpecificRead();
|
||||
PropertyRequest->ValueSize = sizeof(BOOL);
|
||||
}
|
||||
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
|
||||
{
|
||||
m_AdapterCommon->bDevSpecificWrite(*pbDevSpecific);
|
||||
}
|
||||
else
|
||||
{
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEV_SPECIFIC_VT_I4:
|
||||
{
|
||||
INT* piDevSpecific;
|
||||
|
||||
ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(int), 0);
|
||||
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
piDevSpecific = PINT (PropertyRequest->Value);
|
||||
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
|
||||
{
|
||||
*piDevSpecific = m_AdapterCommon->iDevSpecificRead();
|
||||
PropertyRequest->ValueSize = sizeof(int);
|
||||
}
|
||||
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
|
||||
{
|
||||
m_AdapterCommon->iDevSpecificWrite(*piDevSpecific);
|
||||
}
|
||||
else
|
||||
{
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEV_SPECIFIC_VT_UI4:
|
||||
{
|
||||
UINT* puiDevSpecific;
|
||||
|
||||
ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(UINT), 0);
|
||||
|
||||
if (NT_SUCCESS(ntStatus))
|
||||
{
|
||||
puiDevSpecific = PUINT (PropertyRequest->Value);
|
||||
|
||||
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
|
||||
{
|
||||
*puiDevSpecific = m_AdapterCommon->uiDevSpecificRead();
|
||||
PropertyRequest->ValueSize = sizeof(UINT);
|
||||
}
|
||||
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
|
||||
{
|
||||
m_AdapterCommon->uiDevSpecificWrite(*puiDevSpecific);
|
||||
}
|
||||
else
|
||||
{
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( !NT_SUCCESS(ntStatus))
|
||||
{
|
||||
DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus));
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
} // PropertyHandlerDevSpecific
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
VOID
|
||||
CMiniportTopologyVirtualAudioDriver::AddEventToEventList
|
||||
(
|
||||
_In_ PKSEVENT_ENTRY EventEntry
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The AddEventToEventList method adds an event to the port driver's event list
|
||||
|
||||
Arguments:
|
||||
|
||||
EventEntry -
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
DPF_ENTER(("[CMiniportTopology::AddEventToEventList]"));
|
||||
|
||||
ASSERT(m_PortEvents != NULL);
|
||||
|
||||
m_PortEvents->AddEventToEventList(EventEntry);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg()
|
||||
VOID
|
||||
CMiniportTopologyVirtualAudioDriver::GenerateEventList
|
||||
(
|
||||
_In_opt_ GUID *Set,
|
||||
_In_ ULONG EventId,
|
||||
_In_ BOOL PinEvent,
|
||||
_In_ ULONG PinId,
|
||||
_In_ BOOL NodeEvent,
|
||||
_In_ ULONG NodeId
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The GenerateEventList method notifies clients through the port driver's list
|
||||
of event entries that a particular event has occurred.
|
||||
|
||||
Arguments:
|
||||
|
||||
Set -
|
||||
|
||||
EventId -
|
||||
|
||||
PinEvent -
|
||||
|
||||
PinId -
|
||||
|
||||
NodeEvent -
|
||||
|
||||
NodeId -
|
||||
|
||||
--*/
|
||||
{
|
||||
DPF_ENTER(("[CMiniportTopologyVirtualAudioDriver::GenerateEventList]"));
|
||||
|
||||
ASSERT(m_PortEvents != NULL);
|
||||
|
||||
m_PortEvents->GenerateEventList(
|
||||
Set,
|
||||
EventId,
|
||||
PinEvent,
|
||||
PinId,
|
||||
NodeEvent,
|
||||
NodeId);
|
||||
}
|
||||
|
||||
#pragma code_seg()
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,557 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation All Rights Reserved
|
||||
|
||||
Module Name:
|
||||
|
||||
mintopo.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of topology miniport.
|
||||
--*/
|
||||
|
||||
#pragma warning (disable : 4127)
|
||||
|
||||
#include "definitions.h"
|
||||
#include "endpoints.h"
|
||||
#include "minwavert.h"
|
||||
#include "mintopo.h"
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CreateMiniportTopologyVirtualAudioDriver
|
||||
(
|
||||
_Out_ PUNKNOWN * Unknown,
|
||||
_In_ REFCLSID,
|
||||
_In_opt_ PUNKNOWN UnknownOuter,
|
||||
_In_ POOL_FLAGS PoolFlags,
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_opt_ PVOID DeviceContext,
|
||||
_In_ PENDPOINT_MINIPAIR MiniportPair
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Creates a new topology miniport.
|
||||
|
||||
Arguments:
|
||||
|
||||
Unknown -
|
||||
|
||||
RefclsId -
|
||||
|
||||
PoolType -
|
||||
|
||||
UnknownOuter -
|
||||
|
||||
DeviceContext -
|
||||
|
||||
MiniportPair -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER(UnknownAdapter);
|
||||
|
||||
ASSERT(Unknown);
|
||||
ASSERT(MiniportPair);
|
||||
|
||||
CMiniportTopology *obj =
|
||||
new (PoolFlags, MINWAVERT_POOLTAG)
|
||||
CMiniportTopology( UnknownOuter,
|
||||
MiniportPair->TopoDescriptor,
|
||||
MiniportPair->DeviceMaxChannels,
|
||||
MiniportPair->DeviceType,
|
||||
DeviceContext );
|
||||
if (NULL == obj)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
obj->AddRef();
|
||||
*Unknown = reinterpret_cast<IUnknown*>(obj);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
} // CreateMiniportTopologyVirtualAudioDriver
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
CMiniportTopology::~CMiniportTopology
|
||||
(
|
||||
void
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Topology miniport destructor
|
||||
|
||||
Arguments:
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
DPF_ENTER(("[CMiniportTopology::~CMiniportTopology]"));
|
||||
} // ~CMiniportTopology
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopology::DataRangeIntersection
|
||||
(
|
||||
_In_ ULONG PinId,
|
||||
_In_ PKSDATARANGE ClientDataRange,
|
||||
_In_ PKSDATARANGE MyDataRange,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
|
||||
PVOID ResultantFormat,
|
||||
_Out_ PULONG ResultantFormatLength
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The DataRangeIntersection function determines the highest quality
|
||||
intersection of two data ranges.
|
||||
|
||||
Arguments:
|
||||
|
||||
PinId - Pin for which data intersection is being determined.
|
||||
|
||||
ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
|
||||
submitted by client in the data range intersection property
|
||||
request.
|
||||
|
||||
MyDataRange - Pin's data range to be compared with client's data range.
|
||||
|
||||
OutputBufferLength - Size of the buffer pointed to by the resultant format
|
||||
parameter.
|
||||
|
||||
ResultantFormat - Pointer to value where the resultant format should be
|
||||
returned.
|
||||
|
||||
ResultantFormatLength - Actual length of the resultant format that is placed
|
||||
at ResultantFormat. This should be less than or equal
|
||||
to OutputBufferLength.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
return
|
||||
CMiniportTopologyVirtualAudioDriver::DataRangeIntersection
|
||||
(
|
||||
PinId,
|
||||
ClientDataRange,
|
||||
MyDataRange,
|
||||
OutputBufferLength,
|
||||
ResultantFormat,
|
||||
ResultantFormatLength
|
||||
);
|
||||
} // DataRangeIntersection
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
STDMETHODIMP
|
||||
CMiniportTopology::GetDescription
|
||||
(
|
||||
_Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The GetDescription function gets a pointer to a filter description.
|
||||
It provides a location to deposit a pointer in miniport's description
|
||||
structure. This is the placeholder for the FromNode or ToNode fields in
|
||||
connections which describe connections to the filter's pins.
|
||||
|
||||
Arguments:
|
||||
|
||||
OutFilterDescriptor - Pointer to the filter description.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(OutFilterDescriptor);
|
||||
|
||||
return CMiniportTopologyVirtualAudioDriver::GetDescription(OutFilterDescriptor);
|
||||
} // GetDescription
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
STDMETHODIMP
|
||||
CMiniportTopology::Init
|
||||
(
|
||||
_In_ PUNKNOWN UnknownAdapter,
|
||||
_In_ PRESOURCELIST ResourceList,
|
||||
_In_ PPORTTOPOLOGY Port_
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The Init function initializes the miniport. Callers of this function
|
||||
should run at IRQL PASSIVE_LEVEL
|
||||
|
||||
Arguments:
|
||||
|
||||
UnknownAdapter - A pointer to the Iuknown interface of the adapter object.
|
||||
|
||||
ResourceList - Pointer to the resource list to be supplied to the miniport
|
||||
during initialization. The port driver is free to examine the
|
||||
contents of the ResourceList. The port driver will not be
|
||||
modify the ResourceList contents.
|
||||
|
||||
Port - Pointer to the topology port object that is linked with this miniport.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ResourceList);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(UnknownAdapter);
|
||||
ASSERT(Port_);
|
||||
|
||||
DPF_ENTER(("[CMiniportTopology::Init]"));
|
||||
|
||||
NTSTATUS ntStatus;
|
||||
|
||||
ntStatus =
|
||||
CMiniportTopologyVirtualAudioDriver::Init
|
||||
(
|
||||
UnknownAdapter,
|
||||
Port_
|
||||
);
|
||||
|
||||
IF_FAILED_ACTION_JUMP(
|
||||
ntStatus,
|
||||
DPF(D_ERROR, ("Init: CMiniportTopologyVirtualAudioDriver::Init failed, 0x%x", ntStatus)),
|
||||
Done);
|
||||
|
||||
Done:
|
||||
return ntStatus;
|
||||
} // Init
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
STDMETHODIMP
|
||||
CMiniportTopology::NonDelegatingQueryInterface
|
||||
(
|
||||
_In_ REFIID Interface,
|
||||
_COM_Outptr_ PVOID * Object
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
QueryInterface for MiniportTopology
|
||||
|
||||
Arguments:
|
||||
|
||||
Interface - GUID of the interface
|
||||
|
||||
Object - interface object to be returned.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(Object);
|
||||
|
||||
if (IsEqualGUIDAligned(Interface, IID_IUnknown))
|
||||
{
|
||||
*Object = PVOID(PUNKNOWN(this));
|
||||
}
|
||||
else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
|
||||
{
|
||||
*Object = PVOID(PMINIPORT(this));
|
||||
}
|
||||
else if (IsEqualGUIDAligned(Interface, IID_IMiniportTopology))
|
||||
{
|
||||
*Object = PVOID(PMINIPORTTOPOLOGY(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
*Object = NULL;
|
||||
}
|
||||
|
||||
if (*Object)
|
||||
{
|
||||
// We reference the interface for the caller.
|
||||
PUNKNOWN(*Object)->AddRef();
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
return(STATUS_INVALID_PARAMETER);
|
||||
} // NonDelegatingQueryInterface
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopology::PropertyHandlerJackDescription
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG cJackDescriptions,
|
||||
_In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
cJackDescriptions - # of elements in the jack descriptions array.
|
||||
JackDescriptions - Array of jack descriptions pointers.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandlerJackDescription]"));
|
||||
|
||||
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_DESCRIPTION);
|
||||
|
||||
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_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1);
|
||||
|
||||
pMI->Size = cbNeeded;
|
||||
pMI->Count = 1;
|
||||
|
||||
RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
CMiniportTopology::PropertyHandlerJackDescription2
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest,
|
||||
_In_ ULONG cJackDescriptions,
|
||||
_In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions,
|
||||
_In_ DWORD JackCapabilities
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
cJackDescriptions - # of elements in the jack descriptions array.
|
||||
JackDescriptions - Array of jack descriptions pointers.
|
||||
JackCapabilities - Jack capabilities flags.
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandlerJackDescription2]"));
|
||||
|
||||
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_DESCRIPTION2);
|
||||
|
||||
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_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1);
|
||||
|
||||
pMI->Size = cbNeeded;
|
||||
pMI->Count = 1;
|
||||
|
||||
RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
|
||||
|
||||
//
|
||||
// Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
|
||||
// the jack is currently active, streaming, idle, or hardware not ready.
|
||||
//
|
||||
pDesc->DeviceStateInfo = 0;
|
||||
|
||||
//
|
||||
// From MSDN:
|
||||
// "If an audio device lacks jack presence detection, the IsConnected member of
|
||||
// the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
|
||||
// ambiguity that results from this dual meaning of the TRUE value for IsConnected,
|
||||
// a client application can call IKsJackDescription2::GetJackDescription2 to read
|
||||
// the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
|
||||
// the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
|
||||
// does in fact support jack presence detection. In that case, the return value of
|
||||
// the IsConnected member can be interpreted to accurately reflect the insertion status
|
||||
// of the jack."
|
||||
//
|
||||
// Bit definitions:
|
||||
// 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
|
||||
// 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
|
||||
//
|
||||
pDesc->JackCapabilities = JackCapabilities;
|
||||
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#pragma code_seg("PAGE")
|
||||
NTSTATUS
|
||||
PropertyHandler_Topology
|
||||
(
|
||||
_In_ PPCPROPERTY_REQUEST PropertyRequest
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Redirects property request to miniport object
|
||||
|
||||
Arguments:
|
||||
|
||||
PropertyRequest -
|
||||
|
||||
Return Value:
|
||||
|
||||
NT status code.
|
||||
|
||||
--*/
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PropertyRequest);
|
||||
|
||||
DPF_ENTER(("[PropertyHandler_Topology]"));
|
||||
|
||||
// PropertryRequest structure is filled by portcls.
|
||||
// MajorTarget is a pointer to miniport object for miniports.
|
||||
//
|
||||
return
|
||||
((PCMiniportTopology)
|
||||
(PropertyRequest->MajorTarget))->PropertyHandlerGeneric
|
||||
(
|
||||
PropertyRequest
|
||||
);
|
||||
} // PropertyHandler_Topology
|
||||
Loaded 100 of 115 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user