ネイティブWiFi APIを使って無線ネットワークのシグナル強度を列挙するコードです。いくつかのネイティブWiFi APIは独自メモリに確保した構造体に可変長配列を持ちますが、std::unique_ptr
とstd::span
を使えば可読性と安全性をまとめて担保できます。
シグナル品質とデシベルの変換はWLAN_ASSOCIATION_ATTRIBUTES
構造体のドキュメントを参照ください。
#include <span> #include <string> #include <memory> #include <optional> #define STRICT #include <Windows.h> #include <wlanapi.h> #pragma comment(lib, "wlanapi.lib") namespace win32 { struct wlanhandle_delete sealed { inline void operator() (HANDLE handle) const noexcept { ::WlanCloseHandle(handle, nullptr); } }; using unique_wlanhandle = std::unique_ptr<std::remove_pointer_t<HANDLE>, wlanhandle_delete>; unique_wlanhandle WlanOpenHandle( DWORD dwClientVersion, PDWORD pdwNegotiatedVersion = nullptr) noexcept { HANDLE handle; DWORD negotiatedVersion; if (::WlanOpenHandle(dwClientVersion, nullptr, &negotiatedVersion, &handle) != ERROR_SUCCESS) return {}; if (pdwNegotiatedVersion) *pdwNegotiatedVersion = negotiatedVersion; return unique_wlanhandle{handle}; } struct wlanmem_delete sealed { inline void operator() (LPVOID p) const noexcept { ::WlanFreeMemory(p); } }; template <typename T> using unique_wlanmem = std::unique_ptr<T, wlanmem_delete>; unique_wlanmem<WLAN_INTERFACE_INFO_LIST> WlanEnumInterfaces( HANDLE hClientHandle) { PWLAN_INTERFACE_INFO_LIST p; if (::WlanEnumInterfaces(hClientHandle, nullptr, &p) != ERROR_SUCCESS) return {}; return unique_wlanmem<WLAN_INTERFACE_INFO_LIST>{p}; } unique_wlanmem<WLAN_INTERFACE_CAPABILITY> WlanGetInterfaceCapability( HANDLE hClientHandle, CONST GUID* pInterfaceGuid) { PWLAN_INTERFACE_CAPABILITY p; if (::WlanGetInterfaceCapability(hClientHandle, pInterfaceGuid, nullptr, &p) != ERROR_SUCCESS) return {}; return unique_wlanmem<WLAN_INTERFACE_CAPABILITY>{p}; } unique_wlanmem<WLAN_PROFILE_INFO_LIST> WlanGetProfileList( HANDLE hClientHandle, CONST GUID* pInterfaceGuid) { PWLAN_PROFILE_INFO_LIST p; if (::WlanGetProfileList(hClientHandle, pInterfaceGuid, nullptr, &p) != ERROR_SUCCESS) return {}; return unique_wlanmem<WLAN_PROFILE_INFO_LIST>{p}; } std::wstring_view WLAN_INTERFACE_TYPE_ToString(WLAN_INTERFACE_TYPE x) noexcept { const wchar_t* names[] = { L"wlan_interface_type_emulated_802_11", L"wlan_interface_type_native_802_11", L"wlan_interface_type_invalid" }; if (0 <= x && x <= std::ssize(names)) return names[x]; return {}; } std::optional<WLAN_CONNECTION_ATTRIBUTES> WlanQueryInterfaceConnectionAttributes( HANDLE hClientHandle, const GUID* pInterfaceGuid) { DWORD size{}; PWLAN_CONNECTION_ATTRIBUTES pdata{}; auto ret = ::WlanQueryInterface(hClientHandle, pInterfaceGuid, WLAN_INTF_OPCODE::wlan_intf_opcode_current_connection, nullptr, &size, reinterpret_cast<void**>(&pdata), nullptr); if (ret != ERROR_SUCCESS) return {}; auto attrs = *pdata; ::WlanFreeMemory(pdata); return attrs; } } #include <iostream> int main() { std::wcout.imbue(std::locale("", std::locale::ctype)); auto handle{win32::WlanOpenHandle(WLAN_API_VERSION)}; if (!handle) return -1; auto interfaces{win32::WlanEnumInterfaces(handle.get())}; for (const auto& interfaceInfo : std::span(interfaces->InterfaceInfo, interfaces->dwNumberOfItems)) { auto capability{win32::WlanGetInterfaceCapability(handle.get(), &interfaceInfo.InterfaceGuid)}; auto connectAttrs{win32::WlanQueryInterfaceConnectionAttributes(handle.get(), &interfaceInfo.InterfaceGuid)}; auto interfaceType{capability ? win32::WLAN_INTERFACE_TYPE_ToString(capability->interfaceType) : L"(不明)"}; auto signalQuality{connectAttrs ? std::to_wstring(connectAttrs->wlanAssociationAttributes.wlanSignalQuality) : L"(不明)"}; std::wcout << interfaceInfo.strInterfaceDescription << std::endl; std::wcout << L" Interface Type: " << interfaceType << std::endl; std::wcout << L" Signal Quality: " << signalQuality << std::endl; std::wcout << L" Profiles:" << std::endl; auto profiles{win32::WlanGetProfileList(handle.get(), &interfaceInfo.InterfaceGuid)}; for (const auto& profileInfo : std::span(profiles->ProfileInfo, profiles->dwNumberOfItems)) { std::wcout << L" " << profileInfo.strProfileName << std::endl; } } return 0; }