Search code examples
winapiwifibeacon

How to get Wi-Fi Information Elements in Windows Native Wifi


The Windows Native Wifi documentation mentions 802.11 Information Elements (IEs) from Beacon or Probe Response frames are available through the WLAN_BSS_ENTRY structure, specifically, through its ulIeOffset and ulIeSize members, which define an area of memory that contains the IE data blob. I've been unsuccessful with retrieving IEs using these two variables.

I get multiple valid WLAN_BSS_ENTRY structures through GetAvailableNetworkList() (correctly populated with 802.11 network information - SSID, BSSID, etc.) - ulIeOffset and ulIeSize values make sense too, but I get read exception when trying to access that memory area.

My test platform is Windows 10 with all updates as of this post date, latest Visual Studio Community edition, and I wrote a simple console application that prints all WLAN_BSS_ENTRY fields (successful), and the IE data blob (unsuccessful). C++ code related to scan is shown below. Any insight appreciated.

// retrieve scanned networks
dwResult = WlanGetNetworkBssList(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid,
        NULL, dot11_BSS_type_any, false, NULL, &pBssList);
if (dwResult == ERROR_SUCCESS) {
    for (DWORD i = 0; i < pBssList->dwNumberOfItems; i++) {
        const WLAN_BSS_ENTRY bssEntry = pBssList->wlanBssEntries[i];
        std::cout << "SSID: " << bssEntry.dot11Ssid.ucSSID << std::endl;
        std::cout << "RSSI: " << bssEntry.lRssi << " dBm" << std::endl;
        // print bunch of other bssEntry fields, all valid
        std::cout << "IE buffer offset: " << bssEntry.ulIeOffset << std::endl;
        std::cout << "IE buffer size: " << bssEntry.ulIeSize << std::endl;
        // --> IE retrieval below doesn't work (throws read exception) <--
        const PBYTE ieBuffer = (const PBYTE)((PBYTE)(&bssEntry) + bssEntry.ulIeOffset);
        for (DWORD j = 0; j < bssEntry.ulIeSize; j++) {
           printf("%02X ", ieBuffer[j]);
        }
        std::cout << std::endl;
        std::cout << std::endl;
    }
    WlanFreeMemory(pBssList);
}

Solution

  • The problem is this code:

    const WLAN_BSS_ENTRY bssEntry = pBssList->wlanBssEntries[i];
    

    makes a copy of the WLAN_BSS_ENTRY structure, so it's address points to another place in memory. You want to keep everything as pointers:

    WlanGetNetworkBssList(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid, NULL, dot11_BSS_type_any, false, NULL, &pBssList);
    for (DWORD i = 0; i < pBssList->dwNumberOfItems; i++) {
    
        // use the original pointer
        PWLAN_BSS_ENTRY bssEntry = &pBssList->wlanBssEntries[i]
    
        std::cout << "SSID: " << bssEntry->dot11Ssid.ucSSID << std::endl;
        std::cout << "RSSI: " << bssEntry->lRssi << " dBm" << std::endl;
        std::cout << "IE buffer offset: " << bssEntry->ulIeOffset << std::endl;
        std::cout << "IE buffer size: " << bssEntry->ulIeSize << std::endl;
    
        PBYTE ieBuffer = (PBYTE)bssEntry + bssEntry->ulIeOffset;
        for (DWORD j = 0; j < bssEntry->ulIeSize; j++) {
            printf("%02X ", ieBuffer[j]);
        }
        std::cout << std::endl;
        std::cout << std::endl;
    }
    WlanFreeMemory(pBssList);