Converting Delphi code to list all network adapters on a Windows system to FPC lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- vfclists · 2014-05-06 12:06 I am trying out some Delphi code to obtain the list of network adapters on a system, based on code in this stackoverflow question: http://stackoverflow.com/questions/18378630/get-information-about-the- installed-network-adapters. The code uses the Windows and Winsock unit and when I try to run the solution offered by the guy with the approved answer -  JRL - it seems to cause some kind of buffer overrun or stack overflow which causes it to use a lot of CPU and it gets terminated. Can someone look into it and explain the crash? It makes a lot of Windows system calls and I suspect there may be some mismatch between the API calls, the data structures and FreePascal. I have added the code below and have attached a project for testing it.  The last answer in that question offers another solution, but I will discuss that in a separate question. Code: [Select]Unit USock; Interface Uses Windows, Winsock; { Unit to identify the network interfaces   This code requires at least Win98/ME/2K, 95 OSR 2 or NT service pack #3   as WinSock 2 is used (WS2_32.DLL) } // Constants found in manual on non-officially documented M$ Winsock functions Const SIO_GET_INTERFACE_LIST = $4004747F;       IFF_UP                 = $00000001;       IFF_BROADCAST          = $00000002;       IFF_LOOPBACK           = $00000004;       IFF_POINTTOPOINT       = $00000008;       IFF_MULTICAST          = $00000010; Type SockAddr_Gen          = Packed Record                                AddressIn             : SockAddr_In;                                Padding               : Packed Array [0..7] of Byte;                              end;      Interface_Info        = Record                                iiFlags               : u_Long;                                iiAddress             : SockAddr_Gen;                                iiBroadcastAddress    : SockAddr_Gen;                                iiNetmask             : SockAddr_Gen;                              end;      tNetworkInterface     = Record                                ComputerName          : String;                                AddrIP                : String;                                SubnetMask            : String;                                AddrNet               : String;                                AddrLimitedBroadcast  : String;                                AddrDirectedBroadcast : String;                                IsInterfaceUp         : Boolean;                                BroadcastSupport      : Boolean;                                IsLoopback            : Boolean;                              end;      tNetworkInterfaceList = Array of tNetworkInterface; Function WSAIoctl (aSocket              : TSocket;                    aCommand             : DWord;                    lpInBuffer           : Pointer;                    dwInBufferLen        : DWord;                    lpOutBuffer          : Pointer;                    dwOutBufferLen       : DWord;                    lpdwOutBytesReturned : LPDWord;                    lpOverLapped         : Pointer;                    lpOverLappedRoutine  : Pointer) : Integer; stdcall; external 'WS2_32.DLL'; Function GetNetworkInterfaces (Var aNetworkInterfaceList : tNetworkInterfaceList): Boolean; implementation Function GetNetworkInterfaces (Var aNetworkInterfaceList : tNetworkInterfaceList): Boolean; // Returns a complete list the of available network interfaces on a system (IPv4) // Copyright by Dr. Jan Schulz, 23-26th March 2007 // This version can be used for free and non-profit projects. In any other case get in contact // Written with information retrieved from MSDN // www.code10.net Var aSocket             : TSocket;     aWSADataRecord      : WSAData;     NoOfInterfaces      : Integer;     NoOfBytesReturned   : u_Long;     InterfaceFlags      : u_Long;     NameLength          : DWord;     pAddrIP             : SockAddr_In;     pAddrSubnetMask     : SockAddr_In;     pAddrBroadcast      : Sockaddr_In;     DirBroadcastDummy   : In_Addr;     NetAddrDummy        : In_Addr;     Buffer              : Array [0..30] of Interface_Info;     i                   : Integer; Begin   Result := False;   SetLength (aNetworkInterfaceList, 0);   // Startup of old the WinSock   // WSAStartup ($0101, aWSADataRecord);   // Startup of WinSock2   WSAStartup(MAKEWORD(2, 0), aWSADataRecord);   // Open a socket   aSocket := Socket (AF_INET, SOCK_STREAM, 0);   // If impossible to open a socket, not worthy to go any further   If (aSocket = INVALID_SOCKET) THen Exit;   Try     If WSAIoCtl (aSocket, SIO_GET_INTERFACE_LIST, NIL, 0,                  @Buffer, 1024, @NoOfBytesReturned, NIL, NIL) <> SOCKET_ERROR THen     Begin       NoOfInterfaces := NoOfBytesReturned  Div SizeOf (Interface_Info);       SetLength (aNetworkInterfaceList, NoOfInterfaces);       // For each of the identified interfaces get:       For i := 0 to NoOfInterfaces - 1 do       Begin         With aNetworkInterfaceList[i] do         Begin           // Get the name of the machine           NameLength := MAX_COMPUTERNAME_LENGTH + 1;           SetLength (ComputerName, NameLength)  ;           If Not GetComputerName (PChar (Computername), NameLength) THen ComputerName := '';           // Get the IP address           pAddrIP                  := Buffer[i].iiAddress.AddressIn;           AddrIP                   := string(inet_ntoa (pAddrIP.Sin_Addr));           // Get the subnet mask           pAddrSubnetMask          := Buffer[i].iiNetMask.AddressIn;           SubnetMask               := string(inet_ntoa (pAddrSubnetMask.Sin_Addr));           // Get the limited broadcast address           pAddrBroadcast           := Buffer[i].iiBroadCastAddress.AddressIn;           AddrLimitedBroadcast     := string(inet_ntoa (pAddrBroadcast.Sin_Addr));           // Calculate the net and the directed broadcast address           NetAddrDummy.S_addr      := Buffer[i].iiAddress.AddressIn.Sin_Addr.S_Addr;           NetAddrDummy.S_addr      := NetAddrDummy.S_addr And Buffer[i].iiNetMask.AddressIn.Sin_Addr.S_Addr;           DirBroadcastDummy.S_addr := NetAddrDummy.S_addr Or Not Buffer[i].iiNetMask.AddressIn.Sin_Addr.S_Addr;           AddrNet                  := string(inet_ntoa ((NetAddrDummy)));           AddrDirectedBroadcast    := string(inet_ntoa ((DirBroadcastDummy)));           // From the evaluation of the Flags we receive more information           InterfaceFlags           := Buffer[i].iiFlags;           // Is the network interface up or down ?           If (InterfaceFlags And IFF_UP) = IFF_UP THen IsInterfaceUp := True                                                   Else IsInterfaceUp := False;           // Does the network interface support limited broadcasts ?           If (InterfaceFlags And IFF_BROADCAST) = IFF_BROADCAST THen BroadcastSupport := True                                                                 Else BroadcastSupport := False;           // Is the network interface a loopback interface ?           If (InterfaceFlags And IFF_LOOPBACK) = IFF_LOOPBACK THen IsLoopback := True                                                               Else IsLoopback := False;         end;       end;     end;   Except     //Result := False;   end;   // Cleanup the mess   CloseSocket (aSocket);   WSACleanUp;   Result := True; end; end. ---------------------------------------------------------------------- Blaazen · 2014-05-06 13:05 Hi, I tested attached project under Wine and it seems fine. I got no crash and output to memo is: Code: [Select]6.5.2014 15:01:15 : #                          : 0 Name                       : msi-NB IP-Address                 : 192.168.2.4 Subnet mask                : 255.255.255.0 Net address                : 192.168.2.0 Limited broadcast address  : 192.168.2.255 Directed Broadcast address : 192.168.2.255 Interface up               : True Broadcast supported        : True Loopback interface         : Falsewhich seems correct too. ---------------------------------------------------------------------- vfclists · 2014-05-06 13:09 Quote from: Blaazen on May 06, 2014, 03:05:46 pmHi, I tested attached project under Wine and it seems fine. I got no crash and output to memo is: Code: [Select]6.5.2014 15:01:15 : #                          : 0 Name                       : msi-NB IP-Address                 : 192.168.2.4 Subnet mask                : 255.255.255.0 Net address                : 192.168.2.0 Limited broadcast address  : 192.168.2.255 Directed Broadcast address : 192.168.2.255 Interface up               : True Broadcast supported        : True Loopback interface         : Falsewhich seems correct too. Thanks. Can you test it on a proper Windows system and see? ---------------------------------------------------------------------- Blaazen · 2014-05-06 13:13 Unfortunately no. I have no real Windows here, only Wine. ---------------------------------------------------------------------- marcov · 2014-05-06 13:24 Converted to console app, both the .lpr and unit compiled with -Sd (to avoid trouble with alignment): D:\src\listWindowsNICs>listwindowsnics 5/6/2014 15:22:52 : Size of aNetInterfaceList - 1 #                          : 0 Name                       : CANDMARLAPTOP IP-Address                 : 127.0.0.1 Subnet mask                : 255.0.0.0 Net address                : 127.0.0.0 Limited broadcast address  : 0.0.0.0 Directed Broadcast address : 127.255.255.255 Interface up               : True Broadcast supported        : False Loopback interface         : True #                          : 1 Name                       : CANDMARLAPTOP IP-Address                 : 192.168.187.110 Subnet mask                : 255.255.255.0 Net address                : 192.168.187.0 Limited broadcast address  : 255.255.255.255 Directed Broadcast address : 192.168.187.255 Interface up               : True Broadcast supported        : True Loopback interface         : False It doesn't seem to detect my wireless card though. ---------------------------------------------------------------------- vfclists · 2014-05-06 14:20 Quote from: marcov on May 06, 2014, 03:24:17 pmConverted to console app, both the .lpr and unit compiled with -Sd (to avoid trouble with alignment): D:\src\listWindowsNICs>listwindowsnics 5/6/2014 15:22:52 : Size of aNetInterfaceList - 1 #                          : 0 Name                       : CANDMARLAPTOP IP-Address                 : 127.0.0.1 Subnet mask                : 255.0.0.0 Net address                : 127.0.0.0 Limited broadcast address  : 0.0.0.0 Directed Broadcast address : 127.255.255.255 Interface up               : True Broadcast supported        : False Loopback interface         : True #                          : 1 Name                       : CANDMARLAPTOP IP-Address                 : 192.168.187.110 Subnet mask                : 255.255.255.0 Net address                : 192.168.187.0 Limited broadcast address  : 255.255.255.255 Directed Broadcast address : 192.168.187.255 Interface up               : True Broadcast supported        : True Loopback interface         : False It doesn't seem to detect my wireless card though. Thanks. I tested it on 2 other PCs and it worked fine. I suspect the problem may be on the development system. Where do you set the -Sd option in Lazarus? What is the proper name for it? ---------------------------------------------------------------------- Blaazen · 2014-05-06 14:36 AFAIK -Sd is {$mode delphi} ---------------------------------------------------------------------- marcov · 2014-05-06 14:53 Yes. Note that a $mode in the sourcecode overrules anything on the cmdline. So remove $mode objfpc's if you have them ---------------------------------------------------------------------- vfclists · 2014-05-06 15:25 Do modes apply to the whole project or can they change according to the unit? Quote from: marcov on May 06, 2014, 04:53:59 pmYes. Note that a $mode in the sourcecode overrules anything on the cmdline. So remove $mode objfpc's if you have them ---------------------------------------------------------------------- Leledumbo · 2014-05-06 15:28 Quote from: vfclists on May 06, 2014, 05:25:21 pmDo modes apply to the whole project or can they change according to the unit? http://www.freepascal.org/docs-html/user/userse33.html