1 (edited by Hamcat 2026-04-06 19:22:56)

Topic: Changing WDM Devices friendly names

Hi,
Just got my first PCIE RME card, an old AIO but I'm already loving it.

The only thing that bothered me is that the 8 stereo outputs in windows were all called the same (RME HDSPe AIO), impossible to know which one is which without selecting it.

So I identified the wdm devices and made a script to rename the outputs : enjoy if that's bothering you too ! (elevated powershell)

Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;
using Microsoft.Win32;

public class RegOwner {
    [DllImport("advapi32.dll")] static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr tok);
    [DllImport("advapi32.dll")] static extern bool LookupPrivilegeValue(string host, string name, ref long luid);
    [DllImport("advapi32.dll")] static extern bool AdjustTokenPrivileges(IntPtr tok, bool dis, ref TP tp, int len, IntPtr p, IntPtr r);
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    struct TP { public int Count; public long Luid; public int Attr; }

    static void EnablePriv(string priv) {
        IntPtr htok = IntPtr.Zero;
        OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle, 0x28, ref htok);
        TP tp; tp.Count=1; tp.Luid=0; tp.Attr=2;
        LookupPrivilegeValue(null, priv, ref tp.Luid);
        AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
    }

    public static void TakeOwnerAndGrant(string subKey) {
        EnablePriv("SeTakeOwnershipPrivilege");
        EnablePriv("SeRestorePrivilege");
        var key = Registry.LocalMachine.OpenSubKey(subKey,
            RegistryKeyPermissionCheck.ReadWriteSubTree,
            RegistryRights.TakeOwnership);
        var acl = key.GetAccessControl(AccessControlSections.None);
        acl.SetOwner(WindowsIdentity.GetCurrent().User);
        key.SetAccessControl(acl);
        var acl2 = key.GetAccessControl();
        acl2.SetAccessRule(new RegistryAccessRule(
            WindowsIdentity.GetCurrent().User,
            RegistryRights.FullControl,
            InheritanceFlags.None, PropagationFlags.None,
            AccessControlType.Allow));
        key.SetAccessControl(acl2);
        key.Close();
    }
}
"@

$names = @{
    "i_hdspwave1_44"   = "AIO Analog 1-2"
    "i_hdspwave4_44"   = "AIO Phones"
    "i_hdspwave5_44"   = "AIO AES"
    "i_hdspwave6_44"   = "AIO SPDIF"
    "i_hdspwave7_44"   = "AIO ADAT 1-2"
    "i_hdspwave8_44"   = "AIO ADAT 3-4"
    "i_hdspwave9_44"   = "AIO ADAT 5-6"
    "i_hdspwavea_44"   = "AIO ADAT 7-8"
    "i_hdspwave7_44_8" = "AIO ADAT 8ch"
}

$render  = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render"
$nameKey = "{a45c254e-df1c-4efd-8020-67d146a850e0},2"
$wdmKey  = "{233164c8-1b2c-4c7d-bc68-b671687a2567},1"
$strip   = '^Microsoft\.PowerShell\.Core\\Registry::HKEY_LOCAL_MACHINE\\'

Get-ChildItem $render | ForEach-Object {
    $propsPath = "$($_.PSPath)\Properties"
    $props = Get-ItemProperty $propsPath -EA SilentlyContinue
    if ($props."{b3f8fa53-0004-438e-9003-51a46e139bfc},6" -notlike "*RME*") { return }

    $wdm = $props.$wdmKey
    $key = ([regex]::Match($wdm, 'i_hdspwave\w+')).Value
    if (-not $names.ContainsKey($key)) { return }

    $nativeSubKey = $propsPath -replace $strip, ''
    [RegOwner]::TakeOwnerAndGrant($nativeSubKey)
    Set-ItemProperty $propsPath -Name $nameKey -Value $names[$key]
    Write-Host "OK: $key -> $($names[$key])"
}

Restart-Service audiosrv

PS : don't know if AIO is the only card concerned, maybe RME could check on that for future updates ? tongue