mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
Merge pull request #3787 from vegansk/fix_3539_3
Fixed issue #3539 - could not import inet_ntop on XP/2003 - 3rd try
This commit is contained in:
@@ -12,9 +12,18 @@
|
||||
|
||||
{.deadCodeElim:on.}
|
||||
|
||||
import dynlib
|
||||
|
||||
const
|
||||
useWinUnicode* = not defined(useWinAnsi)
|
||||
|
||||
when useWinUnicode:
|
||||
type WinChar* = Utf16Char
|
||||
{.deprecated: [TWinChar: WinChar].}
|
||||
else:
|
||||
type WinChar* = char
|
||||
{.deprecated: [TWinChar: WinChar].}
|
||||
|
||||
type
|
||||
Handle* = int
|
||||
LONG* = int32
|
||||
@@ -74,17 +83,18 @@ type
|
||||
nFileIndexHigh*: DWORD
|
||||
nFileIndexLow*: DWORD
|
||||
|
||||
OSVERSIONINFO* {.final, pure.} = object
|
||||
dwOSVersionInfoSize*: DWORD
|
||||
dwMajorVersion*: DWORD
|
||||
dwMinorVersion*: DWORD
|
||||
dwBuildNumber*: DWORD
|
||||
dwPlatformId*: DWORD
|
||||
szCSDVersion*: array[0..127, WinChar];
|
||||
|
||||
{.deprecated: [THandle: Handle, TSECURITY_ATTRIBUTES: SECURITY_ATTRIBUTES,
|
||||
TSTARTUPINFO: STARTUPINFO, TPROCESS_INFORMATION: PROCESS_INFORMATION,
|
||||
TFILETIME: FILETIME, TBY_HANDLE_FILE_INFORMATION: BY_HANDLE_FILE_INFORMATION].}
|
||||
|
||||
when useWinUnicode:
|
||||
type WinChar* = Utf16Char
|
||||
{.deprecated: [TWinChar: WinChar].}
|
||||
else:
|
||||
type WinChar* = char
|
||||
{.deprecated: [TWinChar: WinChar].}
|
||||
|
||||
const
|
||||
STARTF_USESHOWWINDOW* = 1'i32
|
||||
STARTF_USESTDHANDLES* = 256'i32
|
||||
@@ -117,6 +127,13 @@ const
|
||||
|
||||
CREATE_NO_WINDOW* = 0x08000000'i32
|
||||
|
||||
when useWinUnicode:
|
||||
proc getVersionExW*(lpVersionInfo: ptr OSVERSIONINFO): WINBOOL {.stdcall, dynlib: "kernel32", importc: "GetVersionExW".}
|
||||
else:
|
||||
proc getVersionExA*(lpVersionInfo: ptr OSVERSIONINFO): WINBOOL {.stdcall, dynlib: "kernel32", importc: "GetVersionExA".}
|
||||
|
||||
proc getVersion*(): DWORD {.stdcall, dynlib: "kernel32", importc: "GetVersion".}
|
||||
|
||||
proc closeHandle*(hObject: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
importc: "CloseHandle".}
|
||||
|
||||
@@ -192,6 +209,9 @@ proc flushFileBuffers*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
proc getLastError*(): int32 {.importc: "GetLastError",
|
||||
stdcall, dynlib: "kernel32".}
|
||||
|
||||
proc setLastError*(error: int32) {.importc: "SetLastError",
|
||||
stdcall, dynlib: "kernel32".}
|
||||
|
||||
when useWinUnicode:
|
||||
proc formatMessageW*(dwFlags: int32, lpSource: pointer,
|
||||
dwMessageId, dwLanguageId: int32,
|
||||
@@ -597,9 +617,6 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {.
|
||||
proc inet_ntoa*(i: InAddr): cstring {.
|
||||
stdcall, importc, dynlib: ws2dll.}
|
||||
|
||||
proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
|
||||
stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.}
|
||||
|
||||
const
|
||||
MAXIMUM_WAIT_OBJECTS* = 0x00000040
|
||||
|
||||
@@ -645,6 +662,7 @@ const
|
||||
const
|
||||
ERROR_ACCESS_DENIED* = 5
|
||||
ERROR_HANDLE_EOF* = 38
|
||||
ERROR_BAD_ARGUMENTS* = 165
|
||||
|
||||
proc duplicateHandle*(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE,
|
||||
hTargetProcessHandle: HANDLE,
|
||||
@@ -806,3 +824,54 @@ proc getSystemTimes*(lpIdleTime, lpKernelTime,
|
||||
proc getProcessTimes*(hProcess: Handle; lpCreationTime, lpExitTime,
|
||||
lpKernelTime, lpUserTime: var FILETIME): WINBOOL {.stdcall,
|
||||
dynlib: "kernel32", importc: "GetProcessTimes".}
|
||||
|
||||
type inet_ntop_proc = proc(family: cint, paddr: pointer, pStringBuffer: cstring,
|
||||
stringBufSize: int32): cstring {.stdcall.}
|
||||
|
||||
var inet_ntop_real: inet_ntop_proc = nil
|
||||
|
||||
let l = loadLib(ws2dll)
|
||||
if l != nil:
|
||||
inet_ntop_real = cast[inet_ntop_proc](symAddr(l, "inet_ntop"))
|
||||
|
||||
proc WSAAddressToStringA(pAddr: ptr SockAddr, addrSize: DWORD, unused: pointer, pBuff: cstring, pBuffSize: ptr DWORD): cint {.stdcall, importc, dynlib: ws2dll.}
|
||||
proc inet_ntop_emulated(family: cint, paddr: pointer, pStringBuffer: cstring,
|
||||
stringBufSize: int32): cstring {.stdcall.} =
|
||||
case family
|
||||
of AF_INET:
|
||||
var sa: Sockaddr_in
|
||||
sa.sin_family = AF_INET
|
||||
sa.sin_addr = cast[ptr InAddr](paddr)[]
|
||||
var bs = stringBufSize.DWORD
|
||||
let r = WSAAddressToStringA(cast[ptr SockAddr](sa.addr), sa.sizeof.DWORD, nil, pStringBuffer, bs.addr)
|
||||
if r != 0:
|
||||
result = nil
|
||||
else:
|
||||
result = pStringBuffer
|
||||
of AF_INET6:
|
||||
var sa: Sockaddr_in6
|
||||
sa.sin6_family = AF_INET6
|
||||
sa.sin6_addr = cast[ptr In6_addr](paddr)[]
|
||||
var bs = stringBufSize.DWORD
|
||||
let r = WSAAddressToStringA(cast[ptr SockAddr](sa.addr), sa.sizeof.DWORD, nil, pStringBuffer, bs.addr)
|
||||
if r != 0:
|
||||
result = nil
|
||||
else:
|
||||
result = pStringBuffer
|
||||
else:
|
||||
setLastError(ERROR_BAD_ARGUMENTS)
|
||||
result = nil
|
||||
|
||||
proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
|
||||
stringBufSize: int32): cstring {.stdcall.} =
|
||||
var ver: OSVERSIONINFO
|
||||
ver.dwOSVersionInfoSize = sizeof(ver).DWORD
|
||||
let res = when useWinUnicode: getVersionExW(ver.addr) else: getVersionExA(ver.addr)
|
||||
if res == 0:
|
||||
result = nil
|
||||
elif ver.dwMajorVersion >= 6:
|
||||
if inet_ntop_real == nil:
|
||||
quit("Can't load inet_ntop proc from " & ws2dll)
|
||||
result = inet_ntop_real(family, paddr, pStringBuffer, stringBufSize)
|
||||
else:
|
||||
result = inet_ntop_emulated(family, paddr, pStringBuffer, stringBufSize)
|
||||
|
||||
39
tests/stdlib/tnet_ll.nim
Normal file
39
tests/stdlib/tnet_ll.nim
Normal file
@@ -0,0 +1,39 @@
|
||||
discard """
|
||||
action: run
|
||||
"""
|
||||
|
||||
when defined(windows):
|
||||
import winlean
|
||||
elif defined(posix):
|
||||
import posix
|
||||
else:
|
||||
{.error: "Unsupported OS".}
|
||||
|
||||
import unittest, strutils
|
||||
|
||||
suite "inet_ntop tests":
|
||||
|
||||
setup:
|
||||
when defined(windows):
|
||||
var wsa: WSAData
|
||||
discard wsaStartup(0x101'i16, wsa.addr)
|
||||
|
||||
test "IP V4":
|
||||
var ip4 = 0x10111213
|
||||
var buff: array[0..255, char]
|
||||
let r = inet_ntop(AF_INET, ip4.addr, buff[0].addr, buff.sizeof.int32)
|
||||
let res = if r == nil: "" else: $r
|
||||
check: res == "19.18.17.16"
|
||||
|
||||
|
||||
test "IP V6":
|
||||
when defined(windows):
|
||||
let ipv6Support = (getVersion() and 0xff) > 0x5
|
||||
else:
|
||||
let ipv6Support = true
|
||||
|
||||
var ip6 = [0x1000'u16, 0x1001, 0x2000, 0x2001, 0x3000, 0x3001, 0x4000, 0x4001]
|
||||
var buff: array[0..255, char]
|
||||
let r = inet_ntop(AF_INET6, ip6[0].addr, buff[0].addr, buff.sizeof.int32)
|
||||
let res = if r == nil: "" else: $r
|
||||
check: not ipv6Support or res == "10:110:20:120:30:130:40:140"
|
||||
Reference in New Issue
Block a user