Windows NT系列でデバイス情報要素のGUIDと不透明ハンドル(Opaque Handle)を列挙するサンプルコードです。
SP_DEVINFO_DATA
構造体として取得する
最も単純な方法としてSP_DEVINFO_DATA
構造体のまま取得するサンプルコードです。追記:一部のSetup API(SetupDiGetDeviceRegistryPropertyW
等)はReserved
が0
のSP_DEVINFO_DATA
インスタンスを与えると不正なパラメーターで失敗するため、下記のタプルにするよりもこちらの方が良いかもしれません。
SetupDiDestroyDeviceInfoList
関数に与えるフラグにより列挙される情報を制限できます。ここではDIGCF_ALLCLASSES
を与えてすべての情報を列挙しています。なお、unique_SetupDiGetClassDevsW
関数はSetupDiDestroyDeviceInfoList
関数のHDEVINFO
型戻り値をunique_ptr
で扱うためのラッパー関数です。
#include <memory> #include <string> #include <numeric> #include <iostream> #pragma comment(lib, "SetupAPI.lib") #define STRICT #define NOMINMAX #include <Windows.h> #include <SetupAPI.h> using namespace std; using unique_devinfo_handle = unique_ptr<remove_pointer_t<HDEVINFO>, decltype(&::SetupDiDestroyDeviceInfoList)>; unique_devinfo_handle make_unique_devinfo_handle(HDEVINFO handle) noexcept; unique_devinfo_handle unique_SetupDiGetClassDevsW( const GUID* ClassGuid, LPCWSTR Enumerator, HWND hWndParent, DWORD Flags) noexcept; wstring guid_to_wstring(const GUID& guid); int main() { auto devinfo_handle = unique_SetupDiGetClassDevsW( nullptr, nullptr, nullptr, DIGCF_ALLCLASSES); wcout << L"ClassGuid, DevInst" << endl; for (DWORD i = 0; i < numeric_limits<DWORD>::max(); i++) { SP_DEVINFO_DATA data{ sizeof(data) }; if (!::SetupDiEnumDeviceInfo(devinfo_handle.get(), i, &data)) { break; } wcout << guid_to_wstring(data.ClassGuid) << L", " << data.DevInst << endl; } } unique_devinfo_handle make_unique_devinfo_handle(HDEVINFO handle) noexcept { return unique_devinfo_handle(handle, &::SetupDiDestroyDeviceInfoList); } unique_devinfo_handle unique_SetupDiGetClassDevsW( const GUID* ClassGuid, LPCWSTR Enumerator, HWND hWndParent, DWORD Flags) noexcept { return make_unique_devinfo_handle( ::SetupDiGetClassDevsW(ClassGuid, Enumerator, hWndParent, Flags)); } wstring guid_to_wstring(const GUID& guid) { LPWSTR s; if (FAILED(StringFromCLSID(guid, &s))) return {}; wstring str = s; CoTaskMemFree(s); return move(str); }
GUID ClassGuid
とDWORD DevInst
のタプルリストとして取得する
SP_DEVINFO_DATA
構造体からtuple<GUID, DWORD>
のリストを作成した後、構造化束縛によりGUID ClassGuid
とDWORD DevInst
を列挙するサンプルコードです。
#include <memory> #include <string> #include <numeric> #include <iostream> #include <tuple> #include <list> #pragma comment(lib, "SetupAPI.lib") #define STRICT #define NOMINMAX #include <Windows.h> #include <SetupAPI.h> using namespace std; using unique_devinfo_handle = unique_ptr<remove_pointer_t<HDEVINFO>, decltype(&::SetupDiDestroyDeviceInfoList)>; unique_devinfo_handle make_unique_devinfo_handle(HDEVINFO handle) noexcept; unique_devinfo_handle unique_SetupDiGetClassDevsW( const GUID* ClassGuid, LPCWSTR Enumerator, HWND hWndParent, DWORD Flags) noexcept; wstring guid_to_wstring(const GUID& guid); list<tuple<GUID, DWORD>> SetupDiEnumDeviceInfo_list(HDEVINFO DeviceInfoSet) noexcept { list<tuple<GUID, DWORD>> list; for (DWORD i = 0; i < numeric_limits<DWORD>::max(); i++) { SP_DEVINFO_DATA data{ sizeof(data) }; if (!::SetupDiEnumDeviceInfo(DeviceInfoSet, i, &data)) { break; } list.emplace_back(data.ClassGuid, data.DevInst); } return move(list); } int main() { auto devinfo_handle = unique_SetupDiGetClassDevsW( nullptr, nullptr, nullptr, DIGCF_ALLCLASSES); auto devinfos = SetupDiEnumDeviceInfo_list(devinfo_handle.get()); wcout << L"ClassGuid, DevInst" << endl; for (const auto& [ClassGuid, DevInst] : devinfos) { wcout << guid_to_wstring(ClassGuid) << L", " << DevInst << endl; } } unique_devinfo_handle make_unique_devinfo_handle(HDEVINFO handle) noexcept { return unique_devinfo_handle(handle, &::SetupDiDestroyDeviceInfoList); } unique_devinfo_handle unique_SetupDiGetClassDevsW( const GUID* ClassGuid, LPCWSTR Enumerator, HWND hWndParent, DWORD Flags) noexcept { return make_unique_devinfo_handle( ::SetupDiGetClassDevsW(ClassGuid, Enumerator, hWndParent, Flags)); } wstring guid_to_wstring(const GUID& guid) { LPWSTR s; if (FAILED(StringFromCLSID(guid, &s))) return {}; wstring str = s; CoTaskMemFree(s); return move(str); }