!include LogicLib.nsh
!ifndef AF_INET
!define AF_INET 2
!define SOCK_STREAM 1
!define IPPROTO_TCP 6
!define INADDR_ANY 0
!define SOL_SOCKET 0xffff
!define /math SO_EXCLUSIVEADDRUSE 0xffffffff ^ 0x4
!endif
Function QueryCanBindToIP4TCPPort
Exch $0
Push $1
Push $2
Push $0 ;Push port
System::Alloc 16 ;WSADATA & sockaddr_in
System::Call 'Ws2_32::WSAStartup(i 2,isr2)i.r0'
${If} $0 = 0
System::Call 'Ws2_32::socket(i ${AF_INET},i ${SOCK_STREAM},i ${IPPROTO_TCP})i.r1 ?e'
Pop $0
${If} $1 <> -1
System::Call 'Ws2_32::setsockopt(ir1,i ${SOL_SOCKET},i ${SO_EXCLUSIVEADDRUSE},*i 1,i4)i.r0'
System::Call 'Ws2_32::htons(iss)i.s' ;Convert port (and leaves the original push on the stack)
;Skipping htonl on address since INADDR_ANY is 0
System::Call '*$2(&i2 ${AF_INET},&i2 s,&i4 ${INADDR_ANY},&i8 0)'
System::Call 'Ws2_32::bind(ir1,ir2,i16)i.r0'
${If} $0 = 0
System::Call 'Ws2_32::listen(ir1,i0)i.r0'
;Listening here but once we hit WSACleanup the port will be free again (This is fine if all you need to do is make sure no app is bound to the port at this moment)
; System::Call 'Ws2_32::closesocket(ir1)'
${EndIf}
${EndIf}
System::Call 'Ws2_32::WSACleanup()' ;Remove this call to leave the port open for the duration of the installer
${EndIf}
System::Free $2
Pop $2 ;Throw away port
Pop $2
Pop $1
Exch $0
FunctionEnd
Section
Push 666
call QueryCanBindToIP4TCPPort
Pop $0
${If} $0 = 0
DetailPrint "Bind OK"
${Else}
DetailPrint "Bind Failed!"
${EndIf}
SectionEnd