I was looking for a ip scanner in PureBasic and found this post : http://forums.purebasic.com/english/vie ... 12&t=11009
It was buggy because of the 19 years old code so I updated and upgraded it.
Code: Select all
; Inspired from fweil
; http://forums.purebasic.com/english/viewtopic.php?f=12&t=11009
Import "Ws2_32.lib"
getnameinfo(*pSockAddr, SockaddrLength.i, *pNodeBuffer, NodeBufferSize.l, *ServiceBuffer, ServiceBufferSize.l, Flags.i)
EndImport
Enumeration
#Window_Main
#StatusBar
#Gadget_Text_Start
#Gadget_Text_End
#Gadget_Button_OK
#Gadget_Button_Cancel
#Gadget_IP_Start
#Gadget_IP_End
#Gadget_ListIcon
#Gadget_ShowOffline
#Gadget_SearchHostName
EndEnumeration
Enumeration #PB_Event_FirstCustomValue
#EventProcessingFinished
EndEnumeration
Enumeration ThreadState
#InProgress
#Interrupted
#Done
EndEnumeration
Enumeration HostState
#Online
#Offline
EndEnumeration
Structure PINGINFO
IPAddress.i
RoundTrip.i
HostName.s
HostState.i
ThreadState.i
ThreadID.i
ItemAdded.b
EndStructure
#MaxThreads = 512
Global Run.b
Global TotalThreads, CurrentConnection.s
Global OldTotalConnections, OldTotalThreads, OldCurrentConnection.s
Global MainThreadID
Global TotalAddresses, ScannedAddresses
Global SearchHostName = #True
Global Dim PingInfoArray.PINGINFO(1)
Procedure TestConnectionToIP(ArrayIndex)
PingInfoArray(ArrayIndex)\ThreadState = #InProgress
Protected sIPAddress.s = IPString(PingInfoArray(ArrayIndex)\IPAddress) ;IPString(IPAddress)
#PING_TIMEOUT = 1000
Protected RoundTrip
Protected *Echo.ICMP_ECHO_REPLY = AllocateStructure(ICMP_ECHO_REPLY)
Protected EchoMessage.s = "Ping"
Protected EchoSize = SizeOf(ICMP_ECHO_REPLY) + Len(EchoMessage)
Protected hFile = IcmpCreateFile_()
Protected lngResult = IcmpSendEcho_(hFile, PingInfoArray(ArrayIndex)\IPAddress, EchoMessage, Len(EchoMessage), 0, *Echo, EchoSize, #PING_TIMEOUT)
If lngResult > 0
RoundTrip = *Echo\RoundTripTime
PingInfoArray(ArrayIndex)\HostState = #Online
Else
RoundTrip = -1
PingInfoArray(ArrayIndex)\HostState = #Offline
EndIf
lngResult = IcmpCloseHandle_(hFile)
If RoundTrip >= 0
If SearchHostName
Protected *NodeBuffer, dwRetval
Protected WSAData_.WSADATA
Protected saGNI.SOCKADDR_IN
*NodeBuffer = AllocateMemory(1024)
If *NodeBuffer
WSAStartup_(1, @WSAData_)
saGNI\sin_family = #AF_INET
saGNI\sin_addr = PingInfoArray(ArrayIndex)\IPAddress
dwRetval = getnameinfo(@saGNI, SizeOf(SOCKADDR_IN), *NodeBuffer, MemorySize(*NodeBuffer), 0, 0, 0)
If dwRetval = 0
PingInfoArray(ArrayIndex)\HostName = PeekS(*NodeBuffer, -1, #PB_Ascii)
EndIf
WSACleanup_()
FreeMemory(*NodeBuffer)
EndIf
EndIf
If RoundTrip = 0 : RoundTrip = 1 : EndIf ; 1 ms round trip time minimum
PingInfoArray(ArrayIndex)\RoundTrip = RoundTrip
EndIf
TotalThreads - 1
ScannedAddresses + 1
FreeStructure(*Echo)
PingInfoArray(ArrayIndex)\ThreadState = #Done
PostEvent(#EventProcessingFinished)
EndProcedure
Procedure RunScan(a=0)
Protected IPAddress, sIPAddress.s
Protected i = 0
Delay(500)
Protected StartAddress = GetGadgetState(#Gadget_IP_Start)
Protected EndAddress = GetGadgetState(#Gadget_IP_End)
Protected iStartAddress = IPAddressField(StartAddress, 0) << 24 + IPAddressField(StartAddress, 1) << 16 + IPAddressField(StartAddress, 2) << 8 + IPAddressField(StartAddress, 3)
Protected iEndAddress = IPAddressField(EndAddress, 0) << 24 + IPAddressField(EndAddress, 1) << 16 + IPAddressField(EndAddress, 2) << 8 + IPAddressField(EndAddress, 3)
TotalAddresses = iEndAddress - iStartAddress + 1
Dim PingInfoArray(TotalAddresses)
For iIPAddress = iStartAddress To iEndAddress
IPAddress = MakeIPAddress(IPAddressField(iIPAddress, 3), IPAddressField(iIPAddress, 2), IPAddressField(iIPAddress, 1), IPAddressField(iIPAddress, 0))
sIPAddress.s = IPString(IPAddress)
CurrentConnection = "Scanning " + sIPAddress
PingInfoArray(i)\IPAddress = IPAddress
PingInfoArray(i)\ItemAdded = #False
PingInfoArray(i)\ThreadID = CreateThread(@TestConnectionToIP(), i)
i + 1
TotalThreads + 1
If TotalThreads > #MaxThreads
While TotalThreads > #MaxThreads / 2
Delay(500)
Wend
EndIf
Delay(10) ; between each ping
Next
Run = #False
MainThreadID = 0
EndProcedure
Procedure Stop()
Run = #False
CurrentConnection = "Canceling ..."
If IsThread(MainThreadID)
CurrentConnection = "Canceling " + Str(MainThreadID)
KillThread(MainThreadID)
MainThreadID = 0
EndIf
CurrentConnection = "Done"
EndProcedure
Procedure DoWeRun()
If MainThreadID <> 0
Stop()
EndIf
FreeArray(PingInfoArray())
ClearGadgetItems(#Gadget_ListIcon)
Run = #True
ScannedAddresses = 0
TotalAddresses = 0
CurrentConnection = "Scanning ..."
MainThreadID = CreateThread(@RunScan(), 0)
EndProcedure
;
;
;
;
Define sStartAddress.s = "192.168.0.1"
Define sEndAddress.s = "192.168.0.254"
Define StartAddress.l
Define EndAddress.l
Define Quit = #False
Define WindowXSize = 640
Define WindowYSize = 480
Define RoundTripTime$ = ""
Define OnlineHostCount
Run = #False
If OpenWindow(#Window_Main, 0, 0, WindowXSize, WindowYSize, "Ip Scanner", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateStatusBar(#StatusBar, WindowID(#Window_Main))
AddStatusBarField(250)
AddStatusBarField(140)
AddStatusBarField(140)
AddStatusBarField(110)
EndIf
TextGadget(#Gadget_Text_Start, 10, 10, 80, 20, "Start address")
TextGadget(#Gadget_Text_End, 10, 30, 80, 20, "End address")
ButtonGadget(#Gadget_Button_OK, 230, 10, 60, 20, "Go")
ButtonGadget(#Gadget_Button_Cancel, 230, 30, 60, 20, "Cancel")
IPAddressGadget(#Gadget_IP_Start, 100, 10, 120, 20)
IPAddressGadget(#Gadget_IP_End, 100, 30, 120, 20)
ListIconGadget(#Gadget_ListIcon, 10, 50, WindowXSize - 20, WindowYSize - 80, "Host found", 120)
AddGadgetColumn(#Gadget_ListIcon, 1, "HostName", 100)
AddGadgetColumn(#Gadget_ListIcon, 2, "Time", 80)
CheckBoxGadget(#Gadget_ShowOffline, 360, 10, 120, 20, "Show offline hosts")
SetGadgetState(#Gadget_ShowOffline, #PB_Checkbox_Checked)
CheckBoxGadget(#Gadget_SearchHostName, 360, 30, 120, 20, "Get hostname")
SetGadgetState(#Gadget_SearchHostName, #PB_Checkbox_Checked)
SetGadgetState(#Gadget_IP_Start, MakeIPAddress(Val(StringField(sStartAddress, 1, ".")), Val(StringField(sStartAddress, 2, ".")), Val(StringField(sStartAddress, 3, ".")), Val(StringField(sStartAddress, 4, "."))))
SetGadgetState(#Gadget_IP_End, MakeIPAddress(Val(StringField(sEndAddress, 1, ".")), Val(StringField(sEndAddress, 2, ".")), Val(StringField(sEndAddress, 3, ".")), Val(StringField(sEndAddress, 4, "."))))
Repeat
Select WindowEvent()
Case #PB_Event_CloseWindow
Quit = #True
Case #PB_Event_Gadget
Select EventGadget()
Case #Gadget_IP_Start
sStartAddress = GetGadgetText(#Gadget_IP_Start)
StartAddress = GetGadgetState(#Gadget_IP_Start)
Case #Gadget_IP_End
sEndAddress = GetGadgetText(#Gadget_IP_End)
EndAddress = GetGadgetState(#Gadget_IP_End)
Case #Gadget_Button_OK
OnlineHostCount = 0
If GetGadgetState(#Gadget_SearchHostName) = #PB_Checkbox_Checked
SearchHostName = #True
Else
SearchHostName = #False
EndIf
DoWeRun()
Case #Gadget_Button_Cancel
Stop()
EndSelect
Case #EventProcessingFinished
; pour afficher les ip dans l'ordre
For i = 0 To ArraySize(PingInfoArray())
If PingInfoArray(i)\ThreadState = #Done
If Not PingInfoArray(i)\ItemAdded
If GetGadgetState(#Gadget_ShowOffline) = #PB_Checkbox_Unchecked
If PingInfoArray(i)\HostState = #Offline
Continue
EndIf
EndIf
If PingInfoArray(i)\HostState = #Offline
RoundTripTime$ = ""
Else
RoundTripTime$ = Str(PingInfoArray(i)\RoundTrip)
OnlineHostCount + 1
EndIf
AddGadgetItem(#Gadget_ListIcon, -1, IPString(PingInfoArray(i)\IPAddress) + Chr(10) + PingInfoArray(i)\HostName + Chr(10) + RoundTripTime$)
PingInfoArray(i)\ItemAdded = #True
StatusBarText(#StatusBar, 1, Str(OnlineHostCount) + " Online Hosts")
EndIf
Else
Break
EndIf
Next
EndSelect
If OldCurrentConnection <> CurrentConnection
OldCurrentConnection = CurrentConnection
StatusBarText(#StatusBar, 0, CurrentConnection)
EndIf
If OldScannedAddresses <> ScannedAddresses
OldScannedAddresses = ScannedAddresses
StatusBarText(#StatusBar, 2, Str(ScannedAddresses) + " / " + Str(TotalAddresses) + " IP Addresses")
EndIf
If OldTotalThreads <> TotalThreads
OldTotalThreads = TotalThreads
StatusBarText(#StatusBar, 3, Str(TotalThreads) + " Threads")
EndIf
Delay(1)
Until Quit
Stop()
EndIf
End