Skip to content
The Road to Delphi — Delphi, VCL, VCL Styles, UxTheme and WinAPI

Detecting Wifi Networks Using Delphi and Native Wifi API

,

Today we will use the Native Wifi API and Delphi to enumerate all Wifi Networks availables. In this link you can find a translation of the headers.
I wrote this code using these headers. Tested in Delphi 2007 and Windows Vista.

Try this link for a fixed and updated version of the Native Wifi Delphi headers.

[sourcecode language=”delphi” wraplines=”false”]
{$APPTYPE CONSOLE}

uses
Windows,
SysUtils,
nduWlanAPI in ‘nduWlanAPI.pas’,
nduWlanTypes in ‘nduWlanTypes.pas’;

function DOT11_AUTH_ALGORITHM_To_String( Dummy :Tndu_DOT11_AUTH_ALGORITHM):AnsiString;
begin
Result:=”;
case Dummy of
DOT11_AUTH_ALGO_80211_OPEN : Result:= ‘80211_OPEN’;
DOT11_AUTH_ALGO_80211_SHARED_KEY : Result:= ‘80211_SHARED_KEY’;
DOT11_AUTH_ALGO_WPA : Result:= ‘WPA’;
DOT11_AUTH_ALGO_WPA_PSK : Result:= ‘WPA_PSK’;
DOT11_AUTH_ALGO_WPA_NONE : Result:= ‘WPA_NONE’;
DOT11_AUTH_ALGO_RSNA : Result:= ‘RSNA’;
DOT11_AUTH_ALGO_RSNA_PSK : Result:= ‘RSNA_PSK’;
DOT11_AUTH_ALGO_IHV_START : Result:= ‘IHV_START’;
DOT11_AUTH_ALGO_IHV_END : Result:= ‘IHV_END’;
end;
end;

function DOT11_CIPHER_ALGORITHM_To_String( Dummy :Tndu_DOT11_CIPHER_ALGORITHM):AnsiString;
begin
Result:=”;
case Dummy of
DOT11_CIPHER_ALGO_NONE : Result:= ‘NONE’;
DOT11_CIPHER_ALGO_WEP40 : Result:= ‘WEP40’;
DOT11_CIPHER_ALGO_TKIP : Result:= ‘TKIP’;
DOT11_CIPHER_ALGO_CCMP : Result:= ‘CCMP’;
DOT11_CIPHER_ALGO_WEP104 : Result:= ‘WEP104’;
DOT11_CIPHER_ALGO_WPA_USE_GROUP : Result:= ‘WPA_USE_GROUP OR RSN_USE_GROUP’;
//DOT11_CIPHER_ALGO_RSN_USE_GROUP : Result:= ‘RSN_USE_GROUP’;
DOT11_CIPHER_ALGO_WEP : Result:= ‘WEP’;
DOT11_CIPHER_ALGO_IHV_START : Result:= ‘IHV_START’;
DOT11_CIPHER_ALGO_IHV_END : Result:= ‘IHV_END’;
end;
end;

procedure Scan();
const
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES =$00000001;
var
hClient : THandle;
dwVersion : DWORD;
ResultInt : DWORD;
pInterface : Pndu_WLAN_INTERFACE_INFO_LIST;
i : Integer;
j : Integer;
pAvailableNetworkList: Pndu_WLAN_AVAILABLE_NETWORK_LIST;
pInterfaceGuid : PGUID;
SDummy : AnsiString;
begin
ResultInt:=WlanOpenHandle(1, nil, @dwVersion, @hClient);
try
if ResultInt<> ERROR_SUCCESS then
begin
WriteLn(‘Error Open CLient’+IntToStr(ResultInt));
Exit;
end;

ResultInt:=WlanEnumInterfaces(hClient, nil, @pInterface);
if ResultInt<> ERROR_SUCCESS then
begin
WriteLn(‘Error Enum Interfaces ‘+IntToStr(ResultInt));
exit;
end;

for i := 0 to pInterface^.dwNumberOfItems – 1 do
begin
Writeln(‘Interface ‘ + pInterface^.InterfaceInfo[i].strInterfaceDescription);
WriteLn(‘GUID ‘ + GUIDToString(pInterface^.InterfaceInfo[i].InterfaceGuid));
Writeln(”);
pInterfaceGuid:= @pInterface^.InterfaceInfo[pInterface^.dwIndex].InterfaceGuid;

ResultInt:=WlanGetAvailableNetworkList(hClient,pInterfaceGuid,WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES,nil,pAvailableNetworkList);
if ResultInt<> ERROR_SUCCESS then
begin
WriteLn(‘Error WlanGetAvailableNetworkList ‘+IntToStr(ResultInt));
Exit;
end;

for j := 0 to pAvailableNetworkList^.dwNumberOfItems – 1 do
Begin
WriteLn(Format(‘Profile %s’,[WideCharToString(pAvailableNetworkList^.Network[j].strProfileName)]));
SDummy:=PAnsiChar(@pAvailableNetworkList^.Network[j].dot11Ssid.ucSSID);
WriteLn(Format(‘NetworkName %s’,[SDummy]));
WriteLn(Format(‘Signal Quality %d ‘,[pAvailableNetworkList^.Network[j].wlanSignalQuality])+’%’);
//SDummy := GetEnumName(TypeInfo(Tndu_DOT11_AUTH_ALGORITHM),integer(pAvailableNetworkList^.Network[j].dot11DefaultAuthAlgorithm)) ;
SDummy:=DOT11_AUTH_ALGORITHM_To_String(pAvailableNetworkList^.Network[j].dot11DefaultAuthAlgorithm);
WriteLn(Format(‘Auth Algorithm %s ‘,[SDummy]));
SDummy:=DOT11_CIPHER_ALGORITHM_To_String(pAvailableNetworkList^.Network[j].dot11DefaultCipherAlgorithm);
WriteLn(Format(‘Auth Algorithm %s ‘,[SDummy]));
Writeln(”);
End;
end;
finally
WlanCloseHandle(hClient, nil);
end;
end;
begin
try
Scan();
Readln;
except
on E:Exception do
Writeln(E.Classname, ‘: ‘, E.Message);
end;
end.
[/sourcecode]

ScanWifi Image
ScanWifi Image

25 responses

  1. Bill Miller Avatar
    Bill Miller

    Two of us tested this code on 2 different pc’s with Delphi 2007 and Delphi 2010. One pc was in Norway, the other in the United States.

    The code compiles and functions well on both systems… except Delphi 2010 reports 6 warnings:
    [DCC Warning] nduWlanTypes.pas(38): W1012 Constant expression violates subrange bounds
    [DCC Warning] nduWlanTypes.pas(39): W1012 Constant expression violates subrange bounds
    [DCC Warning] nduWlanTypes.pas(62): W1012 Constant expression violates subrange bounds
    [DCC Warning] nduWlanTypes.pas(63): W1012 Constant expression violates subrange bounds
    [DCC Warning] nduWinDot11.pas(32): W1012 Constant expression violates subrange bounds
    [DCC Warning] nduWinDot11.pas(33): W1012 Constant expression violates subrange bounds

    Thank-you for writing the post.

  2. Works fine under Delphi 7 in France XP SP3 / INTEL 5300 AGN

    Would be nice to also get channel number !

  3. […] time ago I wrote an article about how list the Wifi networks using Delphi and the Native Wifi API, today I will show you how […]

  4. Hi,
    I’m trying to download the headers but link is broken… Where can i download it?

    Thank you, and great job!!!

  5. Nice example!!!
    But how to use a WlanGetNetworkBssList???? Dont’t work… help me, please…

    1. What are you tried so far?

  6. Hi, great work, but the SSID returns non readable on Windows 7 64bit, I dont have an XP machine to test at the moment, I found an article relating to this issue in VB but the header translation needs updating http://www.vbforums.com/showthread.php?547916-List-available-wireless-networks-(using-WMI)-Help-pls

    Hope you can help

  7. Hi, great work on the API however there seems to be an issue with the headers I think MS changed the output!, the SSID returns unreadable on windows 7 64bit, I understand this is due to a change in the format of the returned value, I found this related article http://www.vbforums.com/showthread.php?547916-List-available-wireless-networks-(using-WMI)-Help-pls hopefully you will be able to update the header conversation.

    I am using windows 7 64bit and delphi 2010

    Many thanks

  8. Hi, thought I provide an update I changed line 88 to

    SDummy:=AnsiChar(@pAvailableNetworkList^.Network[j].dot11Ssid.ucSSID);

    And it is now returning the correct SSID name.

    1. The problem was related to the UNICODE strings, the original post was made using Delphi 2007 which is not UNICODE. I just fix the sample code. Thanks for the report.

  9. Hi Again, is there a method to display the AP MAC Address in the output?

  10. Is there a way to check if one of the connections is active?

    1. You must use the WlanQueryInterface method and check if the value of the iState field is wlan_interface_state_connected. for a sample check the MSDN documentation.

      1. Hey, Rodrigo.

        It’s working.

        Here is how I used it
        ResultInt := WlanQueryInterface(hClient, pInterfaceGuid,
        wlan_intf_opcode_interface_state, nil, @pdwDataSize,
        @ppData, nil);if (ResultInt = ERROR_SUCCESS) then
        if ResultInt = ERROR_SUCESS then
        WriteLn(Format(‘Status: %s’, [
        WLAN_INTERFACE_STATE_To_String(ppData^.isState)]))

        the function WLAN_INTERFACE_STATE_To_String is simple as:

        function WLAN_INTERFACE_STATE_To_String(
        Dummy: Tndu_WLAN_INTERFACE_STATE): string;
        var
        s: string;
        begin
        s := ”;
        case Dummy of
        wlan_interface_state_not_ready: s :=’Not ready’;
        wlan_interface_state_connected: s := ‘Connected’;
        wlan_interface_state_ad_hoc_network_formed: s := ‘ad hoc network’;
        wlan_interface_state_disconnecting: s := ‘Disconnecting’;
        wlan_interface_state_disconnected: s := ‘Disconnected’;
        wlan_interface_state_associating: s := ‘Associating’;
        wlan_interface_state_discovering: s := ‘Discovering’;
        wlan_interface_state_authenticating: s := ‘Authenticating’;
        end;
        Result := s;
        end;

        That’s it.

        Thank you.

  11. Hello !

    I’m desperately looking for a good sample using right headers and use of WlanGetNetworkBssList !
    The first Tndu_WLAN_BSS_ENTRY item return seems correct but the following ones are completely scrambled….
    I’m unable to download the “fixed” header you provided (broken Dropbox link).
    Would you please post again a full package ?

    Thanks for this excellent site !

    1. Hi the updated headers of the Native Wifi API are hosted on github.

      1. Then there is a bug in the Tndu_WLAN_BSS_ENTRY definition

        dot11Ssid: Tndu_DOT11_SSID;
        uPhyId: ulong;
        dot11Bssid: Tndu_DOT11_MAC_ADDRESS;
        dot11BssType: Tndu_DOT11_BSS_TYPE;
        //dot11BssPhyType: Tndu_DOT11_PHY_TYPE;
        lRssi: long;
        uLinkQuality: ulong;
        bInRegDomain: Boolean;

        should be replaced by

        dot11Ssid: Tndu_DOT11_SSID;
        uPhyId: ulong;
        dot11Bssid: Tndu_DOT11_MAC_ADDRESS;
        dot11BssType: Tndu_DOT11_BSS_TYPE;
        dot11BssPhyType: ulonglong;
        lRssi: long;
        uLinkQuality: ulong;
        bInRegDomain: Boolean;

        otherwise, data are “shifted” in the record, causing the problem I faced with initial headers.
        With my modification, function works fine.

  12. When using WlanQueryInterface to retrieve stats about my adapter, could you explain to me why multiple PHY are reported for a single adapter ? Where can i find the “description” of these PHY interfaces ?

  13. Another comment, in Tndu_DOT11_PHY_TYPE, there are 2 types missing :
    dot11_phy_type_ht = 7,
    dot11_phy_type_vht = 8,
    as per https://msdn.microsoft.com/en-us/library/windows/desktop/ms706015%28v=vs.85%29.aspx

    required for 802.11n and 802.11ac

    1. Thanks for your comments. I will check and update the repository ASAP. Also you can make a pull request with your changes.

      1. I’m not familiar with GitHub… i’d prefer that you do the fix :)

        I’ll post values for 802.11ad as soon as possible

  14. Hello,

    Final definition of the currently incorrect nduWlanAPI :

    Tndu_WLAN_BSS_ENTRY = record
    dot11Ssid: Tndu_DOT11_SSID;
    uPhyId: ulong;
    dot11Bssid: Tndu_DOT11_MAC_ADDRESS;
    filler1:array[0..1]of byte;
    dot11BssType: Tndu_DOT11_BSS_TYPE;
    filler2:array[0..2]of byte;
    dot11BssPhyType: ulong;
    lRssi: long;
    uLinkQuality: ulong;
    bInRegDomain: Boolean;
    usBeaconPeriod: ushort;
    ullTimestamp: ulonglong;
    ullHostTimestamp: ulonglong;
    usCapabilityInformation: ushort;
    ulChCenterFrequency: ulong;
    wlanRateSet: Tndu_WLAN_RATE_SET;
    ulIeOffset: ulong;
    ulIeSize: ulong;
    end;

  15. Any update of these source code files ?

    1. (Try this link for a fixed and updated version of the Native Wifi Delphi headers => Error 404)

Leave a Reply