Index: net/base/net_util_win.cc |
diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc |
index 5b101aede6b8c4654f29aa487be27b63835d35aa..c3704f260dd2b778e9a63377654c58561637dfc3 100644 |
--- a/net/base/net_util_win.cc |
+++ b/net/base/net_util_win.cc |
@@ -5,16 +5,19 @@ |
#include "net/base/net_util.h" |
#include <iphlpapi.h> |
+#include <wlanapi.h> |
#include <algorithm> |
#include "base/file_path.h" |
+#include "base/lazy_instance.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/string_piece.h" |
#include "base/string_util.h" |
#include "base/sys_string_conversions.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/utf_string_conversions.h" |
+#include "base/win/scoped_handle.h" |
#include "googleurl/src/gurl.h" |
#include "net/base/escape.h" |
#include "net/base/ip_endpoint.h" |
@@ -127,4 +130,139 @@ bool GetNetworkList(NetworkInterfaceList* networks) { |
return true; |
} |
+WifiPhyMode GetWifiPhyMode() { |
+ struct WlanApi { |
+ typedef DWORD (WINAPI *WlanOpenHandleFunc)( |
+ DWORD, VOID*, DWORD*, HANDLE*); |
+ typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( |
+ HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST **); |
+ typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( |
+ HANDLE, const GUID *, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, |
+ WLAN_OPCODE_VALUE_TYPE*); |
+ typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); |
+ typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); |
+ |
+ WlanApi() : initialized(false) { |
+ // Use an absolute path to load the DLL to avoid DLL preloading attacks. |
+ static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; |
+ wchar_t path[MAX_PATH] = {0}; |
+ ExpandEnvironmentStrings(kDLL, path, arraysize(path)); |
+ module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); |
+ if (!module) |
+ return; |
+ |
+ open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( |
+ ::GetProcAddress(module, "WlanOpenHandle")); |
+ enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( |
+ ::GetProcAddress(module, "WlanEnumInterfaces")); |
+ query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( |
+ ::GetProcAddress(module, "WlanQueryInterface")); |
+ free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( |
+ ::GetProcAddress(module, "WlanFreeMemory")); |
+ close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( |
+ ::GetProcAddress(module, "WlanCloseHandle")); |
+ initialized = open_handle_func && enum_interfaces_func && |
+ query_interface_func && free_memory_func && |
+ close_handle_func; |
+ } |
+ |
+ HMODULE module; |
+ WlanOpenHandleFunc open_handle_func; |
+ WlanEnumInterfacesFunc enum_interfaces_func; |
+ WlanQueryInterfaceFunc query_interface_func; |
+ WlanFreeMemoryFunc free_memory_func; |
+ WlanCloseHandleFunc close_handle_func; |
+ bool initialized; |
+ }; |
+ |
+ static base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+ struct WlanApiHandleTraits { |
+ typedef HANDLE Handle; |
+ |
+ static bool CloseHandle(HANDLE handle) { |
+ return lazy_wlanapi.Get().close_handle_func(handle, NULL) == |
+ ERROR_SUCCESS; |
+ } |
+ static bool IsHandleValid(HANDLE handle) { |
+ return base::win::HandleTraits::IsHandleValid(handle); |
+ } |
+ static HANDLE NullHandle() { |
+ return base::win::HandleTraits::NullHandle(); |
+ } |
+ }; |
+ |
+ typedef base::win::GenericScopedHandle<WlanApiHandleTraits, |
+ base::win::VerifierTraits> WlanHandle; |
+ |
+ struct WlanApiDeleter { |
+ inline void operator()(void* ptr) const { |
+ lazy_wlanapi.Get().free_memory_func(ptr); |
+ } |
+ }; |
+ |
+ const WlanApi& wlanapi = lazy_wlanapi.Get(); |
+ if (!wlanapi.initialized) |
+ return WIFI_PHY_MODE_NONE; |
+ |
+ WlanHandle client; |
+ DWORD cur_version = 0; |
+ const DWORD kMaxClientVersion = 2; |
+ DWORD result = wlanapi.open_handle_func(kMaxClientVersion, NULL, &cur_version, |
+ client.Receive()); |
+ if (result != ERROR_SUCCESS) |
+ return WIFI_PHY_MODE_NONE; |
+ |
+ WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; |
+ result = wlanapi.enum_interfaces_func(client, NULL, &interface_list_ptr); |
+ if (result != ERROR_SUCCESS) |
+ return WIFI_PHY_MODE_NONE; |
+ scoped_ptr<WLAN_INTERFACE_INFO_LIST, WlanApiDeleter> interface_list( |
+ interface_list_ptr); |
+ |
+ // Assume at most one connected wifi interface. |
+ WLAN_INTERFACE_INFO* info = NULL; |
+ for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { |
+ if (interface_list->InterfaceInfo[i].isState == |
+ wlan_interface_state_connected) { |
+ info = &interface_list->InterfaceInfo[i]; |
+ break; |
+ } |
+ } |
+ |
+ if (info == NULL) |
+ return WIFI_PHY_MODE_NONE; |
+ |
+ WLAN_CONNECTION_ATTRIBUTES* conn_info_ptr; |
+ DWORD conn_info_size = 0; |
+ WLAN_OPCODE_VALUE_TYPE op_code; |
+ result = wlanapi.query_interface_func( |
+ client, &info->InterfaceGuid, wlan_intf_opcode_current_connection, NULL, |
+ &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr), &op_code); |
+ if (result != ERROR_SUCCESS) |
+ return WIFI_PHY_MODE_UNKNOWN; |
+ scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, WlanApiDeleter> conn_info( |
+ conn_info_ptr); |
+ |
+ switch (conn_info->wlanAssociationAttributes.dot11PhyType) { |
+ case dot11_phy_type_fhss: |
+ return WIFI_PHY_MODE_ANCIENT; |
+ case dot11_phy_type_dsss: |
+ return WIFI_PHY_MODE_B; |
+ case dot11_phy_type_irbaseband: |
+ return WIFI_PHY_MODE_ANCIENT; |
+ case dot11_phy_type_ofdm: |
+ return WIFI_PHY_MODE_A; |
+ case dot11_phy_type_hrdsss: |
+ return WIFI_PHY_MODE_B; |
+ case dot11_phy_type_erp: |
+ return WIFI_PHY_MODE_G; |
+ case dot11_phy_type_ht: |
+ return WIFI_PHY_MODE_N; |
+ default: |
+ return WIFI_PHY_MODE_UNKNOWN; |
+ } |
+} |
+ |
} // namespace net |