15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also support a limited version of the WLAN API. See 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://msdn.microsoft.com/en-us/library/bb204766.aspx. The WLAN API uses 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// wlanapi.h, which is not part of the SDK used by Gears, so is replicated 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// locally using data from the MSDN. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows XP from Service Pack 2 onwards supports the Wireless Zero 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Configuration (WZC) programming interface. See 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The MSDN recommends that one use the WLAN API where available, and WZC 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// However, it seems that WZC fails for some wireless cards. Also, WLAN seems 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/wifi_data_provider_win.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winioctl.h> 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wlanapi.h> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/wifi_data_provider_common.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/wifi_data_provider_common_win.h" 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/browser/geolocation/wifi_data_provider_manager.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Taken from ndis.h for WinCE. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The limits on the size of the buffer used for the OID query. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInitialBufferSize = 2 << 12; // Good for about 50 APs. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaximumBufferSize = 2 << 20; // 2MB 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Length for generic string buffers passed to Windows APIs. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStringLength = 512; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The time periods, in milliseconds, between successive polls of the wifi data. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultPollingInterval = 10000; // 10s 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNoChangePollingInterval = 120000; // 2 mins 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTwoNoChangePollingInterval = 600000; // 10 mins 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WlanOpenHandle 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef DWORD (WINAPI* WlanOpenHandleFunction)(DWORD dwClientVersion, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PVOID pReserved, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PDWORD pdwNegotiatedVersion, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PHANDLE phClientHandle); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WlanEnumInterfaces 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef DWORD (WINAPI* WlanEnumInterfacesFunction)( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hClientHandle, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PVOID pReserved, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PWLAN_INTERFACE_INFO_LIST* ppInterfaceList); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WlanGetNetworkBssList 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef DWORD (WINAPI* WlanGetNetworkBssListFunction)( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hClientHandle, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GUID* pInterfaceGuid, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PDOT11_SSID pDot11Ssid, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOT11_BSS_TYPE dot11BssType, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bSecurityEnabled, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PVOID pReserved, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PWLAN_BSS_LIST* ppWlanBssList 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WlanFreeMemory 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef VOID (WINAPI* WlanFreeMemoryFunction)(PVOID pMemory); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WlanCloseHandle 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef DWORD (WINAPI* WlanCloseHandleFunction)(HANDLE hClientHandle, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PVOID pReserved); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Local classes and functions 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WindowsWlanApi : public WifiDataProviderCommon::WlanApiInterface { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~WindowsWlanApi(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Factory function. Will return NULL if this API is unavailable. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static WindowsWlanApi* Create(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WlanApiInterface 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Takes ownership of the library handle. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit WindowsWlanApi(HINSTANCE library); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loads the required functions from the DLL. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetWLANFunctions(HINSTANCE wlan_library); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetInterfaceDataWLAN(HANDLE wlan_handle, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GUID& interface_id, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WifiData::AccessPointDataSet* data); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Logs number of detected wlan interfaces. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void LogWlanInterfaceCount(int count); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle to the wlanapi.dll library. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HINSTANCE library_; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function pointers for WLAN 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanOpenHandleFunction WlanOpenHandle_function_; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanEnumInterfacesFunction WlanEnumInterfaces_function_; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanFreeMemoryFunction WlanFreeMemory_function_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanCloseHandleFunction WlanCloseHandle_function_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~WindowsNdisApi(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static WindowsNdisApi* Create(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WlanApiInterface 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool GetInterfacesNDIS( 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<base::string16>* interface_service_names_out); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Swaps in content of the vector passed 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) explicit WindowsNdisApi(std::vector<base::string16>* interface_service_names); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool GetInterfaceDataNDIS(HANDLE adapter_handle, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WifiData::AccessPointDataSet* data); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NDIS variables. 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<base::string16> interface_service_names_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remembers scan result buffer size across calls. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int oid_buffer_size_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts data for an access point and converts to Gears format. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AccessPointData* access_point_data); 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool UndefineDosDevice(const base::string16& device_name); 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool DefineDosDeviceIfNotExists(const base::string16& device_name); 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)HANDLE GetFileHandle(const base::string16& device_name); 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Makes the OID query and returns a Windows API error code. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PerformQuery(HANDLE adapter_handle, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* buffer, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD buffer_size, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* bytes_out); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ResizeBuffer(int requested_size, 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<BYTE, base::FreeDeleter>* buffer); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the system directory and appends a trailing slash if not already 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// present. 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool GetSystemDirectory(base::string16* path); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() { 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return new WifiDataProviderWin(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)WifiDataProviderWin::WifiDataProviderWin() { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)WifiDataProviderWin::~WifiDataProviderWin() { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)WifiDataProviderCommon::WlanApiInterface* WifiDataProviderWin::NewWlanApi() { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the WLAN interface if we're on Vista and if it's available. Otherwise, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use NDIS. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanApiInterface* api = WindowsWlanApi::Create(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (api) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return api; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WindowsNdisApi::Create(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)WifiPollingPolicy* WifiDataProviderWin::NewPollingPolicy() { 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return new GenericWifiPollingPolicy<kDefaultPollingInterval, 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) kNoChangePollingInterval, 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) kTwoNoChangePollingInterval, 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) kNoWifiPollingIntervalMilliseconds>; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Local classes and functions 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WindowsWlanApi 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsWlanApi::WindowsWlanApi(HINSTANCE library) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : library_(library) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWLANFunctions(library_); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsWlanApi::~WindowsWlanApi() { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FreeLibrary(library_); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsWlanApi* WindowsWlanApi::Create() { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_VISTA) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use an absolute path to load the DLL to avoid DLL preloading attacks. 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 system_directory; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetSystemDirectory(&system_directory)) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!system_directory.empty()); 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 dll_path = system_directory + L"wlanapi.dll"; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HINSTANCE library = LoadLibraryEx(dll_path.c_str(), 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOAD_WITH_ALTERED_SEARCH_PATH); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!library) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new WindowsWlanApi(library); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowsWlanApi::GetWLANFunctions(HINSTANCE wlan_library) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(wlan_library); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>( 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(wlan_library, "WlanOpenHandle")); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanEnumInterfaces_function_ = reinterpret_cast<WlanEnumInterfacesFunction>( 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(wlan_library, "WlanEnumInterfaces")); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanGetNetworkBssList_function_ = 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<WlanGetNetworkBssListFunction>( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(wlan_library, "WlanGetNetworkBssList")); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanFreeMemory_function_ = reinterpret_cast<WlanFreeMemoryFunction>( 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(wlan_library, "WlanFreeMemory")); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanCloseHandle_function_ = reinterpret_cast<WlanCloseHandleFunction>( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(wlan_library, "WlanCloseHandle")); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(WlanOpenHandle_function_ && 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanEnumInterfaces_function_ && 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanGetNetworkBssList_function_ && 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanFreeMemory_function_ && 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WlanCloseHandle_function_); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowsWlanApi::LogWlanInterfaceCount(int count) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS( 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Net.Wifi.InterfaceCount", 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5, 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowsWlanApi::GetAccessPointData( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WifiData::AccessPointDataSet* data) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the handle to the WLAN API. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD negotiated_version; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE wlan_handle = NULL; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We could be executing on either Windows XP or Windows Vista, so use the 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lower version of the client WLAN API. It seems that the negotiated version 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is the Vista version irrespective of what we pass! 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kXpWlanClientVersion = 1; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*WlanOpenHandle_function_)(kXpWlanClientVersion, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &negotiated_version, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wlan_handle) != ERROR_SUCCESS) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWlanInterfaceCount(0); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(wlan_handle); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the list of interfaces. WlanEnumInterfaces allocates interface_list. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WLAN_INTERFACE_INFO_LIST* interface_list = NULL; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*WlanEnumInterfaces_function_)(wlan_handle, NULL, &interface_list) != 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SUCCESS) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWlanInterfaceCount(0); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(interface_list); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogWlanInterfaceCount(interface_list->dwNumberOfItems); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Go through the list of interfaces and get the data for each. 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < static_cast<int>(interface_list->dwNumberOfItems); ++i) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip any interface that is midway through association; the 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WlanGetNetworkBssList function call is known to hang indefinitely 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when it's in this state. http://crbug.com/39300 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (interface_list->InterfaceInfo[i].isState == 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wlan_interface_state_associating) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Skipping wifi scan on adapter " << i << " (" 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << interface_list->InterfaceInfo[i].strInterfaceDescription 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ") in 'associating' state. Repeated occurrences " 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "indicates a non-responding adapter."; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetInterfaceDataWLAN(wlan_handle, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface_list->InterfaceInfo[i].InterfaceGuid, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free interface_list. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*WlanFreeMemory_function_)(interface_list); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the handle. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*WlanCloseHandle_function_)(wlan_handle, NULL) != ERROR_SUCCESS) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Appends the data for a single interface to the data vector. Returns the 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number of access points found, or -1 on error. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WindowsWlanApi::GetInterfaceDataWLAN( 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HANDLE wlan_handle, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GUID& interface_id, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WifiData::AccessPointDataSet* data) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks start_time = base::TimeTicks::Now(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WlanGetNetworkBssList allocates bss_list. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WLAN_BSS_LIST* bss_list = NULL; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*WlanGetNetworkBssList_function_)(wlan_handle, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &interface_id, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // Use all SSIDs. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dot11_BSS_type_any, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, // bSecurityEnabled - unused 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // reserved 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bss_list) != ERROR_SUCCESS) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // According to http://www.attnetclient.com/kb/questions.php?questionid=75 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WlanGetNetworkBssList can sometimes return success, but leave the bss 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list as NULL. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bss_list) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta duration = base::TimeTicks::Now() - start_time; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_TIMES( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Net.Wifi.ScanLatency", 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) duration, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(1), 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMinutes(1), 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int found = 0; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < static_cast<int>(bss_list->dwNumberOfItems); ++i) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AccessPointData access_point_data; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetNetworkData(bss_list->wlanBssEntries[i], &access_point_data)) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++found; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->insert(access_point_data); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*WlanFreeMemory_function_)(bss_list); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return found; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WindowsNdisApi 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsNdisApi::WindowsNdisApi( 364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<base::string16>* interface_service_names) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : oid_buffer_size_(kInitialBufferSize) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!interface_service_names->empty()); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface_service_names_.swap(*interface_service_names); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsNdisApi::~WindowsNdisApi() { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowsNdisApi* WindowsNdisApi::Create() { 374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<base::string16> interface_service_names; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetInterfacesNDIS(&interface_service_names)) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new WindowsNdisApi(&interface_service_names); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int interfaces_failed = 0; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int interfaces_succeeded = 0; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, check that we have a DOS device for this adapter. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the handle to the device. This will fail if the named device is not 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valid. 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adapter_handle == INVALID_HANDLE_VALUE) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the data. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetInterfaceDataNDIS(adapter_handle, data)) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++interfaces_succeeded; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++interfaces_failed; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clean up. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(adapter_handle); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UndefineDosDevice(interface_service_names_[i]); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return true if at least one interface succeeded, or at the very least none 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // failed. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return interfaces_succeeded > 0 || interfaces_failed == 0; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowsNdisApi::GetInterfacesNDIS( 417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<base::string16>* interface_service_names_out) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY network_cards_key = NULL; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegOpenKeyEx( 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY_LOCAL_MACHINE, 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_READ, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &network_cards_key) != ERROR_SUCCESS) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(network_cards_key); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; ; ++i) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TCHAR name[kStringLength]; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD name_size = kStringLength; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME time; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegEnumKeyEx(network_cards_key, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name, 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &name_size, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &time) != ERROR_SUCCESS) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY hardware_key = NULL; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegOpenKeyEx(network_cards_key, name, 0, KEY_READ, &hardware_key) != 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SUCCESS) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(hardware_key); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TCHAR service_name[kStringLength]; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD service_name_size = kStringLength; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD type = 0; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegQueryValueEx(hardware_key, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"ServiceName", 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<LPBYTE>(service_name), 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &service_name_size) == ERROR_SUCCESS) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface_service_names_out->push_back(service_name); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegCloseKey(hardware_key); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegCloseKey(network_cards_key); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowsNdisApi::GetInterfaceDataNDIS(HANDLE adapter_handle, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WifiData::AccessPointDataSet* data) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<BYTE, base::FreeDeleter> buffer( 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<BYTE*>(malloc(oid_buffer_size_))); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer == NULL) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD bytes_out; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_out = 0; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = PerformQuery(adapter_handle, buffer.get(), 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oid_buffer_size_, &bytes_out); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERROR_GEN_FAILURE || // Returned by some Intel cards. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result == ERROR_INSUFFICIENT_BUFFER || 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result == ERROR_MORE_DATA || 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result == NDIS_STATUS_INVALID_LENGTH || 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result == NDIS_STATUS_BUFFER_TOO_SHORT) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The buffer we supplied is too small, so increase it. bytes_out should 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // provide the required buffer size, but this is not always the case. 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_out > static_cast<DWORD>(oid_buffer_size_)) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oid_buffer_size_ = bytes_out; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oid_buffer_size_ *= 2; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ResizeBuffer(oid_buffer_size_, &buffer)) { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oid_buffer_size_ = kInitialBufferSize; // Reset for next time. 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The buffer is not too small. 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffer.get()); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERROR_SUCCESS) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NDIS_802_11_BSSID_LIST* bssid_list = 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer.get()); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDataFromBssIdList(*bssid_list, oid_buffer_size_, data); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AccessPointData* access_point_data) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently we get only MAC address, signal strength and SSID. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(access_point_data); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_point_data->mac_address = MacAddressAsString16(bss_entry.dot11Bssid); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_point_data->radio_signal_strength = bss_entry.lRssi; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bss_entry.dot11Ssid.ucSSID is not null-terminated. 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID), 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength), 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &access_point_data->ssid); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(steveblock): Is it possible to get the following? 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // access_point_data->signal_to_noise 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // access_point_data->age 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // access_point_data->channel 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool UndefineDosDevice(const base::string16& device_name) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We remove only the mapping we use, that is \Device\<device_name>. 537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 target_path = L"\\Device\\" + device_name; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DefineDosDevice( 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_name.c_str(), 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path.c_str()) == TRUE; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 544a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool DefineDosDeviceIfNotExists(const base::string16& device_name) { 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We create a DOS device name for the device at \Device\<device_name>. 546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 target_path = L"\\Device\\" + device_name; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TCHAR target[kStringLength]; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path.compare(target) == 0) { 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Device already exists. 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetLastError() != ERROR_FILE_NOT_FOUND) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DefineDosDevice(DDD_RAW_TARGET_PATH, 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_name.c_str(), 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path.c_str())) { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the device is really there. 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path.compare(target) == 0; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 570a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)HANDLE GetFileHandle(const base::string16& device_name) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We access a device with DOS path \Device\<device_name> at 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // \\.\<device_name>. 573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 formatted_device_name = L"\\\\.\\" + device_name; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateFile(formatted_device_name.c_str(), 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GENERIC_READ, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // security attributes 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OPEN_EXISTING, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // flags and attributes 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INVALID_HANDLE_VALUE); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PerformQuery(HANDLE adapter_handle, 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BYTE* buffer, 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD buffer_size, 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* bytes_out) { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD oid = OID_802_11_BSSID_LIST; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DeviceIoControl(adapter_handle, 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOCTL_NDIS_QUERY_GLOBAL_STATS, 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &oid, 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(oid), 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer, 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_out, 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL)) { 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetLastError(); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ResizeBuffer(int requested_size, 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<BYTE, base::FreeDeleter>* buffer) { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(requested_size, 0); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffer); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (requested_size > kMaximumBufferSize) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->reset(); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->reset(reinterpret_cast<BYTE*>( 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) realloc(buffer->release(), requested_size))); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer != NULL; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool GetSystemDirectory(base::string16* path) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return value includes terminating NULL. 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_size = ::GetSystemDirectory(NULL, 0); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_size == 0) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::char16[]> buffer(new base::char16[buffer_size]); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return value excludes terminating NULL. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int characters_written = ::GetSystemDirectory(buffer.get(), buffer_size); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (characters_written == 0) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(buffer_size - 1, characters_written); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path->assign(buffer.get(), characters_written); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*path->rbegin() != L'\\') { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path->append(L"\\"); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(L'\\', *path->rbegin()); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 643