Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/browser/geolocation/wifi_data_provider_win.cc

Issue 543174: Update Gears wifi data providers to Chrome style & APIs.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2008, Google Inc. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // 2 // Use of this source code is governed by a BSD-style license that can be
3 // Redistribution and use in source and binary forms, with or without 3 // found in the LICENSE file.
4 // modification, are permitted provided that the following conditions are met: 4
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26 // Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See 5 // Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See
27 // http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP 6 // http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP
28 // Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix) 7 // Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix)
29 // also support a limited version of the WLAN API. See 8 // also support a limited version of the WLAN API. See
30 // http://msdn.microsoft.com/en-us/library/bb204766.aspx. The WLAN API uses 9 // http://msdn.microsoft.com/en-us/library/bb204766.aspx. The WLAN API uses
31 // wlanapi.h, which is not part of the SDK used by Gears, so is replicated 10 // wlanapi.h, which is not part of the SDK used by Gears, so is replicated
32 // locally using data from the MSDN. 11 // locally using data from the MSDN.
33 // 12 //
34 // Windows XP from Service Pack 2 onwards supports the Wireless Zero 13 // Windows XP from Service Pack 2 onwards supports the Wireless Zero
35 // Configuration (WZC) programming interface. See 14 // Configuration (WZC) programming interface. See
36 // http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx. 15 // http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx.
37 // 16 //
38 // The MSDN recommends that one use the WLAN API where available, and WZC 17 // The MSDN recommends that one use the WLAN API where available, and WZC
39 // otherwise. 18 // otherwise.
40 // 19 //
41 // However, it seems that WZC fails for some wireless cards. Also, WLAN seems 20 // However, it seems that WZC fails for some wireless cards. Also, WLAN seems
42 // not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly 21 // not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly
43 // otherwise. 22 // otherwise.
44 23
45 // TODO(cprince): remove platform-specific #ifdef guards when OS-specific 24 #include "chrome/browser/geolocation/wifi_data_provider_win.h"
46 // sources (e.g. WIN32_CPPSRCS) are implemented
47 #if defined(WIN32) && !defined(OS_WINCE)
48
49 #include "gears/geolocation/wifi_data_provider_win32.h"
50 25
51 #include <windows.h> 26 #include <windows.h>
52 #include <ntddndis.h> // For IOCTL_NDIS_QUERY_GLOBAL_STATS 27 #include <winioctl.h>
53 #include "gears/base/common/string_utils.h" 28 #include <wlanapi.h>
54 #include "gears/base/common/vista_utils.h" 29 #include "base/utf_string_conversions.h"
55 #include "gears/geolocation/wifi_data_provider_common.h" 30 #include "chrome/browser/geolocation/wifi_data_provider_common.h"
56 #include "gears/geolocation/wifi_data_provider_windows_common.h" 31 #include "chrome/browser/geolocation/wifi_data_provider_common_win.h"
32
33 #ifdef _MSC_VER
34 #pragma warning(disable:4355) // 'this' : used in base member initializer list
35 #endif
57 36
58 // Taken from ndis.h for WinCE. 37 // Taken from ndis.h for WinCE.
59 #define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) 38 #define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L)
60 #define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) 39 #define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L)
61 40
41 namespace {
62 // The limits on the size of the buffer used for the OID query. 42 // The limits on the size of the buffer used for the OID query.
63 static const int kInitialBufferSize = 2 << 12; // Good for about 50 APs. 43 const int kInitialBufferSize = 2 << 12; // Good for about 50 APs.
64 static const int kMaximumBufferSize = 2 << 20; // 2MB 44 const int kMaximumBufferSize = 2 << 20; // 2MB
65 45
66 // Length for generic string buffers passed to Win32 APIs. 46 // Length for generic string buffers passed to Win32 APIs.
67 static const int kStringLength = 512; 47 const int kStringLength = 512;
68 48
69 // The time periods, in milliseconds, between successive polls of the wifi data. 49 // The time periods, in milliseconds, between successive polls of the wifi data.
70 extern const int kDefaultPollingInterval = 10000; // 10s 50 const int kDefaultPollingInterval = 10000; // 10s
71 extern const int kNoChangePollingInterval = 120000; // 2 mins 51 const int kNoChangePollingInterval = 120000; // 2 mins
72 extern const int kTwoNoChangePollingInterval = 600000; // 10 mins 52 const int kTwoNoChangePollingInterval = 600000; // 10 mins
73 53
74 // Local functions 54 // WlanOpenHandle
55 typedef DWORD (WINAPI *WlanOpenHandleFunction)(DWORD dwClientVersion,
56 PVOID pReserved,
57 PDWORD pdwNegotiatedVersion,
58 PHANDLE phClientHandle);
59
60 // WlanEnumInterfaces
61 typedef DWORD (WINAPI *WlanEnumInterfacesFunction)(
62 HANDLE hClientHandle,
63 PVOID pReserved,
64 PWLAN_INTERFACE_INFO_LIST *ppInterfaceList);
65
66 // WlanGetNetworkBssList
67 typedef DWORD (WINAPI *WlanGetNetworkBssListFunction)(
68 HANDLE hClientHandle,
69 const GUID *pInterfaceGuid,
70 const PDOT11_SSID pDot11Ssid,
71 DOT11_BSS_TYPE dot11BssType,
72 BOOL bSecurityEnabled,
73 PVOID pReserved,
74 PWLAN_BSS_LIST *ppWlanBssList
75 );
76
77 // WlanFreeMemory
78 typedef VOID (WINAPI *WlanFreeMemoryFunction)(PVOID pMemory);
79
80 // WlanCloseHandle
81 typedef DWORD (WINAPI *WlanCloseHandleFunction)(HANDLE hClientHandle,
82 PVOID pReserved);
83
84
85 // Local classes and functions
86 class WindowsWlanApi : public Win32WifiDataProvider::WlanApiInterface {
87 public:
88 ~WindowsWlanApi();
89 // Factory function. Will return NULL if this API is unavailable.
90 static WindowsWlanApi* Create();
91
92 // WlanApiInterface
93 virtual bool GetAccessPointData(WifiData::AccessPointDataSet *data);
94
95 private:
96 // Takes ownership of the library handle.
97 explicit WindowsWlanApi(HINSTANCE library);
98
99 // Loads the required functions from the DLL.
100 void GetWLANFunctions(HINSTANCE wlan_library);
101 int GetInterfaceDataWLAN(HANDLE wlan_handle,
102 const GUID &interface_id,
103 WifiData::AccessPointDataSet *data);
104
105 // Handle to the wlanapi.dll library.
106 HINSTANCE library_;
107
108 // Function pointers for WLAN
109 WlanOpenHandleFunction WlanOpenHandle_function_;
110 WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
111 WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_;
112 WlanFreeMemoryFunction WlanFreeMemory_function_;
113 WlanCloseHandleFunction WlanCloseHandle_function_;
114 };
115
116 class WindowsNdisApi : public Win32WifiDataProvider::WlanApiInterface {
117 public:
118 ~WindowsNdisApi();
119 static WindowsNdisApi* Create();
120
121 // WlanApiInterface
122 virtual bool GetAccessPointData(WifiData::AccessPointDataSet *data);
123
124 private:
125 static bool GetInterfacesNDIS(
126 std::vector<string16>* interface_service_names_out);
127
128 // Swaps in content of the vector passed
129 explicit WindowsNdisApi(std::vector<string16>* interface_service_names);
130
131 bool GetInterfaceDataNDIS(HANDLE adapter_handle,
132 WifiData::AccessPointDataSet *data);
133 // NDIS variables.
134 std::vector<string16> interface_service_names_;
135
136 // Remembers scan result buffer size across calls.
137 int oid_buffer_size_;
138 };
139
140
141 // TODO(joth): Share with the N other copies of this method.
142 bool IsRunningOnVistaOrNewer();
75 143
76 // Extracts data for an access point and converts to Gears format. 144 // Extracts data for an access point and converts to Gears format.
77 static bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry, 145 bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry,
78 AccessPointData *access_point_data); 146 AccessPointData *access_point_data);
79 bool UndefineDosDevice(const std::string16 &device_name); 147 bool UndefineDosDevice(const string16 &device_name);
80 bool DefineDosDeviceIfNotExists(const std::string16 &device_name); 148 bool DefineDosDeviceIfNotExists(const string16 &device_name);
81 HANDLE GetFileHandle(const std::string16 &device_name); 149 HANDLE GetFileHandle(const string16 &device_name);
82 // Makes the OID query and returns a Win32 error code. 150 // Makes the OID query and returns a Win32 error code.
83 int PerformQuery(HANDLE adapter_handle, 151 int PerformQuery(HANDLE adapter_handle,
84 BYTE *buffer, 152 BYTE *buffer,
85 DWORD buffer_size, 153 DWORD buffer_size,
86 DWORD *bytes_out); 154 DWORD *bytes_out);
87 bool ResizeBuffer(int requested_size, BYTE **buffer); 155 bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer);
88 // Gets the system directory and appends a trailing slash if not already 156 // Gets the system directory and appends a trailing slash if not already
89 // present. 157 // present.
90 bool GetSystemDirectory(std::string16 *path); 158 bool GetSystemDirectory(string16 *path);
159 } // namespace
91 160
92 // static
93 template<> 161 template<>
94 WifiDataProviderImplBase *WifiDataProvider::DefaultFactoryFunction() { 162 WifiDataProviderImplBase *WifiDataProvider::DefaultFactoryFunction() {
95 return new Win32WifiDataProvider(); 163 return new Win32WifiDataProvider();
96 } 164 }
97 165
98
99 Win32WifiDataProvider::Win32WifiDataProvider() 166 Win32WifiDataProvider::Win32WifiDataProvider()
100 : oid_buffer_size_(kInitialBufferSize), 167 : Thread(__FILE__),
101 is_first_scan_complete_(false) { 168 is_first_scan_complete_(false),
102 // Start the polling thread. 169 task_factory_(this) {
103 Start();
104 } 170 }
105 171
106 Win32WifiDataProvider::~Win32WifiDataProvider() { 172 Win32WifiDataProvider::~Win32WifiDataProvider() {
107 stop_event_.Signal(); 173 // Base class auto-stops the thread, however we need to do it here so our
108 Join(); 174 // override of CleanUp still exists whilst the thread is shutting down.
175 Stop();
176 }
177
178 void Win32WifiDataProvider::inject_mock_wlan_api(WlanApiInterface* wlan_api) {
179 assert(wlan_api_ == NULL);
180 assert(wlan_api);
181 wlan_api_.reset(wlan_api);
182 }
183
184 void Win32WifiDataProvider::inject_mock_polling_policy(
185 PollingPolicyInterface* policy) {
186 assert(polling_policy_ == NULL);
187 assert(policy);
188 polling_policy_.reset(policy);
189 }
190
191 bool Win32WifiDataProvider::StartDataProvider() {
192 return base::Thread::Start();
109 } 193 }
110 194
111 bool Win32WifiDataProvider::GetData(WifiData *data) { 195 bool Win32WifiDataProvider::GetData(WifiData *data) {
112 assert(data); 196 assert(data);
113 MutexLock lock(&data_mutex_); 197 AutoLock lock(data_mutex_);
114 *data = wifi_data_; 198 *data = wifi_data_;
115 // If we've successfully completed a scan, indicate that we have all of the 199 // If we've successfully completed a scan, indicate that we have all of the
116 // data we can get. 200 // data we can get.
117 return is_first_scan_complete_; 201 return is_first_scan_complete_;
118 } 202 }
119 203
120 // Thread implementation 204 // Thread implementation
121 void Win32WifiDataProvider::Run() { 205 void Win32WifiDataProvider::Init() {
122 // We use an absolute path to load the DLL to avoid DLL preloading attacks. 206 // Use the WLAN interface if we're on Vista and if it's available. Otherwise,
123 HINSTANCE library = NULL; 207 // use NDIS.
124 std::string16 system_directory; 208 if (wlan_api_ == NULL) {
125 if (GetSystemDirectory(&system_directory)) { 209 wlan_api_.reset(WindowsWlanApi::Create());
126 assert(!system_directory.empty()); 210 }
127 std::string16 dll_path = system_directory + L"wlanapi.dll"; 211 if (wlan_api_ == NULL) {
128 library = LoadLibraryEx(dll_path.c_str(), 212 wlan_api_.reset(WindowsNdisApi::Create());
129 NULL, 213 }
130 LOAD_WITH_ALTERED_SEARCH_PATH); 214 if (wlan_api_ == NULL) {
215 // Error! Can't do scans, so don't try and schedule one.
216 is_first_scan_complete_ = true;
217 return;
131 } 218 }
132 219
133 // Use the WLAN interface if we're on Vista and if it's available. Otherwise, 220 if (polling_policy_ == NULL) {
134 // use NDIS. 221 polling_policy_.reset(
135 typedef bool (Win32WifiDataProvider::*GetAccessPointDataFunction)( 222 new GenericPollingPolicy<kDefaultPollingInterval,
136 WifiData::AccessPointDataSet *data); 223 kNoChangePollingInterval,
137 GetAccessPointDataFunction get_access_point_data_function = NULL; 224 kTwoNoChangePollingInterval>);
138 if (VistaUtils::IsRunningOnVista() && library) {
139 GetWLANFunctions(library);
140 get_access_point_data_function =
141 &Win32WifiDataProvider::GetAccessPointDataWLAN;
142 } else {
143 // We assume the list of interfaces doesn't change while Gears is running.
144 if (!GetInterfacesNDIS()) {
145 is_first_scan_complete_ = true;
146 return;
147 }
148 get_access_point_data_function =
149 &Win32WifiDataProvider::GetAccessPointDataNDIS;
150 } 225 }
151 assert(get_access_point_data_function); 226 assert(polling_policy_ != NULL);
152 227
153 int polling_interval = kDefaultPollingInterval; 228 ScheduleNextScan();
154 // Regularly get the access point data.
155 do {
156 WifiData new_data;
157 if ((this->*get_access_point_data_function)(&new_data.access_point_data)) {
158 bool update_available;
159 data_mutex_.Lock();
160 update_available = wifi_data_.DiffersSignificantly(new_data);
161 wifi_data_ = new_data;
162 data_mutex_.Unlock();
163 polling_interval =
164 UpdatePollingInterval(polling_interval, update_available);
165 if (update_available) {
166 is_first_scan_complete_ = true;
167 NotifyListeners();
168 }
169 }
170 } while (!stop_event_.WaitWithTimeout(polling_interval));
171
172 FreeLibrary(library);
173 } 229 }
174 230
175 // WLAN functions 231 void Win32WifiDataProvider::CleanUp() {
232 // Destroy the wlan api instance in the thread in which it was created.
233 wlan_api_.reset(NULL);
234 }
176 235
177 void Win32WifiDataProvider::GetWLANFunctions(HINSTANCE wlan_library) { 236 void Win32WifiDataProvider::DoWifiScanTask() {
237 WifiData new_data;
238 if (wlan_api_->GetAccessPointData(&new_data.access_point_data)) {
239 bool update_available;
240 data_mutex_.Acquire();
241 update_available = wifi_data_.DiffersSignificantly(new_data);
242 wifi_data_ = new_data;
243 data_mutex_.Release();
244 polling_policy_->UpdatePollingInterval(update_available);
245 if (update_available) {
246 is_first_scan_complete_ = true;
247 NotifyListeners();
248 }
249 }
250 ScheduleNextScan();
251 }
252
253 void Win32WifiDataProvider::ScheduleNextScan() {
254 message_loop()->PostDelayedTask(FROM_HERE,
255 task_factory_.NewRunnableMethod(&Win32WifiDataProvider::DoWifiScanTask),
256 polling_policy_->PollingInterval());
257 }
258
259 // Local classes and functions
260 namespace {
261
262 // WindowsWlanApi
263 WindowsWlanApi::WindowsWlanApi(HINSTANCE library)
264 : library_(library) {
265 GetWLANFunctions(library_);
266 }
267
268 WindowsWlanApi::~WindowsWlanApi() {
269 FreeLibrary(library_);
270 }
271
272 WindowsWlanApi* WindowsWlanApi::Create() {
273 // We use an absolute path to load the DLL to avoid DLL preloading attacks.
274 string16 system_directory;
275 if (!IsRunningOnVistaOrNewer()) {
276 return NULL;
277 }
278 if (!GetSystemDirectory(&system_directory)) {
279 return NULL;
280 }
281 assert(!system_directory.empty());
282 string16 dll_path = system_directory + L"wlanapi.dll";
283 HINSTANCE library = LoadLibraryEx(dll_path.c_str(),
284 NULL,
285 LOAD_WITH_ALTERED_SEARCH_PATH);
286 if (!library) {
287 return NULL;
288 }
289 return new WindowsWlanApi(library);
290 }
291
292 void WindowsWlanApi::GetWLANFunctions(HINSTANCE wlan_library) {
178 assert(wlan_library); 293 assert(wlan_library);
179 WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>( 294 WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>(
180 GetProcAddress(wlan_library, "WlanOpenHandle")); 295 GetProcAddress(wlan_library, "WlanOpenHandle"));
181 WlanEnumInterfaces_function_ = reinterpret_cast<WlanEnumInterfacesFunction>( 296 WlanEnumInterfaces_function_ = reinterpret_cast<WlanEnumInterfacesFunction>(
182 GetProcAddress(wlan_library, "WlanEnumInterfaces")); 297 GetProcAddress(wlan_library, "WlanEnumInterfaces"));
183 WlanGetNetworkBssList_function_ = 298 WlanGetNetworkBssList_function_ =
184 reinterpret_cast<WlanGetNetworkBssListFunction>( 299 reinterpret_cast<WlanGetNetworkBssListFunction>(
185 GetProcAddress(wlan_library, "WlanGetNetworkBssList")); 300 GetProcAddress(wlan_library, "WlanGetNetworkBssList"));
186 WlanFreeMemory_function_ = reinterpret_cast<WlanFreeMemoryFunction>( 301 WlanFreeMemory_function_ = reinterpret_cast<WlanFreeMemoryFunction>(
187 GetProcAddress(wlan_library, "WlanFreeMemory")); 302 GetProcAddress(wlan_library, "WlanFreeMemory"));
188 WlanCloseHandle_function_ = reinterpret_cast<WlanCloseHandleFunction>( 303 WlanCloseHandle_function_ = reinterpret_cast<WlanCloseHandleFunction>(
189 GetProcAddress(wlan_library, "WlanCloseHandle")); 304 GetProcAddress(wlan_library, "WlanCloseHandle"));
190 assert(WlanOpenHandle_function_ && 305 assert(WlanOpenHandle_function_ &&
191 WlanEnumInterfaces_function_ && 306 WlanEnumInterfaces_function_ &&
192 WlanGetNetworkBssList_function_ && 307 WlanGetNetworkBssList_function_ &&
193 WlanFreeMemory_function_ && 308 WlanFreeMemory_function_ &&
194 WlanCloseHandle_function_); 309 WlanCloseHandle_function_);
195 } 310 }
196 311
197 bool Win32WifiDataProvider::GetAccessPointDataWLAN( 312 bool WindowsWlanApi::GetAccessPointData(
198 WifiData::AccessPointDataSet *data) { 313 WifiData::AccessPointDataSet *data) {
199 assert(data); 314 assert(data);
200 315
201 // Get the handle to the WLAN API. 316 // Get the handle to the WLAN API.
202 DWORD negotiated_version; 317 DWORD negotiated_version;
203 HANDLE wlan_handle = NULL; 318 HANDLE wlan_handle = NULL;
204 // We could be executing on either Windows XP or Windows Vista, so use the 319 // We could be executing on either Windows XP or Windows Vista, so use the
205 // lower version of the client WLAN API. It seems that the negotiated version 320 // lower version of the client WLAN API. It seems that the negotiated version
206 // is the Vista version irrespective of what we pass! 321 // is the Vista version irrespective of what we pass!
207 static const int kXpWlanClientVersion = 1; 322 static const int kXpWlanClientVersion = 1;
(...skipping 26 matching lines...) Expand all
234 // Close the handle. 349 // Close the handle.
235 if ((*WlanCloseHandle_function_)(wlan_handle, NULL) != ERROR_SUCCESS) { 350 if ((*WlanCloseHandle_function_)(wlan_handle, NULL) != ERROR_SUCCESS) {
236 return false; 351 return false;
237 } 352 }
238 353
239 return true; 354 return true;
240 } 355 }
241 356
242 // Appends the data for a single interface to the data vector. Returns the 357 // Appends the data for a single interface to the data vector. Returns the
243 // number of access points found, or -1 on error. 358 // number of access points found, or -1 on error.
244 int Win32WifiDataProvider::GetInterfaceDataWLAN( 359 int WindowsWlanApi::GetInterfaceDataWLAN(
245 const HANDLE wlan_handle, 360 const HANDLE wlan_handle,
246 const GUID &interface_id, 361 const GUID &interface_id,
247 WifiData::AccessPointDataSet *data) { 362 WifiData::AccessPointDataSet *data) {
248 assert(data); 363 assert(data);
249 // WlanGetNetworkBssList allocates bss_list. 364 // WlanGetNetworkBssList allocates bss_list.
250 WLAN_BSS_LIST *bss_list; 365 WLAN_BSS_LIST *bss_list;
251 if ((*WlanGetNetworkBssList_function_)(wlan_handle, 366 if ((*WlanGetNetworkBssList_function_)(wlan_handle,
252 &interface_id, 367 &interface_id,
253 NULL, // Use all SSIDs. 368 NULL, // Use all SSIDs.
254 DOT11_BSS_TYPE_UNUSED, 369 dot11_BSS_type_any,
255 false, // bSecurityEnabled - unused 370 false, // bSecurityEnabled - unused
256 NULL, // reserved 371 NULL, // reserved
257 &bss_list) != ERROR_SUCCESS) { 372 &bss_list) != ERROR_SUCCESS) {
258 return -1; 373 return -1;
259 } 374 }
260 375
261 int found = 0; 376 int found = 0;
262 for (int i = 0; i < static_cast<int>(bss_list->dwNumberOfItems); ++i) { 377 for (int i = 0; i < static_cast<int>(bss_list->dwNumberOfItems); ++i) {
263 AccessPointData access_point_data; 378 AccessPointData access_point_data;
264 if (GetNetworkData(bss_list->wlanBssEntries[i], &access_point_data)) { 379 if (GetNetworkData(bss_list->wlanBssEntries[i], &access_point_data)) {
265 ++found; 380 ++found;
266 data->insert(access_point_data); 381 data->insert(access_point_data);
267 } 382 }
268 } 383 }
269 384
270 (*WlanFreeMemory_function_)(bss_list); 385 (*WlanFreeMemory_function_)(bss_list);
271 386
272 return found; 387 return found;
273 } 388 }
274 389
275 // NDIS functions 390 // WindowsNdisApi
391 WindowsNdisApi::WindowsNdisApi(
392 std::vector<string16>* interface_service_names)
393 : oid_buffer_size_(kInitialBufferSize) {
394 assert(!interface_service_names->empty());
395 interface_service_names_.swap(*interface_service_names);
396 }
276 397
277 bool Win32WifiDataProvider::GetInterfacesNDIS() { 398 WindowsNdisApi::~WindowsNdisApi() {
399 }
400
401 WindowsNdisApi* WindowsNdisApi::Create() {
402 std::vector<string16> interface_service_names;
403 if (GetInterfacesNDIS(&interface_service_names)) {
404 return new WindowsNdisApi(&interface_service_names);
405 }
406 return NULL;
407 }
408
409 bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet *data) {
410 assert(data);
411 int interfaces_failed = 0;
412 int interfaces_succeeded = 0;
413
414 for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) {
415 // First, check that we have a DOS device for this adapter.
416 if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) {
417 continue;
418 }
419
420 // Get the handle to the device. This will fail if the named device is not
421 // valid.
422 HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]);
423 if (adapter_handle == INVALID_HANDLE_VALUE) {
424 continue;
425 }
426
427 // Get the data.
428 if (GetInterfaceDataNDIS(adapter_handle, data)) {
429 ++interfaces_succeeded;
430 } else {
431 ++interfaces_failed;
432 }
433
434 // Clean up.
435 CloseHandle(adapter_handle);
436 UndefineDosDevice(interface_service_names_[i]);
437 }
438
439 // Return true if at least one interface succeeded, or at the very least none
440 // failed.
441 return interfaces_succeeded > 0 || interfaces_failed == 0;
442 }
443
444 bool WindowsNdisApi::GetInterfacesNDIS(
445 std::vector<string16>* interface_service_names_out) {
278 HKEY network_cards_key = NULL; 446 HKEY network_cards_key = NULL;
279 if (RegOpenKeyEx( 447 if (RegOpenKeyEx(
280 HKEY_LOCAL_MACHINE, 448 HKEY_LOCAL_MACHINE,
281 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", 449 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards",
282 0, 450 0,
283 KEY_READ, 451 KEY_READ,
284 &network_cards_key) != ERROR_SUCCESS) { 452 &network_cards_key) != ERROR_SUCCESS) {
285 return false; 453 return false;
286 } 454 }
287 assert(network_cards_key); 455 assert(network_cards_key);
(...skipping 21 matching lines...) Expand all
309 477
310 TCHAR service_name[kStringLength]; 478 TCHAR service_name[kStringLength];
311 DWORD service_name_size = kStringLength; 479 DWORD service_name_size = kStringLength;
312 DWORD type = 0; 480 DWORD type = 0;
313 if (RegQueryValueEx(hardware_key, 481 if (RegQueryValueEx(hardware_key,
314 L"ServiceName", 482 L"ServiceName",
315 NULL, 483 NULL,
316 &type, 484 &type,
317 reinterpret_cast<LPBYTE>(service_name), 485 reinterpret_cast<LPBYTE>(service_name),
318 &service_name_size) == ERROR_SUCCESS) { 486 &service_name_size) == ERROR_SUCCESS) {
319 interface_service_names_.push_back(service_name); 487 interface_service_names_out->push_back(service_name);
320 } 488 }
321 RegCloseKey(hardware_key); 489 RegCloseKey(hardware_key);
322 } 490 }
323 491
324 RegCloseKey(network_cards_key); 492 RegCloseKey(network_cards_key);
325 return true; 493 return true;
326 } 494 }
327 495
328 bool Win32WifiDataProvider::GetAccessPointDataNDIS( 496
329 WifiData::AccessPointDataSet *data) { 497 bool WindowsNdisApi::GetInterfaceDataNDIS(HANDLE adapter_handle,
498 WifiData::AccessPointDataSet *data) {
330 assert(data); 499 assert(data);
331 500
332 for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) { 501 scoped_ptr_malloc<BYTE> buffer(
333 // First, check that we have a DOS device for this adapter. 502 reinterpret_cast<BYTE*>(malloc(oid_buffer_size_)));
334 if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) {
335 continue;
336 }
337
338 // Get the handle to the device. This will fail if the named device is not
339 // valid.
340 HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]);
341 if (adapter_handle == INVALID_HANDLE_VALUE) {
342 continue;
343 }
344
345 // Get the data.
346 GetInterfaceDataNDIS(adapter_handle, data);
347
348 // Clean up.
349 CloseHandle(adapter_handle);
350 UndefineDosDevice(interface_service_names_[i]);
351 }
352
353 return true;
354 }
355
356 bool Win32WifiDataProvider::GetInterfaceDataNDIS(
357 HANDLE adapter_handle,
358 WifiData::AccessPointDataSet *data) {
359 assert(data);
360
361 BYTE *buffer = reinterpret_cast<BYTE*>(malloc(oid_buffer_size_));
362 if (buffer == NULL) { 503 if (buffer == NULL) {
363 return false; 504 return false;
364 } 505 }
365 506
366 DWORD bytes_out; 507 DWORD bytes_out;
367 int result; 508 int result;
368 509
369 while (true) { 510 while (true) {
370 bytes_out = 0; 511 bytes_out = 0;
371 result = PerformQuery(adapter_handle, buffer, oid_buffer_size_, &bytes_out); 512 result = PerformQuery(adapter_handle, buffer.get(),
513 oid_buffer_size_, &bytes_out);
372 if (result == ERROR_GEN_FAILURE || // Returned by some Intel cards. 514 if (result == ERROR_GEN_FAILURE || // Returned by some Intel cards.
373 result == ERROR_INSUFFICIENT_BUFFER || 515 result == ERROR_INSUFFICIENT_BUFFER ||
374 result == ERROR_MORE_DATA || 516 result == ERROR_MORE_DATA ||
375 result == NDIS_STATUS_INVALID_LENGTH || 517 result == NDIS_STATUS_INVALID_LENGTH ||
376 result == NDIS_STATUS_BUFFER_TOO_SHORT) { 518 result == NDIS_STATUS_BUFFER_TOO_SHORT) {
377 // The buffer we supplied is too small, so increase it. bytes_out should 519 // The buffer we supplied is too small, so increase it. bytes_out should
378 // provide the required buffer size, but this is not always the case. 520 // provide the required buffer size, but this is not always the case.
379 if (bytes_out > static_cast<DWORD>(oid_buffer_size_)) { 521 if (bytes_out > static_cast<DWORD>(oid_buffer_size_)) {
380 oid_buffer_size_ = bytes_out; 522 oid_buffer_size_ = bytes_out;
381 } else { 523 } else {
382 oid_buffer_size_ *= 2; 524 oid_buffer_size_ *= 2;
383 } 525 }
384 if (!ResizeBuffer(oid_buffer_size_, &buffer)) { 526 if (!ResizeBuffer(oid_buffer_size_, &buffer)) {
385 oid_buffer_size_ = kInitialBufferSize; // Reset for next time. 527 oid_buffer_size_ = kInitialBufferSize; // Reset for next time.
386 return false; 528 return false;
387 } 529 }
388 } else { 530 } else {
389 // The buffer is not too small. 531 // The buffer is not too small.
390 break; 532 break;
391 } 533 }
392 } 534 }
393 assert(buffer); 535 assert(buffer.get());
394 536
395 if (result == ERROR_SUCCESS) { 537 if (result == ERROR_SUCCESS) {
396 NDIS_802_11_BSSID_LIST* bssid_list = 538 NDIS_802_11_BSSID_LIST* bssid_list =
397 reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer); 539 reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer.get());
398 GetDataFromBssIdList(*bssid_list, oid_buffer_size_, data); 540 GetDataFromBssIdList(*bssid_list, oid_buffer_size_, data);
399 } 541 }
400 542
401 free(buffer);
402 return true; 543 return true;
403 } 544 }
404 545
405 // Local functions 546 bool IsRunningOnVistaOrNewer() {
547 OSVERSIONINFO info = {0};
548 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
549 GetVersionEx(&info);
550 return (info.dwMajorVersion >=6);
551 }
406 552
407 static bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry, 553 bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry,
408 AccessPointData *access_point_data) { 554 AccessPointData *access_point_data) {
409 // Currently we get only MAC address, signal strength and SSID. 555 // Currently we get only MAC address, signal strength and SSID.
410 assert(access_point_data); 556 assert(access_point_data);
411 access_point_data->mac_address = MacAddressAsString16(bss_entry.dot11Bssid); 557 access_point_data->mac_address = MacAddressAsString16(bss_entry.dot11Bssid);
412 access_point_data->radio_signal_strength = bss_entry.lRssi; 558 access_point_data->radio_signal_strength = bss_entry.lRssi;
413 // bss_entry.dot11Ssid.ucSSID is not null-terminated. 559 // bss_entry.dot11Ssid.ucSSID is not null-terminated.
414 UTF8ToString16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID), 560 UTF8ToUTF16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID),
415 static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength), 561 static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength),
416 &access_point_data->ssid); 562 &access_point_data->ssid);
417 // TODO(steveblock): Is it possible to get the following? 563 // TODO(steveblock): Is it possible to get the following?
418 //access_point_data->signal_to_noise 564 // access_point_data->signal_to_noise
419 //access_point_data->age 565 // access_point_data->age
420 //access_point_data->channel 566 // access_point_data->channel
421 return true; 567 return true;
422 } 568 }
423 569
424 bool UndefineDosDevice(const std::string16 &device_name) { 570 bool UndefineDosDevice(const string16 &device_name) {
425 // We remove only the mapping we use, that is \Device\<device_name>. 571 // We remove only the mapping we use, that is \Device\<device_name>.
426 std::string16 target_path = L"\\Device\\" + device_name; 572 string16 target_path = L"\\Device\\" + device_name;
427 return DefineDosDevice( 573 return DefineDosDevice(
428 DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, 574 DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
429 device_name.c_str(), 575 device_name.c_str(),
430 target_path.c_str()) == TRUE; 576 target_path.c_str()) == TRUE;
431 } 577 }
432 578
433 bool DefineDosDeviceIfNotExists(const std::string16 &device_name) { 579 bool DefineDosDeviceIfNotExists(const string16 &device_name) {
434 // We create a DOS device name for the device at \Device\<device_name>. 580 // We create a DOS device name for the device at \Device\<device_name>.
435 std::string16 target_path = L"\\Device\\" + device_name; 581 string16 target_path = L"\\Device\\" + device_name;
436 582
437 TCHAR target[kStringLength]; 583 TCHAR target[kStringLength];
438 if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && 584 if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 &&
439 target_path.compare(target) == 0) { 585 target_path.compare(target) == 0) {
440 // Device already exists. 586 // Device already exists.
441 return true; 587 return true;
442 } 588 }
443 589
444 if (GetLastError() != ERROR_FILE_NOT_FOUND) { 590 if (GetLastError() != ERROR_FILE_NOT_FOUND) {
445 return false; 591 return false;
446 } 592 }
447 593
448 if (!DefineDosDevice(DDD_RAW_TARGET_PATH, 594 if (!DefineDosDevice(DDD_RAW_TARGET_PATH,
449 device_name.c_str(), 595 device_name.c_str(),
450 target_path.c_str())) { 596 target_path.c_str())) {
451 return false; 597 return false;
452 } 598 }
453 599
454 // Check that the device is really there. 600 // Check that the device is really there.
455 return QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && 601 return QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 &&
456 target_path.compare(target) == 0; 602 target_path.compare(target) == 0;
457 } 603 }
458 604
459 HANDLE GetFileHandle(const std::string16 &device_name) { 605 HANDLE GetFileHandle(const string16 &device_name) {
460 // We access a device with DOS path \Device\<device_name> at 606 // We access a device with DOS path \Device\<device_name> at
461 // \\.\<device_name>. 607 // \\.\<device_name>.
462 std::string16 formatted_device_name = L"\\\\.\\" + device_name; 608 string16 formatted_device_name = L"\\\\.\\" + device_name;
463 609
464 return CreateFile(formatted_device_name.c_str(), 610 return CreateFile(formatted_device_name.c_str(),
465 GENERIC_READ, 611 GENERIC_READ,
466 FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode 612 FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
467 0, // security attributes 613 0, // security attributes
468 OPEN_EXISTING, 614 OPEN_EXISTING,
469 0, // flags and attributes 615 0, // flags and attributes
470 INVALID_HANDLE_VALUE); 616 INVALID_HANDLE_VALUE);
471 } 617 }
472 618
473 int PerformQuery(HANDLE adapter_handle, 619 int PerformQuery(HANDLE adapter_handle,
474 BYTE *buffer, 620 BYTE *buffer,
475 DWORD buffer_size, 621 DWORD buffer_size,
476 DWORD *bytes_out) { 622 DWORD *bytes_out) {
477 DWORD oid = OID_802_11_BSSID_LIST; 623 DWORD oid = OID_802_11_BSSID_LIST;
478 if (!DeviceIoControl(adapter_handle, 624 if (!DeviceIoControl(adapter_handle,
479 IOCTL_NDIS_QUERY_GLOBAL_STATS, 625 IOCTL_NDIS_QUERY_GLOBAL_STATS,
480 &oid, 626 &oid,
481 sizeof(oid), 627 sizeof(oid),
482 buffer, 628 buffer,
483 buffer_size, 629 buffer_size,
484 bytes_out, 630 bytes_out,
485 NULL)) { 631 NULL)) {
486 return GetLastError(); 632 return GetLastError();
487 } 633 }
488 return ERROR_SUCCESS; 634 return ERROR_SUCCESS;
489 } 635 }
490 636
491 bool ResizeBuffer(int requested_size, BYTE **buffer) { 637 bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer) {
638 assert(requested_size > 0);
639 assert(buffer);
492 if (requested_size > kMaximumBufferSize) { 640 if (requested_size > kMaximumBufferSize) {
493 free(*buffer); 641 buffer->reset(NULL);
494 *buffer = NULL;
495 return false; 642 return false;
496 } 643 }
497 644
498 BYTE *new_buffer = reinterpret_cast<BYTE*>(realloc(*buffer, requested_size)); 645 buffer->reset(reinterpret_cast<BYTE*>(
499 if (new_buffer == NULL) { 646 realloc(buffer->release(), requested_size)));
500 free(*buffer); 647 return buffer != NULL;
501 *buffer = NULL;
502 return false;
503 }
504
505 *buffer = new_buffer;
506 return true;
507 } 648 }
508 649
509 bool GetSystemDirectory(std::string16 *path) { 650 bool GetSystemDirectory(string16 *path) {
510 assert(path); 651 assert(path);
511 // Return value includes terminating NULL. 652 // Return value includes terminating NULL.
512 int buffer_size = GetSystemDirectory(NULL, 0); 653 int buffer_size = ::GetSystemDirectory(NULL, 0);
513 if (buffer_size == 0) { 654 if (buffer_size == 0) {
514 return false; 655 return false;
515 } 656 }
516 char16 *buffer = new char16[buffer_size]; 657 char16 *buffer = new char16[buffer_size];
517 658
518 // Return value excludes terminating NULL. 659 // Return value excludes terminating NULL.
519 int characters_written = GetSystemDirectory(buffer, buffer_size); 660 int characters_written = ::GetSystemDirectory(buffer, buffer_size);
520 if (characters_written == 0) { 661 if (characters_written == 0) {
521 return false; 662 return false;
522 } 663 }
523 assert(characters_written == buffer_size - 1); 664 assert(characters_written == buffer_size - 1);
524 665
525 path->assign(buffer); 666 path->assign(buffer);
526 delete[] buffer; 667 delete[] buffer;
527 668
528 if (path->at(path->length() - 1) != L'\\') { 669 if (path->at(path->length() - 1) != L'\\') {
529 path->append(L"\\"); 670 path->append(L"\\");
530 } 671 }
531 return true; 672 return true;
532 } 673 }
533 674 } // namespace
534 #endif // WIN32 && !OS_WINCE
OLDNEW
« no previous file with comments | « chrome/browser/geolocation/wifi_data_provider_win.h ('k') | chrome/browser/geolocation/wifi_data_provider_windows_common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698