Windows Dev Test Harness

Internal developer guide for building and testing the Mcaster1AudioPipe WDM driver. End users should use the GUI application to install the driver — no special setup needed.

Contents

Overview

The Mcaster1AudioPipe Windows driver is a WDM kernel-mode PortCls WaveRT miniport that creates virtual audio endpoints. During development, before obtaining a Microsoft driver signing certificate (EV code signing or attestation signing via the Windows Hardware Developer Center), the driver must be installed in test signing mode.

Important Test signing mode places a "Test Mode" watermark on the desktop. This is normal and expected during development. It will be removed once the driver is production-signed.

┌─────────────────────┐ pnputil ┌──────────────────────┐ │ Mcaster1AudioPipe │ ──────/add-driver───▶ │ Windows Driver │ │ Qt6 GUI (.exe) │ /install │ Store │ └─────────────────────┘ └──────────┬───────────┘ │ │ detects arch, loads on PnP test signing, device enum shows status │ │ ┌──────────▼───────────┐ └──── IPC (Named Pipes) ──────────▶ │ Mcaster1AudioPipe │ (future: via service) │ .sys (kernel mode) │ │ PortCls WaveRT │ └──────────────────────┘

Prerequisites

ComponentVersionInstall Command / Notes
Visual Studio 2022 17.x (Pro or Community) "Desktop development with C++" workload
Windows SDK 10.0.26100.0 Installed with VS2022 or winget install Microsoft.WindowsSDK
Windows Driver Kit 10.0.26100.0 winget install Microsoft.WindowsDriverKit
Qt 6.9.3 (msvc2022_64) Qt Online Installer — avoid 6.10.2 (broken cmake)
vcpkg latest git clone https://github.com/microsoft/vcpkg + bootstrap-vcpkg.bat
CMake 3.21+ Bundled with VS2022

Note The WDK must match the Windows SDK version. If using SDK 10.0.26100.0, install WDK 10.0.26100.0.

Step 1 — Build the WDM Driver (.sys)

The driver project is a standalone .vcxproj that uses the WDK build system.

Using MSBuild (recommended)

# Open "Developer Command Prompt for VS 2022" or "x64 Native Tools Command Prompt"

# Build Release|x64
MSBuild src\driver\windows\Mcaster1AudioPipe.vcxproj /p:Configuration=Release /p:Platform=x64

# Output:
#   src\driver\windows\Release\x64\Mcaster1AudioPipe.sys   (19 KB driver binary)
#   src\driver\windows\Release\x64\Mcaster1AudioPipe.pdb   (debug symbols)

Multi-architecture builds

# ARM64 (Surface Pro X, etc.)
MSBuild src\driver\windows\Mcaster1AudioPipe.vcxproj /p:Configuration=Release /p:Platform=ARM64

# x86 (32-bit, legacy)
MSBuild src\driver\windows\Mcaster1AudioPipe.vcxproj /p:Configuration=Release /p:Platform=Win32

# Debug build (verbose logging, assertions)
MSBuild src\driver\windows\Mcaster1AudioPipe.vcxproj /p:Configuration=Debug /p:Platform=x64

Using Visual Studio IDE

  1. Open src\driver\windows\Mcaster1AudioPipe.vcxproj in VS2022
  2. Set configuration to Release | x64
  3. Build > Build Solution (Ctrl+Shift+B)
  4. Output appears in src\driver\windows\Release\x64\

Source files compiled

FilePurpose
adapter.cppDriverEntry, AddDevice, StartDevice — creates WaveRT + Topology subdevices
miniport.cppCMiniportWaveRT (audio streaming) + CMiniportTopology (volume/mute nodes)
stream.cppCMiniportWaveRTStream — render/capture stream with lock-free ring buffer

Key headers

FilePurpose
adapter.hConstants, pin/node IDs, IOCTL codes, factory function declarations
miniport.hPIPE_DEVICE_WIN state struct, CMiniportWaveRT class, data range externs
stream.hCMiniportWaveRTStream class declaration
ring_buffer_win.hLock-free SPSC ring buffer (64-byte cache-line aligned)
ipc_server.hNamed Pipe IPC server (userspace service, excluded from kernel build)

Step 2 — Build the Qt GUI App

# Configure
cmake -B build -G "Visual Studio 17 2022" -A x64 ^
  -DCMAKE_PREFIX_PATH=C:\Qt\6.9.3\msvc2022_64 ^
  -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake

# Build
cmake --build build --config Release

# Copy driver files to build output
mkdir build\Release\driver 2>nul
copy src\driver\windows\Release\x64\Mcaster1AudioPipe.sys build\Release\driver\
copy src\driver\windows\Mcaster1AudioPipe.inf build\Release\driver\

# The INF is also auto-copied by CMake post-build step

Tip The GUI app's CMakeLists.txt includes a post-build step that copies the .inf to build/Release/driver/. You only need to manually copy the .sys after building the WDK project.

Step 3 — Enable Test Signing

Requires Reboot Test signing changes take effect only after a full system reboot. Plan accordingly.

What is test signing?

Windows requires all kernel-mode drivers to be digitally signed. During development, you can enable test signing mode which allows Windows to load drivers signed with a test certificate (or unsigned drivers via pnputil).

Enable test signing

# Run as Administrator (PowerShell or CMD):
bcdedit /set testsigning on

# Reboot to apply
shutdown /r /t 0

Verify test signing is active

# After reboot, check:
bcdedit | findstr testsigning

# Expected output:
# testsigning             Yes

# Visual confirmation: "Test Mode" watermark appears in bottom-right of desktop

Automated detection

The Mcaster1AudioPipe GUI app automatically detects test signing status when you click Install Driver. If test signing is not enabled, it offers to enable it for you (elevated via UAC) and reminds you to reboot.

Secure Boot If Secure Boot is enabled in your UEFI/BIOS, test signing mode may not work. You may need to disable Secure Boot temporarily, or use the one-time "Disable driver signature enforcement" option from Advanced Startup.

To access Advanced Startup:
Settings > System > Recovery > Advanced startup > Restart now
Then: Troubleshoot > Advanced options > Startup Settings > Restart
Press 7 or F7 to "Disable driver signature enforcement"

Step 4 — Install the Driver

Option A: From the GUI (recommended)

  1. Run the app as Administrator.
    Right-click Mcaster1AudioPipe.exe > "Run as administrator"
  2. Navigate to Audio Driver Management tab (Ctrl+3).
    The platform info panel shows your Windows version, architecture, and driver status.
  3. Click the blue "Install Driver" button.
    The app checks test signing status and validates driver files.
  4. Accept the UAC prompt for pnputil.exe.
    The driver is added to the Windows driver store and installed.
  5. Verify the status changes to "INSTALLED".
    If it doesn't, check the pnputil output in the error dialog.

Option B: From the command line

# Run as Administrator:

# Add driver to the driver store and install
pnputil /add-driver "C:\path\to\Mcaster1AudioPipe.inf" /install

# Expected output:
# Microsoft PnP Utility
# Adding driver package: Mcaster1AudioPipe.inf
# Driver package added successfully.
# Published name: oem##.inf

Option C: Using devcon (Device Console)

# devcon is part of the WDK tools
# Install the device directly:
devcon install Mcaster1AudioPipe.inf Root\Mcaster1AudioPipe

What happens during installation

  1. pnputil copies the .inf and .sys to the Windows driver store
  2. Windows PnP manager creates a device node for the virtual audio device
  3. PortCls loads the driver and calls DriverEntry > AddDevice > StartDevice
  4. The driver creates Wave (audio streaming) and Topology (volume/mute) subdevices
  5. The audio endpoint appears in Sound Settings as "Mcaster1 AudioPipe Virtual Audio Device"

Step 5 — Verify Installation

Check Sound Settings

Open Settings > System > Sound (or Win+I). Look for "Mcaster1 AudioPipe Virtual Audio Device" in the output and input device lists.

Check the driver store

# List third-party drivers in the store:
pnputil /enum-drivers

# Look for:
#   Original Name: Mcaster1AudioPipe.inf
#   Provider Name: Mcaster1
#   Class Name:    MEDIA

Check the registry

# Query the service registry key:
reg query "HKLM\SYSTEM\CurrentControlSet\Services\Mcaster1AudioPipe"

# If the key exists, the driver is registered

Check Device Manager

  1. Open Device Manager (devmgmt.msc)
  2. Expand "Sound, video and game controllers"
  3. Look for "Mcaster1 AudioPipe Virtual Audio Device"
  4. Right-click > Properties > Driver tab shows driver details

Check with PowerShell

# List audio devices via PowerShell:
Get-PnpDevice -Class AudioEndpoint | Where-Object { $_.FriendlyName -like "*Mcaster1*" }

# Check driver loading:
Get-WinEvent -LogName System -MaxEvents 50 | Where-Object { $_.Message -like "*AudioPipe*" }

Debugging & Troubleshooting

Driver won't load

SymptomCauseFix
pnputil succeeds but no audio device appears Test signing not active (forgot reboot) bcdedit | findstr testsigning — must say "Yes". Reboot if just enabled.
"A digitally signed driver is required" Test signing not enabled, or Secure Boot blocks it Enable test signing + reboot, or disable Secure Boot in UEFI
Status shows "NOT INSTALLED" after pnputil Driver added to store but not loaded Check pnputil /enum-drivers — if listed, try devcon install
BSOD on driver load Bug in kernel driver code Check minidump in C:\Windows\Minidump\. Use WinDbg to analyze.
"Could not find .inf driver package" Driver files not in expected location Copy .sys and .inf to build\Release\driver\

View kernel debug output

The driver uses DbgPrintEx for logging (prefixed with [AudioPipe]). Use DebugView (Sysinternals) or a kernel debugger to see output.

# Download DebugView from Sysinternals:
# https://learn.microsoft.com/en-us/sysinternals/downloads/debugview

# Run as Administrator, enable:
#   Capture > Capture Kernel (Ctrl+K)
# Filter for "[AudioPipe]" to see driver messages

# Or use WinDbg for full kernel debugging:
# 1. Enable kernel debugging: bcdedit /debug on
# 2. Attach WinDbg to the target (local or remote)
# 3. Set breakpoint: bp Mcaster1AudioPipe!DriverEntry

Driver log levels

The driver has three log levels controlled by PIPE_LOG_LEVEL in adapter.h:

LevelMacroOutput
0No logging
1 (default)PIPE_LOG_ERRErrors and warnings only
2PIPE_LOG_INFOInformational messages (startup, init, device creation)
3PIPE_LOG_DBGVerbose trace output (IO operations, stream state changes)

To change the log level, edit adapter.h:

#define PIPE_LOG_LEVEL 3  /* 0=off, 1=errors, 2=info, 3=verbose */

Analyzing crash dumps

# If the driver causes a BSOD, a minidump is written to C:\Windows\Minidump\

# Analyze with WinDbg:
windbg -z C:\Windows\Minidump\MMDDYY-NNNN.dmp

# In WinDbg:
!analyze -v
# This shows the faulting module, call stack, and bug check code

Driver Architecture

┌─────────────────────────────────────────────────────────────────┐ │ User Mode │ │ │ │ ┌──────────────────┐ Named Pipes ┌──────────────────┐ │ │ │ Mcaster1AudioPipe│ ◄────────────────── │ IPC Service │ │ │ │ Qt6 GUI (.exe) │ (future) │ (future .exe) │ │ │ └──────────────────┘ └────────┬─────────┘ │ │ │ IOCTLs │ ├────────────────────────────────────────────────────┼────────────┤ │ Kernel Mode │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────┐│ │ │ Mcaster1AudioPipe.sys (WDM PortCls Driver) ││ │ │ ││ │ │ ┌─────────────┐ ┌──────────────────┐ ││ │ │ │ adapter.cpp │ │ miniport.cpp │ ││ │ │ │ DriverEntry │ │ CMiniportWaveRT │ ││ │ │ │ AddDevice │ │ CMiniportTopology│ ││ │ │ │ StartDevice │ │ │ ││ │ │ └──────────────┘ └────────┬─────────┘ ││ │ │ │ ││ │ │ ┌──────────▼──────────┐ ││ │ │ │ stream.cpp │ ││ │ │ │ CMiniportWaveRT │ ││ │ │ │ Stream │ ││ │ │ │ │ ││ │ │ │ ┌─────────────────┐ │ ││ │ │ │ │ PipeRingBuffer │ │ ││ │ │ │ │ Win (SPSC, │ │ ││ │ │ │ │ 64B aligned) │ │ ││ │ │ │ └─────────────────┘ │ ││ │ │ └─────────────────────┘ ││ │ └─────────────────────────────────────────────────────────────┘│ │ │ │ PortCls.sys ◄──── KS Filter Graph ────▶ Audio Engine │ └─────────────────────────────────────────────────────────────────┘

Component responsibilities

ComponentRolemacOS Equivalent
adapter.cpp DriverEntry, PnP AddDevice/StartDevice, registers subdevices with PortCls ap_Initialize(), plugin factory
CMiniportWaveRT Audio streaming miniport — creates render/capture streams DoIOOperation (WriteMix/ReadInput)
CMiniportTopology Volume/mute control nodes Volume/mute HAL properties
CMiniportWaveRTStream Per-stream state, ring buffer IO, clock Per-device IO callbacks
PipeRingBufferWin Lock-free SPSC ring buffer (render → capture loopback) ring_buffer.h (ARM64 NEON aligned)

Path to Production Signing

For distribution, Windows kernel-mode drivers must be signed. There are two paths:

Option 1: EV Code Signing Certificate

  1. Purchase an EV (Extended Validation) code signing certificate from a CA (DigiCert, Sectigo, GlobalSign, etc.) — requires business entity verification
  2. Sign the driver with signtool
  3. Submit to the Windows Hardware Developer Center for attestation signing
  4. Microsoft co-signs the driver with a WHQL signature

Option 2: Attestation Signing (recommended for virtual drivers)

  1. Register at the Windows Hardware Developer Center with an EV certificate
  2. Create a driver submission
  3. Upload the unsigned driver package (.sys + .inf + .cat)
  4. Microsoft performs attestation signing (no HLK tests required for virtual devices)
  5. Download the signed driver package

Current Status Microsoft driver signing certificate: pending approval. Using test signing mode for development builds.

Self-signed test certificate (alternative to test signing mode)

# Create a self-signed test certificate:
makecert -r -pe -ss PrivateCertStore -n "CN=Mcaster1AudioPipe Test" Mcaster1Test.cer

# Sign the driver:
signtool sign /s PrivateCertStore /n "Mcaster1AudioPipe Test" /t http://timestamp.digicert.com Mcaster1AudioPipe.sys

# Install the test cert as a trusted root (elevated):
certutil -addstore root Mcaster1Test.cer
certutil -addstore trustedpublisher Mcaster1Test.cer

# This still requires test signing mode to be enabled

Uninstall & Cleanup

Remove the driver

# Run as Administrator:

# Option 1: From the GUI
# Audio Driver Management tab > click "Uninstall"

# Option 2: pnputil
pnputil /delete-driver Mcaster1AudioPipe.inf /uninstall /force

# Option 3: devcon
devcon remove Root\Mcaster1AudioPipe

Disable test signing (when done developing)

# Run as Administrator:
bcdedit /set testsigning off

# Reboot to apply — the "Test Mode" watermark will be removed
shutdown /r /t 0

Clean build artifacts

# Remove GUI build
rmdir /s /q build

# Remove driver build
rmdir /s /q src\driver\windows\Release
rmdir /s /q src\driver\windows\Debug