michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include "windows.h" michael@0: #include "wlanapi.h" michael@0: michael@0: #include "stdlib.h" michael@0: michael@0: #include "nsWifiMonitor.h" michael@0: #include "nsWifiAccessPoint.h" michael@0: michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsIMutableArray.h" michael@0: michael@0: #define DOT11_BSS_TYPE_UNUSED static_cast(0) michael@0: michael@0: using namespace mozilla; michael@0: michael@0: nsresult michael@0: nsWifiMonitor::DoScan() michael@0: { michael@0: HINSTANCE wlan_library = LoadLibrary("Wlanapi.dll"); michael@0: if (!wlan_library) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: decltype(::WlanOpenHandle)* WlanOpenHandle = (decltype(::WlanOpenHandle)*) GetProcAddress(wlan_library, "WlanOpenHandle"); michael@0: decltype(::WlanEnumInterfaces)* WlanEnumInterfaces = (decltype(::WlanEnumInterfaces)*) GetProcAddress(wlan_library, "WlanEnumInterfaces"); michael@0: decltype(::WlanGetNetworkBssList)* WlanGetNetworkBssList = (decltype(::WlanGetNetworkBssList)*) GetProcAddress(wlan_library, "WlanGetNetworkBssList"); michael@0: decltype(::WlanFreeMemory)* WlanFreeMemory = (decltype(::WlanFreeMemory)*) GetProcAddress(wlan_library, "WlanFreeMemory"); michael@0: decltype(::WlanCloseHandle)* WlanCloseHandle = (decltype(::WlanCloseHandle)*) GetProcAddress(wlan_library, "WlanCloseHandle"); michael@0: michael@0: if (!WlanOpenHandle || michael@0: !WlanEnumInterfaces || michael@0: !WlanGetNetworkBssList || michael@0: !WlanFreeMemory || michael@0: !WlanCloseHandle) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // Regularly get the access point data. michael@0: michael@0: nsCOMArray lastAccessPoints; michael@0: nsCOMArray accessPoints; michael@0: michael@0: do { michael@0: accessPoints.Clear(); michael@0: michael@0: // Get the handle to the WLAN API. michael@0: DWORD negotiated_version; michael@0: HANDLE wlan_handle = nullptr; michael@0: // We could be executing on either Windows XP or Windows Vista, so use the michael@0: // lower version of the client WLAN API. It seems that the negotiated version michael@0: // is the Vista version irrespective of what we pass! michael@0: static const int kXpWlanClientVersion = 1; michael@0: if ((*WlanOpenHandle)(kXpWlanClientVersion, michael@0: nullptr, michael@0: &negotiated_version, michael@0: &wlan_handle) != ERROR_SUCCESS) { michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: // try again later. michael@0: if (!wlan_handle) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // Get the list of interfaces. WlanEnumInterfaces allocates interface_list. michael@0: WLAN_INTERFACE_INFO_LIST *interface_list = nullptr; michael@0: if ((*WlanEnumInterfaces)(wlan_handle, nullptr, &interface_list) != ERROR_SUCCESS) { michael@0: // try again later michael@0: (*WlanCloseHandle)(wlan_handle, nullptr); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // Go through the list of interfaces and get the data for each. michael@0: for (int i = 0; i < static_cast(interface_list->dwNumberOfItems); ++i) { michael@0: michael@0: WLAN_BSS_LIST *bss_list; michael@0: HRESULT rv = (*WlanGetNetworkBssList)(wlan_handle, michael@0: &interface_list->InterfaceInfo[i].InterfaceGuid, michael@0: nullptr, // Use all SSIDs. michael@0: DOT11_BSS_TYPE_UNUSED, michael@0: false, // bSecurityEnabled - unused michael@0: nullptr, // reserved michael@0: &bss_list); michael@0: if (rv != ERROR_SUCCESS) { michael@0: continue; michael@0: } michael@0: michael@0: for (int j = 0; j < static_cast(bss_list->dwNumberOfItems); ++j) { michael@0: michael@0: nsWifiAccessPoint* ap = new nsWifiAccessPoint(); michael@0: if (!ap) michael@0: continue; michael@0: michael@0: const WLAN_BSS_ENTRY bss_entry = bss_list->wlanBssEntries[j]; michael@0: michael@0: ap->setMac(bss_entry.dot11Bssid); michael@0: ap->setSignal(bss_entry.lRssi); michael@0: ap->setSSID((char*) bss_entry.dot11Ssid.ucSSID, michael@0: bss_entry.dot11Ssid.uSSIDLength); michael@0: michael@0: accessPoints.AppendObject(ap); michael@0: } michael@0: (*WlanFreeMemory)(bss_list); michael@0: } michael@0: michael@0: // Free interface_list. michael@0: (*WlanFreeMemory)(interface_list); michael@0: michael@0: // Close the handle. michael@0: (*WlanCloseHandle)(wlan_handle, nullptr); michael@0: michael@0: michael@0: bool accessPointsChanged = !AccessPointsEqual(accessPoints, lastAccessPoints); michael@0: ReplaceArray(lastAccessPoints, accessPoints); michael@0: michael@0: nsresult rv = CallWifiListeners(lastAccessPoints, accessPointsChanged); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // wait for some reasonable amount of time. pref? michael@0: LOG(("waiting on monitor\n")); michael@0: michael@0: ReentrantMonitorAutoEnter mon(mReentrantMonitor); michael@0: mon.Wait(PR_SecondsToInterval(60)); michael@0: } michael@0: while (mKeepGoing); michael@0: michael@0: return NS_OK; michael@0: }