# # # Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## This module implements a small wrapper for some needed Win API procedures, ## so that the Nim compiler does not depend on the huge Windows module. {.deadCodeElim: on.} # dce option deprecated import dynlib {.passC: "-DWIN32_LEAN_AND_MEAN".} 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 ULONG* = int32 PULONG* = ptr int WINBOOL* = int32 DWORD* = int32 PDWORD* = ptr DWORD LPINT* = ptr int32 ULONG_PTR* = uint PULONG_PTR* = ptr uint HDC* = Handle HGLRC* = Handle SECURITY_ATTRIBUTES* {.final, pure.} = object nLength*: int32 lpSecurityDescriptor*: pointer bInheritHandle*: WINBOOL STARTUPINFO* {.final, pure.} = object cb*: int32 lpReserved*: cstring lpDesktop*: cstring lpTitle*: cstring dwX*: int32 dwY*: int32 dwXSize*: int32 dwYSize*: int32 dwXCountChars*: int32 dwYCountChars*: int32 dwFillAttribute*: int32 dwFlags*: int32 wShowWindow*: int16 cbReserved2*: int16 lpReserved2*: pointer hStdInput*: Handle hStdOutput*: Handle hStdError*: Handle PROCESS_INFORMATION* {.final, pure.} = object hProcess*: Handle hThread*: Handle dwProcessId*: int32 dwThreadId*: int32 FILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT dwLowDateTime*: DWORD dwHighDateTime*: DWORD BY_HANDLE_FILE_INFORMATION* {.final, pure.} = object dwFileAttributes*: DWORD ftCreationTime*: FILETIME ftLastAccessTime*: FILETIME ftLastWriteTime*: FILETIME dwVolumeSerialNumber*: DWORD nFileSizeHigh*: DWORD nFileSizeLow*: DWORD nNumberOfLinks*: DWORD 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].} const STARTF_USESHOWWINDOW* = 1'i32 STARTF_USESTDHANDLES* = 256'i32 HIGH_PRIORITY_CLASS* = 128'i32 IDLE_PRIORITY_CLASS* = 64'i32 NORMAL_PRIORITY_CLASS* = 32'i32 REALTIME_PRIORITY_CLASS* = 256'i32 WAIT_OBJECT_0* = 0'i32 WAIT_TIMEOUT* = 0x00000102'i32 WAIT_FAILED* = 0xFFFFFFFF'i32 INFINITE* = -1'i32 STILL_ACTIVE* = 0x00000103'i32 STD_INPUT_HANDLE* = -10'i32 STD_OUTPUT_HANDLE* = -11'i32 STD_ERROR_HANDLE* = -12'i32 DETACHED_PROCESS* = 8'i32 SW_SHOWNORMAL* = 1'i32 INVALID_HANDLE_VALUE* = Handle(-1) CREATE_UNICODE_ENVIRONMENT* = 1024'i32 PIPE_ACCESS_DUPLEX* = 0x00000003'i32 PIPE_ACCESS_INBOUND* = 1'i32 PIPE_ACCESS_OUTBOUND* = 2'i32 PIPE_NOWAIT* = 0x00000001'i32 SYNCHRONIZE* = 0x00100000'i32 FILE_FLAG_WRITE_THROUGH* = 0x80000000'i32 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".} proc readFile*(hFile: Handle, Buffer: pointer, nNumberOfBytesToRead: int32, lpNumberOfBytesRead: ptr int32, lpOverlapped: pointer): WINBOOL{. stdcall, dynlib: "kernel32", importc: "ReadFile".} proc writeFile*(hFile: Handle, Buffer: pointer, nNumberOfBytesToWrite: int32, lpNumberOfBytesWritten: ptr int32, lpOverlapped: pointer): WINBOOL{. stdcall, dynlib: "kernel32", importc: "WriteFile".} proc createPipe*(hReadPipe, hWritePipe: var Handle, lpPipeAttributes: var SECURITY_ATTRIBUTES, nSize: int32): WINBOOL{. stdcall, dynlib: "kernel32", importc: "CreatePipe".} proc createNamedPipe*(lpName: WideCString, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut: int32, lpSecurityAttributes: ptr SECURITY_ATTRIBUTES): Handle {. stdcall, dynlib: "kernel32", importc: "CreateNamedPipeW".} proc peekNamedPipe*(hNamedPipe: Handle, lpBuffer: pointer=nil, nBufferSize: int32 = 0, lpBytesRead: ptr int32 = nil, lpTotalBytesAvail: ptr int32 = nil, lpBytesLeftThisMessage: ptr int32 = nil): bool {. stdcall, dynlib: "kernel32", importc: "PeekNamedPipe".} when useWinUnicode: proc createProcessW*(lpApplicationName, lpCommandLine: WideCString, lpProcessAttributes: ptr SECURITY_ATTRIBUTES, lpThreadAttributes: ptr SECURITY_ATTRIBUTES, bInheritHandles: WINBOOL, dwCreationFlags: int32, lpEnvironment, lpCurrentDirectory: WideCString, lpStartupInfo: var STARTUPINFO, lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{. stdcall, dynlib: "kernel32", importc: "CreateProcessW".} else: proc createProcessA*(lpApplicationName, lpCommandLine: cstring, lpProcessAttributes: ptr SECURITY_ATTRIBUTES, lpThreadAttributes: ptr SECURITY_ATTRIBUTES, bInheritHandles: WINBOOL, dwCreationFlags: int32, lpEnvironment: pointer, lpCurrentDirectory: cstring, lpStartupInfo: var STARTUPINFO, lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{. stdcall, dynlib: "kernel32", importc: "CreateProcessA".} proc suspendThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32", importc: "SuspendThread".} proc resumeThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32", importc: "ResumeThread".} proc waitForSingleObject*(hHandle: Handle, dwMilliseconds: int32): int32 {. stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".} proc terminateProcess*(hProcess: Handle, uExitCode: int): WINBOOL {.stdcall, dynlib: "kernel32", importc: "TerminateProcess".} proc getExitCodeProcess*(hProcess: Handle, lpExitCode: var int32): WINBOOL {. stdcall, dynlib: "kernel32", importc: "GetExitCodeProcess".} proc getStdHandle*(nStdHandle: int32): Handle {.stdcall, dynlib: "kernel32", importc: "GetStdHandle".} proc setStdHandle*(nStdHandle: int32, hHandle: Handle): WINBOOL {.stdcall, dynlib: "kernel32", importc: "SetStdHandle".} proc flushFileBuffers*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32", importc: "FlushFileBuffers".} 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, lpBuffer: pointer, nSize: int32, Arguments: pointer): int32 {. importc: "FormatMessageW", stdcall, dynlib: "kernel32".} else: proc formatMessageA*(dwFlags: int32, lpSource: pointer, dwMessageId, dwLanguageId: int32, lpBuffer: pointer, nSize: int32, Arguments: pointer): int32 {. importc: "FormatMessageA", stdcall, dynlib: "kernel32".} proc localFree*(p: pointer) {. importc: "LocalFree", stdcall, dynlib: "kernel32".} when useWinUnicode: proc getCurrentDirectoryW*(nBufferLength: int32, lpBuffer: WideCString): int32 {. importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall.} proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {. importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall.} proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {. importc: "CreateDirectoryW", dynlib: "kernel32", stdcall.} proc removeDirectoryW*(lpPathName: WideCString): int32 {. importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall.} proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {. stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW".} proc getModuleFileNameW*(handle: Handle, buf: WideCString, size: int32): int32 {.importc: "GetModuleFileNameW", dynlib: "kernel32", stdcall.} else: proc getCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {. importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall.} proc setCurrentDirectoryA*(lpPathName: cstring): int32 {. importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall.} proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {. importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.} proc removeDirectoryA*(lpPathName: cstring): int32 {. importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall.} proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {. stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA".} proc getModuleFileNameA*(handle: Handle, buf: cstring, size: int32): int32 {. importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.} when useWinUnicode: proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString, flags: DWORD): int32 {. importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall.} proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString, security: pointer=nil): int32 {. importc:"CreateHardLinkW", dynlib: "kernel32", stdcall.} else: proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring, flags: DWORD): int32 {. importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall.} proc createHardLinkA*(lpFileName, lpExistingFileName: cstring, security: pointer=nil): int32 {. importc:"CreateHardLinkA", dynlib: "kernel32", stdcall.} const FILE_ATTRIBUTE_ARCHIVE* = 32'i32 FILE_ATTRIBUTE_COMPRESSED* = 2048'i32 FILE_ATTRIBUTE_NORMAL* = 128'i32 FILE_ATTRIBUTE_DIRECTORY* = 16'i32 FILE_ATTRIBUTE_HIDDEN* = 2'i32 FILE_ATTRIBUTE_READONLY* = 1'i32 FILE_ATTRIBUTE_REPARSE_POINT* = 1024'i32 FILE_ATTRIBUTE_SYSTEM* = 4'i32 FILE_ATTRIBUTE_TEMPORARY* = 256'i32 MAX_PATH* = 260 MOVEFILE_COPY_ALLOWED* = 0x2'i32 MOVEFILE_CREATE_HARDLINK* = 0x10'i32 MOVEFILE_DELAY_UNTIL_REBOOT* = 0x4'i32 MOVEFILE_FAIL_IF_NOT_TRACKABLE* = 0x20'i32 MOVEFILE_REPLACE_EXISTING* = 0x1'i32 MOVEFILE_WRITE_THROUGH* = 0x8'i32 type WIN32_FIND_DATA* {.pure.} = object dwFileAttributes*: int32 ftCreationTime*: FILETIME ftLastAccessTime*: FILETIME ftLastWriteTime*: FILETIME nFileSizeHigh*: int32 nFileSizeLow*: int32 dwReserved0: int32 dwReserved1: int32 cFileName*: array[0..(MAX_PATH) - 1, WinChar] cAlternateFileName*: array[0..13, WinChar] {.deprecated: [TWIN32_FIND_DATA: WIN32_FIND_DATA].} when useWinUnicode: proc findFirstFileW*(lpFileName: WideCString, lpFindFileData: var WIN32_FIND_DATA): Handle {. stdcall, dynlib: "kernel32", importc: "FindFirstFileW".} proc findNextFileW*(hFindFile: Handle, lpFindFileData: var WIN32_FIND_DATA): int32 {. stdcall, dynlib: "kernel32", importc: "FindNextFileW".} else: proc findFirstFileA*(lpFileName: cstring, lpFindFileData: var WIN32_FIND_DATA): Handle {. stdcall, dynlib: "kernel32", importc: "FindFirstFileA".} proc findNextFileA*(hFindFile: Handle, lpFindFileData: var WIN32_FIND_DATA): int32 {. stdcall, dynlib: "kernel32", importc: "FindNextFileA".} proc findClose*(hFindFile: Handle) {.stdcall, dynlib: "kernel32", importc: "FindClose".} when useWinUnicode: proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32, lpBuffer: WideCString, lpFilePart: var WideCString): int32 {. stdcall, dynlib: "kernel32", importc: "GetFullPathNameW".} proc getFileAttributesW*(lpFileName: WideCString): int32 {. stdcall, dynlib: "kernel32", importc: "GetFileAttributesW".} proc setFileAttributesW*(lpFileName: WideCString, dwFileAttributes: int32): WINBOOL {. stdcall, dynlib: "kernel32", importc: "SetFileAttributesW".} proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString, bFailIfExists: WINBOOL): WINBOOL {. importc: "CopyFileW", stdcall, dynlib: "kernel32".} proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString): WINBOOL {. importc: "MoveFileW", stdcall, dynlib: "kernel32".} proc moveFileExW*(lpExistingFileName, lpNewFileName: WideCString, flags: DWORD): WINBOOL {. importc: "MoveFileExW", stdcall, dynlib: "kernel32".} proc getEnvironmentStringsW*(): WideCString {. stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW".} proc freeEnvironmentStringsW*(para1: WideCString): int32 {. stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW".} proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW", stdcall, dynlib: "kernel32".} else: proc getFullPathNameA*(lpFileName: cstring, nBufferLength: int32, lpBuffer: cstring, lpFilePart: var cstring): int32 {. stdcall, dynlib: "kernel32", importc: "GetFullPathNameA".} proc getFileAttributesA*(lpFileName: cstring): int32 {. stdcall, dynlib: "kernel32", importc: "GetFileAttributesA".} proc setFileAttributesA*(lpFileName: cstring, dwFileAttributes: int32): WINBOOL {. stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".} proc copyFileA*(lpExistingFileName, lpNewFileName: cstring, bFailIfExists: cint): cint {. importc: "CopyFileA", stdcall, dynlib: "kernel32".} proc moveFileA*(lpExistingFileName, lpNewFileName: cstring): WINBOOL {. importc: "MoveFileA", stdcall, dynlib: "kernel32".} proc moveFileExA*(lpExistingFileName, lpNewFileName: WideCString, flags: DWORD): WINBOOL {. importc: "MoveFileExA", stdcall, dynlib: "kernel32".} proc getEnvironmentStringsA*(): cstring {. stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsA".} proc freeEnvironmentStringsA*(para1: cstring): int32 {. stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsA".} proc getCommandLineA*(): cstring {. importc: "GetCommandLineA", stdcall, dynlib: "kernel32".} proc rdFileTime*(f: FILETIME): int64 = result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32) proc rdFileSize*(f: WIN32_FIND_DATA): int64 = result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32) proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {. importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall.} proc sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32", importc: "Sleep".} when useWinUnicode: proc shellExecuteW*(HWND: Handle, lpOperation, lpFile, lpParameters, lpDirectory: WideCString, nShowCmd: int32): Handle{. stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW".} else: proc shellExecuteA*(HWND: Handle, lpOperation, lpFile, lpParameters, lpDirectory: cstring, nShowCmd: int32): Handle{. stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".} proc getFileInformationByHandle*(hFile: Handle, lpFileInformation: ptr BY_HANDLE_FILE_INFORMATION): WINBOOL{. stdcall, dynlib: "kernel32", importc: "GetFileInformationByHandle".} const WSADESCRIPTION_LEN* = 256 WSASYS_STATUS_LEN* = 128 FD_SETSIZE* = 64 MSG_PEEK* = 2 INADDR_ANY* = 0'u32 INADDR_LOOPBACK* = 0x7F000001 INADDR_BROADCAST* = -1 INADDR_NONE* = -1 ws2dll = "Ws2_32.dll" proc wsaGetLastError*(): cint {.importc: "WSAGetLastError", dynlib: ws2dll.} type SocketHandle* = distinct int {.deprecated: [TSocketHandle: SocketHandle].} type WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object wVersion, wHighVersion: int16 szDescription: array[0..WSADESCRIPTION_LEN, char] szSystemStatus: array[0..WSASYS_STATUS_LEN, char] iMaxSockets, iMaxUdpDg: int16 lpVendorInfo: cstring SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object sa_family*: int16 # unsigned sa_data*: array[0..13, char] PSockAddr = ptr SockAddr InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object s_addr*: uint32 # IP address Sockaddr_in* {.importc: "SOCKADDR_IN", header: "winsock2.h".} = object sin_family*: int16 sin_port*: uint16 sin_addr*: InAddr sin_zero*: array[0..7, char] In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object bytes* {.importc: "u.Byte".}: array[0..15, char] Sockaddr_in6* {.importc: "SOCKADDR_IN6", header: "ws2tcpip.h".} = object sin6_family*: int16 sin6_port*: uint16 sin6_flowinfo*: int32 # unsigned sin6_addr*: In6_addr sin6_scope_id*: int32 # unsigned Sockaddr_in6_old* = object sin6_family*: int16 sin6_port*: int16 # unsigned sin6_flowinfo*: int32 # unsigned sin6_addr*: In6_addr Sockaddr_storage* {.importc: "SOCKADDR_STORAGE", header: "winsock2.h".} = object ss_family*: int16 ss_pad1: array[6, byte] ss_align: int64 ss_pad2: array[112, byte] Servent* = object s_name*: cstring s_aliases*: cstringArray when defined(cpu64): s_proto*: cstring s_port*: int16 else: s_port*: int16 s_proto*: cstring Hostent* = object h_name*: cstring h_aliases*: cstringArray h_addrtype*: int16 h_length*: int16 h_addr_list*: cstringArray TFdSet* = object fd_count*: cint # unsigned fd_array*: array[0..FD_SETSIZE-1, SocketHandle] Timeval* = object tv_sec*, tv_usec*: int32 AddrInfo* = object ai_flags*: cint ## Input flags. ai_family*: cint ## Address family of socket. ai_socktype*: cint ## Socket type. ai_protocol*: cint ## Protocol of socket. ai_addrlen*: csize ## Length of socket address. ai_canonname*: cstring ## Canonical name of service location. ai_addr*: ptr SockAddr ## Socket address of socket. ai_next*: ptr AddrInfo ## Pointer to next in list. SockLen* = cuint {.deprecated: [TSockaddr_in: Sockaddr_in, TAddrinfo: AddrInfo, TSockAddr: SockAddr, TSockLen: SockLen, TTimeval: Timeval, TWSADATA: WSADATA, Thostent: Hostent, TServent: Servent, TInAddr: InAddr, Tin6_addr: In6_addr, Tsockaddr_in6: Sockaddr_in6, Tsockaddr_in6_old: Sockaddr_in6_old].} var SOMAXCONN* {.importc, header: "winsock2.h".}: cint INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle SOL_SOCKET* {.importc, header: "winsock2.h".}: cint SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen() SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse SO_REUSEPORT* {.importc: "SO_REUSEADDR", header: "winsock2.h".}: cint # allow port reuse. Since Windows does not really support it, mapped to SO_REUSEADDR. This shouldn't cause problems. SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs SO_USELOOPBACK* {.importc, header: "winsock2.h".}: cint # bypass hardware when possible SO_LINGER* {.importc, header: "winsock2.h".}: cint # linger on close if data present SO_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse SO_ERROR* {.importc, header: "winsock2.h".}: cint TCP_NODELAY* {.importc, header: "winsock2.h".}: cint proc `==`*(x, y: SocketHandle): bool {.borrow.} proc getservbyname*(name, proto: cstring): ptr Servent {. stdcall, importc: "getservbyname", dynlib: ws2dll.} proc getservbyport*(port: cint, proto: cstring): ptr Servent {. stdcall, importc: "getservbyport", dynlib: ws2dll.} proc gethostbyaddr*(ip: ptr InAddr, len: cuint, theType: cint): ptr Hostent {. stdcall, importc: "gethostbyaddr", dynlib: ws2dll.} proc gethostbyname*(name: cstring): ptr Hostent {. stdcall, importc: "gethostbyname", dynlib: ws2dll.} proc gethostname*(hostname: cstring, len: cint): cint {. stdcall, importc: "gethostname", dynlib: ws2dll.} proc socket*(af, typ, protocol: cint): SocketHandle {. stdcall, importc: "socket", dynlib: ws2dll.} proc closesocket*(s: SocketHandle): cint {. stdcall, importc: "closesocket", dynlib: ws2dll.} proc accept*(s: SocketHandle, a: ptr SockAddr, addrlen: ptr SockLen): SocketHandle {. stdcall, importc: "accept", dynlib: ws2dll.} proc bindSocket*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {. stdcall, importc: "bind", dynlib: ws2dll.} proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {. stdcall, importc: "connect", dynlib: ws2dll.} proc getsockname*(s: SocketHandle, name: ptr SockAddr, namelen: ptr SockLen): cint {. stdcall, importc: "getsockname", dynlib: ws2dll.} proc getpeername*(s: SocketHandle, name: ptr SockAddr, namelen: ptr SockLen): cint {. stdcall, importc, dynlib: ws2dll.} proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer, optlen: ptr SockLen): cint {. stdcall, importc: "getsockopt", dynlib: ws2dll.} proc setsockopt*(s: SocketHandle, level, optname: cint, optval: pointer, optlen: SockLen): cint {. stdcall, importc: "setsockopt", dynlib: ws2dll.} proc listen*(s: SocketHandle, backlog: cint): cint {. stdcall, importc: "listen", dynlib: ws2dll.} proc recv*(s: SocketHandle, buf: pointer, len, flags: cint): cint {. stdcall, importc: "recv", dynlib: ws2dll.} proc recvfrom*(s: SocketHandle, buf: cstring, len, flags: cint, fromm: ptr SockAddr, fromlen: ptr SockLen): cint {. stdcall, importc: "recvfrom", dynlib: ws2dll.} proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet, timeout: ptr Timeval): cint {. stdcall, importc: "select", dynlib: ws2dll.} proc send*(s: SocketHandle, buf: pointer, len, flags: cint): cint {. stdcall, importc: "send", dynlib: ws2dll.} proc sendto*(s: SocketHandle, buf: pointer, len, flags: cint, to: ptr SockAddr, tolen: SockLen): cint {. stdcall, importc: "sendto", dynlib: ws2dll.} proc shutdown*(s: SocketHandle, how: cint): cint {. stdcall, importc: "shutdown", dynlib: ws2dll.} proc getnameinfo*(a1: ptr SockAddr, a2: SockLen, a3: cstring, a4: SockLen, a5: cstring, a6: SockLen, a7: cint): cint {. stdcall, importc: "getnameinfo", dynlib: ws2dll.} proc inet_addr*(cp: cstring): uint32 {. stdcall, importc: "inet_addr", dynlib: ws2dll.} proc WSAFDIsSet(s: SocketHandle, set: var TFdSet): bool {. stdcall, importc: "__WSAFDIsSet", dynlib: ws2dll, noSideEffect.} proc FD_ISSET*(socket: SocketHandle, set: var TFdSet): cint = result = if WSAFDIsSet(socket, set): 1'i32 else: 0'i32 proc FD_SET*(socket: SocketHandle, s: var TFdSet) = if s.fd_count < FD_SETSIZE: s.fd_array[int(s.fd_count)] = socket inc(s.fd_count) proc FD_ZERO*(s: var TFdSet) = s.fd_count = 0 proc wsaStartup*(wVersionRequired: int16, WSData: ptr WSAData): cint {. stdcall, importc: "WSAStartup", dynlib: ws2dll.} proc getaddrinfo*(nodename, servname: cstring, hints: ptr AddrInfo, res: var ptr AddrInfo): cint {. stdcall, importc: "getaddrinfo", dynlib: ws2dll.} proc freeaddrinfo*(ai: ptr AddrInfo) {. stdcall, importc: "freeaddrinfo", dynlib: ws2dll.} proc inet_ntoa*(i: InAddr): cstring {. stdcall, importc, dynlib: ws2dll.} const MAXIMUM_WAIT_OBJECTS* = 0x00000040 type WOHandleArray* = array[0..MAXIMUM_WAIT_OBJECTS - 1, Handle] PWOHandleArray* = ptr WOHandleArray {.deprecated: [TWOHandleArray: WOHandleArray].} proc waitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray, bWaitAll: WINBOOL, dwMilliseconds: DWORD): DWORD{. stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".} # for memfiles.nim: const GENERIC_READ* = 0x80000000'i32 GENERIC_WRITE* = 0x40000000'i32 GENERIC_ALL* = 0x10000000'i32 FILE_SHARE_READ* = 1'i32 FILE_SHARE_DELETE* = 4'i32 FILE_SHARE_WRITE* = 2'i32 CREATE_ALWAYS* = 2'i32 CREATE_NEW* = 1'i32 OPEN_EXISTING* = 3'i32 OPEN_ALWAYS* = 4'i32 FILE_BEGIN* = 0'i32 INVALID_SET_FILE_POINTER* = -1'i32 NO_ERROR* = 0'i32 PAGE_READONLY* = 2'i32 PAGE_READWRITE* = 4'i32 FILE_MAP_READ* = 4'i32 FILE_MAP_WRITE* = 2'i32 INVALID_FILE_SIZE* = -1'i32 FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32 FILE_FLAG_OPEN_REPARSE_POINT* = 0x00200000'i32 DUPLICATE_SAME_ACCESS* = 2 FILE_READ_DATA* = 0x00000001 # file & pipe FILE_WRITE_DATA* = 0x00000002 # file & pipe # Error Constants const ERROR_FILE_NOT_FOUND* = 2 ERROR_PATH_NOT_FOUND* = 3 ERROR_ACCESS_DENIED* = 5 ERROR_NO_MORE_FILES* = 18 ERROR_HANDLE_EOF* = 38 ERROR_BAD_ARGUMENTS* = 165 proc duplicateHandle*(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: ptr HANDLE, dwDesiredAccess: DWORD, bInheritHandle: WINBOOL, dwOptions: DWORD): WINBOOL{.stdcall, dynlib: "kernel32", importc: "DuplicateHandle".} proc setHandleInformation*(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD): WINBOOL {.stdcall, dynlib: "kernel32", importc: "SetHandleInformation".} proc getCurrentProcess*(): HANDLE{.stdcall, dynlib: "kernel32", importc: "GetCurrentProcess".} when useWinUnicode: proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD, lpSecurityAttributes: pointer, dwCreationDisposition, dwFlagsAndAttributes: DWORD, hTemplateFile: Handle): Handle {. stdcall, dynlib: "kernel32", importc: "CreateFileW".} proc deleteFileW*(pathName: WideCString): int32 {. importc: "DeleteFileW", dynlib: "kernel32", stdcall.} else: proc createFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD, lpSecurityAttributes: pointer, dwCreationDisposition, dwFlagsAndAttributes: DWORD, hTemplateFile: Handle): Handle {. stdcall, dynlib: "kernel32", importc: "CreateFileA".} proc deleteFileA*(pathName: cstring): int32 {. importc: "DeleteFileA", dynlib: "kernel32", stdcall.} proc setEndOfFile*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32", importc: "SetEndOfFile".} proc setFilePointer*(hFile: Handle, lDistanceToMove: LONG, lpDistanceToMoveHigh: ptr LONG, dwMoveMethod: DWORD): DWORD {. stdcall, dynlib: "kernel32", importc: "SetFilePointer".} proc getFileSize*(hFile: Handle, lpFileSizeHigh: ptr DWORD): DWORD{.stdcall, dynlib: "kernel32", importc: "GetFileSize".} proc mapViewOfFileEx*(hFileMappingObject: Handle, dwDesiredAccess: DWORD, dwFileOffsetHigh, dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: DWORD, lpBaseAddress: pointer): pointer{. stdcall, dynlib: "kernel32", importc: "MapViewOfFileEx".} proc createFileMappingW*(hFile: Handle, lpFileMappingAttributes: pointer, flProtect, dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: pointer): Handle {. stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".} when not useWinUnicode: proc createFileMappingA*(hFile: Handle, lpFileMappingAttributes: pointer, flProtect, dwMaximumSizeHigh: DWORD, dwMaximumSizeLow: DWORD, lpName: cstring): Handle {. stdcall, dynlib: "kernel32", importc: "CreateFileMappingA".} proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall, dynlib: "kernel32", importc: "UnmapViewOfFile".} type OVERLAPPED* {.pure, inheritable.} = object internal*: PULONG internalHigh*: PULONG offset*: DWORD offsetHigh*: DWORD hEvent*: Handle POVERLAPPED* = ptr OVERLAPPED POVERLAPPED_COMPLETION_ROUTINE* = proc (para1: DWORD, para2: DWORD, para3: POVERLAPPED){.stdcall.} GUID* {.final, pure.} = object D1*: int32 D2*: int16 D3*: int16 D4*: array[0..7, int8] {.deprecated: [TOVERLAPPED: OVERLAPPED, TGUID: GUID].} const ERROR_IO_PENDING* = 997 # a.k.a WSA_IO_PENDING FILE_FLAG_OVERLAPPED* = 1073741824 WSAECONNABORTED* = 10053 WSAEADDRINUSE* = 10048 WSAECONNRESET* = 10054 WSAEDISCON* = 10101 WSAENETRESET* = 10052 WSAETIMEDOUT* = 10060 WSANOTINITIALISED* = 10093 WSAENOTSOCK* = 10038 WSAEINPROGRESS* = 10036 WSAEINTR* = 10004 WSAEWOULDBLOCK* = 10035 ERROR_NETNAME_DELETED* = 64 STATUS_PENDING* = 0x103 proc createIoCompletionPort*(FileHandle: Handle, ExistingCompletionPort: Handle, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD): Handle{.stdcall, dynlib: "kernel32", importc: "CreateIoCompletionPort".} proc getQueuedCompletionStatus*(CompletionPort: Handle, lpNumberOfBytesTransferred: PDWORD, lpCompletionKey: PULONG_PTR, lpOverlapped: ptr POVERLAPPED, dwMilliseconds: DWORD): WINBOOL{.stdcall, dynlib: "kernel32", importc: "GetQueuedCompletionStatus".} proc getOverlappedResult*(hFile: Handle, lpOverlapped: POVERLAPPED, lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{. stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".} # this is copy of HasOverlappedIoCompleted() macro from # because we have declared own OVERLAPPED structure with member names not # compatible with original names. template hasOverlappedIoCompleted*(lpOverlapped): bool = (cast[uint](lpOverlapped.internal) != STATUS_PENDING) const IOC_OUT* = 0x40000000 IOC_IN* = 0x80000000 IOC_WS2* = 0x08000000 IOC_INOUT* = IOC_IN or IOC_OUT template WSAIORW*(x,y): untyped = (IOC_INOUT or x or y) const SIO_GET_EXTENSION_FUNCTION_POINTER* = WSAIORW(IOC_WS2,6).DWORD SO_UPDATE_ACCEPT_CONTEXT* = 0x700B AI_V4MAPPED* = 0x0008 AF_UNSPEC* = 0 AF_INET* = 2 AF_INET6* = 23 var WSAID_CONNECTEX*: GUID = GUID(D1: 0x25a207b9, D2: 0xddf3'i16, D3: 0x4660, D4: [ 0x8e'i8, 0xe9'i8, 0x76'i8, 0xe5'i8, 0x8c'i8, 0x74'i8, 0x06'i8, 0x3e'i8]) WSAID_ACCEPTEX*: GUID = GUID(D1: 0xb5367df1'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [ 0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8]) WSAID_GETACCEPTEXSOCKADDRS*: GUID = GUID(D1: 0xb5367df2'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [ 0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8]) proc WSAIoctl*(s: SocketHandle, dwIoControlCode: DWORD, lpvInBuffer: pointer, cbInBuffer: DWORD, lpvOutBuffer: pointer, cbOutBuffer: DWORD, lpcbBytesReturned: PDWORD, lpOverlapped: POVERLAPPED, lpCompletionRoutine: POVERLAPPED_COMPLETION_ROUTINE): cint {.stdcall, importc: "WSAIoctl", dynlib: "Ws2_32.dll".} type TWSABuf* {.importc: "WSABUF", header: "winsock2.h".} = object len*: ULONG buf*: cstring proc WSARecv*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD, bytesReceived, flags: PDWORD, lpOverlapped: POVERLAPPED, completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. stdcall, importc: "WSARecv", dynlib: "Ws2_32.dll".} proc WSARecvFrom*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD, bytesReceived: PDWORD, flags: PDWORD, name: ptr SockAddr, namelen: ptr cint, lpOverlapped: POVERLAPPED, completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. stdcall, importc: "WSARecvFrom", dynlib: "Ws2_32.dll".} proc WSASend*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD, bytesSent: PDWORD, flags: DWORD, lpOverlapped: POVERLAPPED, completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".} proc WSASendTo*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD, bytesSent: PDWORD, flags: DWORD, name: ptr SockAddr, namelen: cint, lpOverlapped: POVERLAPPED, completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. stdcall, importc: "WSASendTo", dynlib: "Ws2_32.dll".} proc get_osfhandle*(fd:FileHandle): Handle {. importc: "_get_osfhandle", header:"".} proc getSystemTimes*(lpIdleTime, lpKernelTime, lpUserTime: var FILETIME): WINBOOL {.stdcall, dynlib: "kernel32", importc: "GetSystemTimes".} 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 {.gcsafe, stdcall.} var inet_ntop_real: inet_ntop_proc = nil let ws2 = loadLib(ws2dll) if ws2 != nil: inet_ntop_real = cast[inet_ntop_proc](symAddr(ws2, "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) type WSAPROC_ACCEPTEX* = proc (sListenSocket: SocketHandle, sAcceptSocket: SocketHandle, lpOutputBuffer: pointer, dwReceiveDataLength: DWORD, dwLocalAddressLength: DWORD, dwRemoteAddressLength: DWORD, lpdwBytesReceived: ptr DWORD, lpOverlapped: POVERLAPPED): bool {. stdcall,gcsafe.} WSAPROC_CONNECTEX* = proc (s: SocketHandle, name: ptr SockAddr, namelen: cint, lpSendBuffer: pointer, dwSendDataLength: DWORD, lpdwBytesSent: ptr DWORD, lpOverlapped: POVERLAPPED): bool {. stdcall,gcsafe.} WSAPROC_GETACCEPTEXSOCKADDRS* = proc(lpOutputBuffer: pointer, dwReceiveDataLength: DWORD, dwLocalAddressLength: DWORD, dwRemoteAddressLength: DWORD, LocalSockaddr: ptr PSockAddr, LocalSockaddrLength: ptr cint, RemoteSockaddr: ptr PSockAddr, RemoteSockaddrLength: ptr cint) {. stdcall,gcsafe.} const WT_EXECUTEDEFAULT* = 0x00000000'i32 WT_EXECUTEINIOTHREAD* = 0x00000001'i32 WT_EXECUTEINUITHREAD* = 0x00000002'i32 WT_EXECUTEINWAITTHREAD* = 0x00000004'i32 WT_EXECUTEONLYONCE* = 0x00000008'i32 WT_EXECUTELONGFUNCTION* = 0x00000010'i32 WT_EXECUTEINTIMERTHREAD* = 0x00000020'i32 WT_EXECUTEINPERSISTENTIOTHREAD* = 0x00000040'i32 WT_EXECUTEINPERSISTENTTHREAD* = 0x00000080'i32 WT_TRANSFER_IMPERSONATION* = 0x00000100'i32 PROCESS_TERMINATE* = 0x00000001'i32 PROCESS_CREATE_THREAD* = 0x00000002'i32 PROCESS_SET_SESSIONID* = 0x00000004'i32 PROCESS_VM_OPERATION* = 0x00000008'i32 PROCESS_VM_READ* = 0x00000010'i32 PROCESS_VM_WRITE* = 0x00000020'i32 PROCESS_DUP_HANDLE* = 0x00000040'i32 PROCESS_CREATE_PROCESS* = 0x00000080'i32 PROCESS_SET_QUOTA* = 0x00000100'i32 PROCESS_SET_INFORMATION* = 0x00000200'i32 PROCESS_QUERY_INFORMATION* = 0x00000400'i32 PROCESS_SUSPEND_RESUME* = 0x00000800'i32 PROCESS_QUERY_LIMITED_INFORMATION* = 0x00001000'i32 PROCESS_SET_LIMITED_INFORMATION* = 0x00002000'i32 type WAITORTIMERCALLBACK* = proc(para1: pointer, para2: int32): void {.stdcall.} proc postQueuedCompletionStatus*(CompletionPort: HANDLE, dwNumberOfBytesTransferred: DWORD, dwCompletionKey: ULONG_PTR, lpOverlapped: pointer): bool {.stdcall, dynlib: "kernel32", importc: "PostQueuedCompletionStatus".} proc registerWaitForSingleObject*(phNewWaitObject: ptr Handle, hObject: Handle, Callback: WAITORTIMERCALLBACK, Context: pointer, dwMilliseconds: ULONG, dwFlags: ULONG): bool {.stdcall, dynlib: "kernel32", importc: "RegisterWaitForSingleObject".} proc unregisterWait*(WaitHandle: HANDLE): DWORD {.stdcall, dynlib: "kernel32", importc: "UnregisterWait".} proc openProcess*(dwDesiredAccess: DWORD, bInheritHandle: WINBOOL, dwProcessId: DWORD): Handle {.stdcall, dynlib: "kernel32", importc: "OpenProcess".} when defined(useWinAnsi): proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES, bManualReset: DWORD, bInitialState: DWORD, lpName: cstring): Handle {.stdcall, dynlib: "kernel32", importc: "CreateEventA".} else: proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES, bManualReset: DWORD, bInitialState: DWORD, lpName: ptr Utf16Char): Handle {.stdcall, dynlib: "kernel32", importc: "CreateEventW".} proc setEvent*(hEvent: Handle): cint {.stdcall, dynlib: "kernel32", importc: "SetEvent".} const FD_READ* = 0x00000001'i32 FD_WRITE* = 0x00000002'i32 FD_OOB* = 0x00000004'i32 FD_ACCEPT* = 0x00000008'i32 FD_CONNECT* = 0x00000010'i32 FD_CLOSE* = 0x00000020'i32 FD_QQS* = 0x00000040'i32 FD_GROUP_QQS* = 0x00000080'i32 FD_ROUTING_INTERFACE_CHANGE* = 0x00000100'i32 FD_ADDRESS_LIST_CHANGE* = 0x00000200'i32 FD_ALL_EVENTS* = 0x000003FF'i32 proc wsaEventSelect*(s: SocketHandle, hEventObject: Handle, lNetworkEvents: clong): cint {.stdcall, importc: "WSAEventSelect", dynlib: "ws2_32.dll".} proc wsaCreateEvent*(): Handle {.stdcall, importc: "WSACreateEvent", dynlib: "ws2_32.dll".} proc wsaCloseEvent*(hEvent: Handle): bool {.stdcall, importc: "WSACloseEvent", dynlib: "ws2_32.dll".} proc wsaResetEvent*(hEvent: Handle): bool {.stdcall, importc: "WSAResetEvent", dynlib: "ws2_32.dll".} type KEY_EVENT_RECORD* {.final, pure.} = object eventType*: int16 bKeyDown*: WINBOOL wRepeatCount*: int16 wVirtualKeyCode*: int16 wVirtualScanCode*: int16 uChar*: int16 dwControlKeyState*: DWORD when defined(useWinAnsi): proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint, lpNumberOfEventsRead: ptr cint): cint {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputA".} else: proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint, lpNumberOfEventsRead: ptr cint): cint {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".} type LPFIBER_START_ROUTINE* = proc (param: pointer): void {.stdcall.} const FIBER_FLAG_FLOAT_SWITCH* = 0x01 proc CreateFiber*(stackSize: int, fn: LPFIBER_START_ROUTINE, param: pointer): pointer {.stdcall, discardable, dynlib: "kernel32", importc.} proc CreateFiberEx*(stkCommit: int, stkReserve: int, flags: int32, fn: LPFIBER_START_ROUTINE, param: pointer): pointer {.stdcall, discardable, dynlib: "kernel32", importc.} proc ConvertThreadToFiber*(param: pointer): pointer {.stdcall, discardable, dynlib: "kernel32", importc.} proc ConvertThreadToFiberEx*(param: pointer, flags: int32): pointer {.stdcall, discardable, dynlib: "kernel32", importc.} proc DeleteFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kernel32", importc.} proc SwitchToFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kernel32", importc.} proc GetCurrentFiber*(): pointer {.stdcall, importc, header: "Windows.h".} proc toFILETIME*(t: int64): FILETIME = ## Convert the Windows file time timestamp ``t`` to ``FILETIME``. result = FILETIME(dwLowDateTime: cast[DWORD](t), dwHighDateTime: DWORD(t shr 32)) type LPFILETIME* = ptr FILETIME proc setFileTime*(hFile: HANDLE, lpCreationTime: LPFILETIME, lpLastAccessTime: LPFILETIME, lpLastWriteTime: LPFILETIME): WINBOOL {.stdcall, dynlib: "kernel32", importc: "SetFileTime".}