SetupDi系APIでマイクやカメラのデバイスインスタンスパスを取る

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

最近、Windowsのドライバの情報を取得する方法を練習している。

※最後のヤツは、今回やったのと似てるが、自分で完全にやったことを忘れてた...

それらをもとに、簡単に、自分でコードを組んでみた。それの備忘。

作ったコード

マイクスピーカーやカメラの情報(フレンドリ名、デスクリプション、ハードウェアID、デバイスインスタンスパス)を取得して表示してみた。

#include <windows.h>
#include <setupapi.h>//SetupDi・・・関数
#include <iostream>
#include <cfgmgr32.h>// MAX_DEVICE_ID_LEN
#include <locale.h>

#pragma comment(lib, "setupapi.lib")

int main()
{
    _wsetlocale(LC_ALL, L"japanese");

    // 情報を取得したいクラス
    //auto className = std::wstring(L"AudioEndpoint");      // AutioEndpoint(マイクやスピーカー)
    auto className = std::wstring(L"Camera");               // Camera(カメラ)

    GUID cls;
    DWORD numClass = 0;

    if (SetupDiClassGuidsFromNameEx(className.c_str(), &cls, 1, &numClass, NULL, NULL) != TRUE)
    {
        std::wcout << L"エラー1" << std::endl;
        return -1;
    }

    //DIGCF_ALLCLASSESにすると、クラスGUIDを指定しても、全クラス分取れるっぽい?
    //auto devs = SetupDiGetClassDevsEx(&cls, NULL, NULL, DIGCF_ALLCLASSES, NULL, NULL, NULL);
    auto devs = SetupDiGetClassDevsEx(&cls, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);

    if (devs == INVALID_HANDLE_VALUE)
    {
        std::wcout << L"エラー2" << std::endl;
        return -1;
    }

    SP_DEVINFO_DATA devInfo;
    DWORD devIndex;
    devInfo.cbSize = sizeof(devInfo);

    // デバイスの数だけ(SetupDiEnumDeviceInfo()がFALSEになるまで)繰り返す
    for (devIndex = 0; SetupDiEnumDeviceInfo(devs, devIndex, &devInfo); devIndex++)
    {
        const DWORD size = 8192;
        DWORD dataType;
        WCHAR buffer[(size / sizeof(TCHAR)) + 2];
        DWORD reqSize;

        auto result = SetupDiGetDeviceRegistryProperty(devs, &devInfo, SPDRP_FRIENDLYNAME, &dataType, (LPBYTE)buffer, size, &reqSize);
        std::wcout << devIndex << L". フレンドリー名:" << (result ? buffer : L"エラー") << std::endl;

        result = SetupDiGetDeviceRegistryProperty(devs, &devInfo, SPDRP_DEVICEDESC, &dataType, (LPBYTE)buffer, size, &reqSize);
        std::wcout << L"  デスクリプション:" << (result ? buffer : L"エラー") << std::endl;

        result = SetupDiGetDeviceRegistryProperty(devs, &devInfo, SPDRP_HARDWAREID, &dataType, (LPBYTE)buffer, size, &reqSize);
        std::wcout << L"  ハードウェアID:" << (result ? buffer : L"エラー") << std::endl;

        TCHAR devID[MAX_DEVICE_ID_LEN];
        LPTSTR* hwIds = NULL;
        LPTSTR* compatIds = NULL;

        auto cr = CM_Get_Device_ID_Ex(devInfo.DevInst, devID, MAX_DEVICE_ID_LEN, 0, NULL);
        std::wcout << L"  デバイスインスタンスパス:" << (cr == CR_SUCCESS ? devID : L"エラー") << std::endl;
    }


    std::wcout << L"完了" << std::endl;
}

「デバイスインスタンスパス」が、そのドライバの一意のID(だと思う)ので、そいつを見たら、そのデバイスがあるかないかを見れそう。