New Lexer:
; Ping function by Drugwash April 29, 2010
; v2.0
;*********************************
ping_(adr, data, timeout)
{
static reply
ErrorLevel = 0
SetFormat, IntegerFast, H
cAdr := DllCall("wsock32\inet_addr", UInt, &adr, UInt) ; convert address to 32bit UInt
if cAdr = 0xFFFFFFFF
cAdr := DllCall("ws2_32\inet_addr", str, adr, Int) ; second attempt at conversion, using ws2_32
if cAdr = 0xFFFFFFFF
{
ErrorLevel = 1
return err := "Error: Cannot convert address to UInt."
}
; test for function presence since it's located in different libs through various OS
hLib := DllCall("LoadLibrary", str, "iphlpapi.dll")
if hLib
{
hPrAdr := DllCall("GetProcAddress", UInt, hLib, str, "IcmpCreateFile")
if hPrAdr
; hPort := DllCall("iphlpapi\IcmpCreateFile", UInt) ; open a port (iphlpapi.dll in XP+)
hPort := DllCall(hPrAdr, UInt) ; open a port (iphlpapi.dll in XP+)
else
DllCall("FreeLibrary", UInt, hLib)
}
if !hPort
hPort := DllCall("icmp\IcmpCreateFile", UInt) ; open a port (icmp.dll in Win2000 and lower)
if !hPort
{
ErrorLevel = 1
return err := "Error: Cannot open port."
}
SetFormat, Integer, D
szreply = 278 ; ICMP_ECHO_REPLY structure
VarSetCapacity(reply, szreply, 0)
DllCall("icmp\IcmpSendEcho", UInt, hPort, UInt, cAdr, UInt, &data, UInt, StrLen(data), UInt, NULL, UInt, &reply, UInt, szreply, UInt, timeout, UInt)
errcode := NumGet(reply, 4, "UInt") ; check for status
errcode := errcode <> 0 ? errcode : errcode+11000
if errcode = 11001 ; function returned 'buffer too small' so we increase it and try again
{
VarSetCapacity(reply, NumGet(reply, 12, "UShort")+16)
DllCall("icmp\IcmpSendEcho", UInt, hPort, UInt, cAdr, UInt, &data, UInt, StrLen(data), UInt, NULL, UInt, &reply, UInt, szreply, UInt, timeout, UInt)
errcode := NumGet(reply, 4, "UInt") ; another check for status on 2-nd attempt
errcode := errcode <> 0 ? errcode : errcode+11000
}
err := ping_GetError(errcode, "IcmpSendEcho") ; error handling
DllCall("icmp\IcmpCloseHandle", UInt, hPort) ; close port
if errcode != 11000 ; IP_SUCCESS
{
ErrorLevel = 1
return err
}
else
; on success returns ICMP_ECHO_REPLY structure address for external processing of data
return err := &reply
}
;*********************************
ping_GetError(code, func="[ukn]") ; error translation
{
str := "Success|Reply buffer too small|Destination network unreachable|Destination host unreachable|Destination protocol unreachable|Destination port unreachable|Insufficient IP resources|Bad IP option specified|Hardware error|Packet too big|Request timed out|Bad request|Bad route|TTL expired in transit|TTL expired during fragment reassembly|Parameter problem|Datagrams are arriving too fast to be processed and datagrams may have been discarded|IP option too big|Bad destination|General failure (possible malformed ICMP packets)"
Loop, Parse, str, |
{
if (code = 11000 + A_Index - 1) || (A_Index = 20 && code = 11050)
return err := "Error " code " [" A_LoopField "] in function " func
}
return err := "Function " func " returned " code
}
;*********************************
ping_Host2IP(name)
{
ErrorLevel = 0
type := SubStr(name, 1, 1)
if type is alpha
{
hostent := DllCall("ws2_32\gethostbyname", UInt, &name, UInt) ; http://msdn.microsoft.com/en-us/library/ms738524(VS.85).aspx
if !hostent
{
err := DllCall("ws2_32\WSAGetLastError")
ErrorLevel = 1
return err
}
; string containing protocol types (mainly for debug purposes)
str := "local to host (pipes, portals)|internetwork: UDP, TCP, etc.|arpanet imp addresses|pup protocols: e.g. BSP|mit CHAOS protocols|XEROX NS protocols or IPX protocols: IPX, SPX, etc.|ISO protocols or OSI is ISO|european computer manufacturers|datakit protocols|CCITT protocols, X.25 etc|IBM SNA|DECnet|Direct data link interface|LAT|NSC Hyperchannel|AppleTalk|NetBios-style addresses|VoiceView|Protocols from Firefox|Unknown - Somebody is using this!|Banyan|Native ATM Services|Internetwork Version 6|Microsoft Wolfpack|IEEE 1284.4 WG AF"
ptrName := NumGet(hostent+0, 0, "UInt")
pt := NumGet(hostent+0, 8, "UShort")
Loop, Parse, str, |
if (A_Index = pt)
type := A_LoopField
len := NumGet(hostent+0, 10, "UShort")
ptrAddress := NumGet(hostent+0, 12, "UInt")
ptrIPAddress := NumGet(ptrAddress+0, 0, "UInt")
strAddress := NumGet(ptrIPAddress+0, 0, "UInt")
VarSetCapacity(adr, 16, 32)
DllCall("lstrcpy", UInt, &adr, UInt, DllCall("ws2_32\inet_ntoa", UInt, strAddress))
VarSetCapacity(adr, -1)
VarSetCapacity(pname, 260, 32)
DllCall("lstrcpy", UInt, &pname, UInt, ptrName)
VarSetCapacity(pname, -1)
return adr
}
else
return name
}
;*********************************
ping_DW2IP(adr)
{
res := NumGet(adr+0, 0, "Uchar") "." NumGet(adr+0, 1, "Uchar") "." NumGet(adr+0, 2, "Uchar") "." NumGet(adr+0, 3, "Uchar")
return res
}
;*********************************
ping(addr, data="AHK ping test", timeout="500")
{
; Sockets initialization http://msdn.microsoft.com/en-us/library/ms741563(VS.85).aspx
VarSetCapacity(WSADATA, 12+257+129, 0) ; WSADATA structure initialization
err := DllCall("wsock32\WSAStartup", Short, 0x101, UInt, &WSADATA, UInt)
if err > 0
{
ErrorLevel = 1
err = Socket initialization error %err% ; Failed to initialize sockets
goto error
}
address := ping_Host2IP(addr) ; address conversion to DWORD
err := ping_GetError(address, "ping_Host2IP") ; error handling
if ErrorLevel
goto error
err := ping_(address, data, timeout) ; ping function call
error:
EL := ErrorLevel
DllCall("wsock32\WSACleanup") ; Sockets cleanup & close
ErrorLevel := EL
return err
}