From 514efab8ebbc28467d2c8b0b9dd4a6e71b11de4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 18 Aug 2026 16:41:11 +0800 Subject: [PATCH] Wifi (Windows): adds channel width and device driver detection --- src/common/windows/nt.h | 2 +- src/detection/wifi/wifi_windows.c | 149 +++++++++++++++++++++++++----- 2 files changed, 126 insertions(+), 25 deletions(-) diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index 730a75ba8..4a61b8226 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -169,7 +169,7 @@ NTSTATUS NTAPI NtQuerySystemEnvironmentValueEx( ); NTSTATUS NTAPI RtlGUIDFromString(IN PCUNICODE_STRING GuidString, OUT GUID* Guid); -NTSTATUS NTAPI RtlStringFromGUIDEx(IN GUID* Guid, OUT PCUNICODE_STRING GuidString, _In_ BOOLEAN AllocateGuidString); +NTSTATUS NTAPI RtlStringFromGUIDEx(IN const GUID* Guid, OUT PUNICODE_STRING GuidString, IN BOOLEAN AllocateGuidString); typedef struct _SYSTEM_SECUREBOOT_INFORMATION { BOOLEAN SecureBootEnabled; diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 8e900ad42..51adcdc33 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -1,45 +1,118 @@ #include "wifi.h" #include "common/library.h" #include "common/windows/unicode.h" +#include "common/windows/registry.h" #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch" - static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result) { switch (state) { case wlan_interface_state_not_ready: - ffStrbufAppendS(result, "Not ready"); + ffStrbufSetStatic(result, "Not ready"); break; case wlan_interface_state_connected: - ffStrbufAppendS(result, "Connected"); + ffStrbufSetStatic(result, "Connected"); break; case wlan_interface_state_ad_hoc_network_formed: - ffStrbufAppendS(result, "Ad hoc network formed"); + ffStrbufSetStatic(result, "Ad hoc network formed"); break; case wlan_interface_state_disconnecting: - ffStrbufAppendS(result, "Disconnecting"); + ffStrbufSetStatic(result, "Disconnecting"); break; case wlan_interface_state_disconnected: - ffStrbufAppendS(result, "Disconnected"); + ffStrbufSetStatic(result, "Disconnected"); break; case wlan_interface_state_associating: - ffStrbufAppendS(result, "Associating"); + ffStrbufSetStatic(result, "Associating"); break; case wlan_interface_state_discovering: - ffStrbufAppendS(result, "Discovering"); + ffStrbufSetStatic(result, "Discovering"); break; case wlan_interface_state_authenticating: - ffStrbufAppendS(result, "Authenticating"); + ffStrbufSetStatic(result, "Authenticating"); break; default: - ffStrbufAppendS(result, "Unknown"); + ffStrbufSetStatic(result, "Unknown"); break; } } +typedef struct _WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO { + UCHAR ucLinkID; + ULONG ulChannelCenterFrequencyMhz; + ULONG ulBandwidth; + LONG lRssi; + WLAN_RATE_SET wlanRateSet; +} WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO, *PWLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO; + +typedef struct _WLAN_REALTIME_CONNECTION_QUALITY { + DOT11_PHY_TYPE dot11PhyType; + ULONG ulLinkQuality; + ULONG ulRxRate; + ULONG ulTxRate; + BOOL bIsMLOConnection; + ULONG ulNumLinks; + // Array of size ulNumLinks + WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO linksInfo[]; +} WLAN_REALTIME_CONNECTION_QUALITY, *PWLAN_REALTIME_CONNECTION_QUALITY; + +enum { wlan_intf_opcode_realtime_connection_quality = 19 }; + +#define WIFI_DRIVER_REG_PATH L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +static bool detectWifiDriver(const GUID* interfaceGuid, FFstrbuf* driver) { + char interfaceGuidA[64]; + snprintf(interfaceGuidA, sizeof(interfaceGuidA), + "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + (unsigned) interfaceGuid->Data1, + (unsigned) interfaceGuid->Data2, + (unsigned) interfaceGuid->Data3, + (unsigned) interfaceGuid->Data4[0], (unsigned) interfaceGuid->Data4[1], + (unsigned) interfaceGuid->Data4[2], (unsigned) interfaceGuid->Data4[3], + (unsigned) interfaceGuid->Data4[4], (unsigned) interfaceGuid->Data4[5], + (unsigned) interfaceGuid->Data4[6], (unsigned) interfaceGuid->Data4[7]); + + FF_AUTO_CLOSE_FD HANDLE hClassKey = nullptr; + if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, WIFI_DRIVER_REG_PATH, &hClassKey, nullptr)) { + return false; + } + + wchar_t subKeyW[16]; + + for (uint32_t i = 0;; ++i) { + _snwprintf(subKeyW, ARRAY_SIZE(subKeyW), L"%04u", i); + + FF_AUTO_CLOSE_FD HANDLE hDeviceKey = nullptr; + if (!ffRegOpenSubkeyForRead(hClassKey, subKeyW, &hDeviceKey, nullptr)) { + return false; + } + + FF_STRBUF_AUTO_DESTROY netCfgInstanceId = ffStrbufCreate(); + if (!ffRegReadStrbuf(hDeviceKey, L"NetCfgInstanceId", &netCfgInstanceId, nullptr)) { + continue; + } + + if (!ffStrbufEqualS(&netCfgInstanceId, interfaceGuidA)) { + continue; + } + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffRegReadStrbuf(hDeviceKey, L"ProviderName", &buffer, nullptr)) { + ffStrbufSet(driver, &buffer); + } + + if (ffRegReadStrbuf(hDeviceKey, L"DriverVersion", &buffer, nullptr)) { + if (driver->length) { + ffStrbufAppendC(driver, ' '); + } + ffStrbufAppend(driver, &buffer); + } + + return true; + } +} + const char* ffDetectWifi(FFlist* result) { FF_LIBRARY_LOAD_MESSAGE(wlanapi, "wlanapi" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle) @@ -54,7 +127,7 @@ const char* ffDetectWifi(FFlist* result) { WLAN_INTERFACE_INFO_LIST* ifList = nullptr; const char* error = nullptr; - if (ffWlanOpenHandle(2, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) { + if (ffWlanOpenHandle(2 /*maxClientVersion*/, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) { error = "WlanOpenHandle() failed"; goto exit; } @@ -70,6 +143,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitWS(&item->inf.description, ifInfo->strInterfaceDescription); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -79,8 +153,10 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; + detectWifiDriver(&ifInfo->InterfaceGuid, &item->inf.driver); convertIfStateToString(ifInfo->isState, &item->inf.status); if (ifInfo->isState != wlan_interface_state_connected) { @@ -200,17 +276,44 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufAppendS(&item->conn.security, "Insecure"); } - WLAN_BSS_LIST* bssList = nullptr; - if (ffWlanGetNetworkBssList(hClient, + WLAN_REALTIME_CONNECTION_QUALITY* connectionQuality = nullptr; + bufSize = 0; + if (ffWlanQueryInterface(hClient, &ifInfo->InterfaceGuid, - &connInfo->wlanAssociationAttributes.dot11Ssid, - connInfo->wlanAssociationAttributes.dot11BssType, - connInfo->wlanSecurityAttributes.bSecurityEnabled, + wlan_intf_opcode_realtime_connection_quality, nullptr, - &bssList) == ERROR_SUCCESS && - bssList->dwNumberOfItems > 0) { - item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000); - ffWlanFreeMemory(bssList); + &bufSize, + (PVOID*) &connectionQuality, + &opCode) == ERROR_SUCCESS) { + const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* bestLink = nullptr; + for (ULONG linkIndex = 0; linkIndex < connectionQuality->ulNumLinks; ++linkIndex) { + const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* link = &connectionQuality->linksInfo[linkIndex]; + if (!bestLink || link->lRssi > bestLink->lRssi) { + bestLink = link; + } + } + if (bestLink) { + item->conn.channelWidth = (uint16_t) bestLink->ulBandwidth; + item->conn.frequency = (uint16_t) bestLink->ulChannelCenterFrequencyMhz; + } + } + if (connectionQuality) { + ffWlanFreeMemory(connectionQuality); + } + + if (item->conn.frequency == 0) { + WLAN_BSS_LIST* bssList = nullptr; + if (ffWlanGetNetworkBssList(hClient, + &ifInfo->InterfaceGuid, + &connInfo->wlanAssociationAttributes.dot11Ssid, + connInfo->wlanAssociationAttributes.dot11BssType, + connInfo->wlanSecurityAttributes.bSecurityEnabled, + nullptr, + &bssList) == ERROR_SUCCESS && + bssList->dwNumberOfItems > 0) { + item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000); + ffWlanFreeMemory(bssList); + } } ffWlanFreeMemory(connInfo); @@ -238,5 +341,3 @@ exit: } return error; } - -#pragma GCC diagnostic pop