Old 28th November 2017, 09:26   #1
philin
Junior Member
 
Join Date: Nov 2017
Posts: 1
ws2_32::ntohs returns mistake after WIN10 1709

Greeting everybody,
In my installer, I need to check port if listen or not, so I use the code "Ports.nsh" in NSIS wiki.

http://nsis.sourceforge.net/Check_open_ports

It works perfect until I update Windows 10 Fall Creators Update (ver 1709)

Tracking code and debug for a while, I found the error reason is ws2_32::ntohs returns mistake value.

For example, in this code
code:
System::Call ws2_32::ntohs(ir4)i.r4

If input ir4 is 14357(0x3815), ws2_32::ntohs should return 5432(0x1538) to i.r4, but in error case, $4 is 3675448(0x381538).

I have no idea why ws2_32::ntohs retruns mistake value, so I modify my script to avoid ws2_32::ntohs.
code:

IntOp $3 $R0 >> 8
IntOp $4 $R0 & 0xFF
IntOp $4 $4 << 8
IntOp $4 $4 & 0xFF00
IntOp $R0 $4 | $3


just reverse high-low byte of port value.

Full code will post below, wish it can help someone.


code:

# Usage:
# Push "Tcp" or "Udp"
# Push "port_number"
# Call IsPortOpen
# Pop $0 ; "open" or "closed" or anything else for error
#
# Or with the LogicLib
# ${If} ${TCPPortOpen} 80
# ${EndIf}
# ${If} ${UDPPortOpen} 137
# ${EndIf}
#
Function IsPortOpen

Exch $R0 # port to check
Exch
Exch $R1
Push $0
Push $1
Push $2

System::Call 'iphlpapi::Get$R1Table(*i.r0, *i .r1, i 1) i .r2'
${If} $2 != 122 # ERROR_INSUFFICIENT_BUFFER
StrCpy $R0 ""
Pop $2
Pop $1
Pop $0
Exch $R1
Exch
Exch $R0
Return
${EndIf}

System::Alloc $1
Pop $0

System::Call 'iphlpapi::Get$R1Table(ir0, *i r1, i 1) i .r2'
${If} $2 != 0 # NO_ERROR
System::Free $0
StrCpy $R0 ""
Pop $2
Pop $1
Pop $0
Exch $R1
Exch
Exch $R0
Return
${EndIf}

Push $3
Push $4
Push $5

#reverse high-low byte of port to check
IntOp $3 $R0 >> 8
IntOp $4 $R0 & 0xFF
IntOp $4 $4 << 8
IntOp $4 $4 & 0xFF00
IntOp $R0 $4 | $3

System::Call *$0(i.r2)
IntOp $2 $2 - 1
${For} $3 0 $2
IntOp $4 $0 + 4 # skip dwNumEntries
${If} $R1 == "Tcp"
IntOp $5 $3 * 20 # sizeof(MIB_TCPROW)
IntOp $4 $4 + $5 # skip to entry
System::Call *$4(i.r1,i,i.r4,i,i)
${If} $1 <> 2 # $1 = dwState, 2 = MIB_TCP_STATE_LISTEN
${Continue}
${EndIf}
${Else}
IntOp $5 $3 * 8 # sizeof(MIB_UDPROW)
IntOp $4 $4 + $5 # skip to entry
System::Call *$4(i,i.r4)
${EndIf}
#System::Call ws2_32::ntohs(ir4)i.r4

${If} $4 = $R0
StrCpy $R0 "open"
${Break}
${EndIf}
${Next}

${If} $R0 != "open"
StrCpy $R0 "closed"
${EndIf}

System::Free $0

Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
Exch $R1
Exch
Exch $R0

FunctionEnd

# LogicLib macros for IsPortOpen

!include LogicLib.nsh

!macro _PortOpen _a _b _t _f
!insertmacro _LOGICLIB_TEMP
Push `${_a}`
Push `${_b}`
Call IsPortOpen
Pop $_LOGICLIB_TEMP
!insertmacro _== $_LOGICLIB_TEMP "open" `${_t}` `${_f}`
!macroend
!define PortOpen `PortOpen`

!macro _TCPPortOpen _a _b _t _f
!insertmacro _PortOpen Tcp `${_b}` `${_t}` `${_f}`
!macroend
!define TCPPortOpen `"" TCPPortOpen`

!macro _UDPPortOpen _a _b _t _f
!insertmacro _PortOpen Udp `${_b}` `${_t}` `${_f}`
!macroend
!define UDPPortOpen `"" UDPPortOpen`

philin is offline   Reply With Quote
Old 28th November 2017, 12:24   #2
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,888
This is not a bug in Windows, the function is documented as returning a 16-bit value and the upper part of EAX should be ignored. Unfortunately the System plug-in does not have a 16-bit return type but you can use this workaround:

Quote:
System::Call ws2_32::ntohs(ir4)i.r4
IntOp $4 $4 & 0xffff

This seems to affect others as well so it might get "fixed" in the next Windows release.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 30th November 2017, 18:26   #3
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 4,888
Win 10 FCU left shifts the 16-bit parameter (in ECX) and ORs it with EAX (the bottom right shifted bits) at the end.

Win 8 has the registers swapped and EAX is ANDed with 0xff before it is left shifted.

The source code has probably not changed, the compiler has swapped things around and removed one 10 byte instruction.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Reply
Go Back   Winamp & SHOUTcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump