Chromium Code Reviews| 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 { |
|
rvargas (doing something else)
2013/02/12 02:42:33
nit: class
|
| + 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 |