| 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..62eabcc8d6a75f0157f5296057b8369ecff82175 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;
|
| }
|
|
|
| +WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
|
| + 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_LAYER_PROTOCOL_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_LAYER_PROTOCOL_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_LAYER_PROTOCOL_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_LAYER_PROTOCOL_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_LAYER_PROTOCOL_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_LAYER_PROTOCOL_ANCIENT;
|
| + case dot11_phy_type_dsss:
|
| + return WIFI_PHY_LAYER_PROTOCOL_B;
|
| + case dot11_phy_type_irbaseband:
|
| + return WIFI_PHY_LAYER_PROTOCOL_ANCIENT;
|
| + case dot11_phy_type_ofdm:
|
| + return WIFI_PHY_LAYER_PROTOCOL_A;
|
| + case dot11_phy_type_hrdsss:
|
| + return WIFI_PHY_LAYER_PROTOCOL_B;
|
| + case dot11_phy_type_erp:
|
| + return WIFI_PHY_LAYER_PROTOCOL_G;
|
| + case dot11_phy_type_ht:
|
| + return WIFI_PHY_LAYER_PROTOCOL_N;
|
| + default:
|
| + return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
|
| + }
|
| +}
|
| +
|
| } // namespace net
|
|
|