winlean.nim 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module implements a small wrapper for some needed Win API procedures,
  10. ## so that the Nim compiler does not depend on the huge Windows module.
  11. import std/dynlib
  12. when defined(nimHasStyleChecks):
  13. {.push styleChecks: off.}
  14. {.passc: "-DWIN32_LEAN_AND_MEAN".}
  15. when defined(nimPreviewSlimSystem):
  16. from std/syncio import FileHandle
  17. import std/widestrs
  18. type WinChar* = Utf16Char
  19. # See https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
  20. type
  21. Handle* = int
  22. LONG* = int32
  23. ULONG* = int32
  24. PULONG* = ptr int
  25. WINBOOL* = int32
  26. ## `WINBOOL` uses opposite convention as posix, !=0 meaning success.
  27. # xxx this should be distinct int32, distinct would make code less error prone
  28. PBOOL* = ptr WINBOOL
  29. DWORD* = int32
  30. PDWORD* = ptr DWORD
  31. LPINT* = ptr int32
  32. ULONG_PTR* = uint
  33. PULONG_PTR* = ptr uint
  34. HDC* = Handle
  35. HGLRC* = Handle
  36. BYTE* = uint8
  37. SECURITY_ATTRIBUTES* = object
  38. nLength*: int32
  39. lpSecurityDescriptor*: pointer
  40. bInheritHandle*: WINBOOL
  41. STARTUPINFO* = object
  42. cb*: int32
  43. lpReserved*: cstring
  44. lpDesktop*: cstring
  45. lpTitle*: cstring
  46. dwX*: int32
  47. dwY*: int32
  48. dwXSize*: int32
  49. dwYSize*: int32
  50. dwXCountChars*: int32
  51. dwYCountChars*: int32
  52. dwFillAttribute*: int32
  53. dwFlags*: int32
  54. wShowWindow*: int16
  55. cbReserved2*: int16
  56. lpReserved2*: pointer
  57. hStdInput*: Handle
  58. hStdOutput*: Handle
  59. hStdError*: Handle
  60. PROCESS_INFORMATION* = object
  61. hProcess*: Handle
  62. hThread*: Handle
  63. dwProcessId*: int32
  64. dwThreadId*: int32
  65. FILETIME* = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
  66. dwLowDateTime*: DWORD
  67. dwHighDateTime*: DWORD
  68. BY_HANDLE_FILE_INFORMATION* = object
  69. dwFileAttributes*: DWORD
  70. ftCreationTime*: FILETIME
  71. ftLastAccessTime*: FILETIME
  72. ftLastWriteTime*: FILETIME
  73. dwVolumeSerialNumber*: DWORD
  74. nFileSizeHigh*: DWORD
  75. nFileSizeLow*: DWORD
  76. nNumberOfLinks*: DWORD
  77. nFileIndexHigh*: DWORD
  78. nFileIndexLow*: DWORD
  79. OSVERSIONINFO* = object
  80. dwOSVersionInfoSize*: DWORD
  81. dwMajorVersion*: DWORD
  82. dwMinorVersion*: DWORD
  83. dwBuildNumber*: DWORD
  84. dwPlatformId*: DWORD
  85. szCSDVersion*: array[0..127, WinChar]
  86. Protoent* = object
  87. p_name*: cstring
  88. p_aliases*: cstringArray
  89. p_proto*: cshort
  90. const
  91. STARTF_USESHOWWINDOW* = 1'i32
  92. STARTF_USESTDHANDLES* = 256'i32
  93. HIGH_PRIORITY_CLASS* = 128'i32
  94. IDLE_PRIORITY_CLASS* = 64'i32
  95. NORMAL_PRIORITY_CLASS* = 32'i32
  96. REALTIME_PRIORITY_CLASS* = 256'i32
  97. WAIT_OBJECT_0* = 0'i32
  98. WAIT_TIMEOUT* = 0x00000102'i32
  99. WAIT_FAILED* = 0xFFFFFFFF'i32
  100. INFINITE* = -1'i32
  101. STILL_ACTIVE* = 0x00000103'i32
  102. STD_INPUT_HANDLE* = -10'i32
  103. STD_OUTPUT_HANDLE* = -11'i32
  104. STD_ERROR_HANDLE* = -12'i32
  105. DETACHED_PROCESS* = 8'i32
  106. SW_SHOWNORMAL* = 1'i32
  107. INVALID_HANDLE_VALUE* = Handle(-1)
  108. CREATE_UNICODE_ENVIRONMENT* = 1024'i32
  109. PIPE_ACCESS_DUPLEX* = 0x00000003'i32
  110. PIPE_ACCESS_INBOUND* = 1'i32
  111. PIPE_ACCESS_OUTBOUND* = 2'i32
  112. PIPE_NOWAIT* = 0x00000001'i32
  113. SYNCHRONIZE* = 0x00100000'i32
  114. CREATE_NO_WINDOW* = 0x08000000'i32
  115. HANDLE_FLAG_INHERIT* = 0x00000001'i32
  116. proc isSuccess*(a: WINBOOL): bool {.inline.} =
  117. ## Returns true if `a != 0`. Windows uses a different convention than POSIX,
  118. ## where `a == 0` is commonly used on success.
  119. a != 0
  120. proc getVersionExW*(lpVersionInfo: ptr OSVERSIONINFO): WINBOOL {.
  121. stdcall, dynlib: "kernel32", importc: "GetVersionExW", sideEffect.}
  122. proc getVersionExA*(lpVersionInfo: ptr OSVERSIONINFO): WINBOOL {.
  123. stdcall, dynlib: "kernel32", importc: "GetVersionExA", sideEffect.}
  124. proc getVersion*(): DWORD {.stdcall, dynlib: "kernel32", importc: "GetVersion", sideEffect.}
  125. proc closeHandle*(hObject: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
  126. importc: "CloseHandle".}
  127. proc readFile*(hFile: Handle, buffer: pointer, nNumberOfBytesToRead: int32,
  128. lpNumberOfBytesRead: ptr int32, lpOverlapped: pointer): WINBOOL{.
  129. stdcall, dynlib: "kernel32", importc: "ReadFile", sideEffect.}
  130. proc writeFile*(hFile: Handle, buffer: pointer, nNumberOfBytesToWrite: int32,
  131. lpNumberOfBytesWritten: ptr int32,
  132. lpOverlapped: pointer): WINBOOL{.
  133. stdcall, dynlib: "kernel32", importc: "WriteFile", sideEffect.}
  134. proc createPipe*(hReadPipe, hWritePipe: var Handle,
  135. lpPipeAttributes: var SECURITY_ATTRIBUTES,
  136. nSize: int32): WINBOOL{.
  137. stdcall, dynlib: "kernel32", importc: "CreatePipe", sideEffect.}
  138. proc createNamedPipe*(lpName: WideCString,
  139. dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize,
  140. nInBufferSize, nDefaultTimeOut: int32,
  141. lpSecurityAttributes: ptr SECURITY_ATTRIBUTES): Handle {.
  142. stdcall, dynlib: "kernel32", importc: "CreateNamedPipeW", sideEffect.}
  143. proc peekNamedPipe*(hNamedPipe: Handle, lpBuffer: pointer=nil,
  144. nBufferSize: int32 = 0,
  145. lpBytesRead: ptr int32 = nil,
  146. lpTotalBytesAvail: ptr int32 = nil,
  147. lpBytesLeftThisMessage: ptr int32 = nil): bool {.
  148. stdcall, dynlib: "kernel32", importc: "PeekNamedPipe".}
  149. proc createProcessW*(lpApplicationName, lpCommandLine: WideCString,
  150. lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
  151. lpThreadAttributes: ptr SECURITY_ATTRIBUTES,
  152. bInheritHandles: WINBOOL, dwCreationFlags: int32,
  153. lpEnvironment, lpCurrentDirectory: WideCString,
  154. lpStartupInfo: var STARTUPINFO,
  155. lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{.
  156. stdcall, dynlib: "kernel32", importc: "CreateProcessW", sideEffect.}
  157. proc suspendThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32",
  158. importc: "SuspendThread", sideEffect.}
  159. proc resumeThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32",
  160. importc: "ResumeThread", sideEffect.}
  161. proc waitForSingleObject*(hHandle: Handle, dwMilliseconds: int32): int32 {.
  162. stdcall, dynlib: "kernel32", importc: "WaitForSingleObject", sideEffect.}
  163. proc terminateProcess*(hProcess: Handle, uExitCode: int): WINBOOL {.stdcall,
  164. dynlib: "kernel32", importc: "TerminateProcess", sideEffect.}
  165. proc getExitCodeProcess*(hProcess: Handle, lpExitCode: var int32): WINBOOL {.
  166. stdcall, dynlib: "kernel32", importc: "GetExitCodeProcess".}
  167. proc getStdHandle*(nStdHandle: int32): Handle {.stdcall, dynlib: "kernel32",
  168. importc: "GetStdHandle".}
  169. proc setStdHandle*(nStdHandle: int32, hHandle: Handle): WINBOOL {.stdcall,
  170. dynlib: "kernel32", importc: "SetStdHandle", sideEffect.}
  171. proc flushFileBuffers*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
  172. importc: "FlushFileBuffers", sideEffect.}
  173. proc getLastError*(): int32 {.importc: "GetLastError",
  174. stdcall, dynlib: "kernel32", sideEffect.}
  175. proc setLastError*(error: int32) {.importc: "SetLastError",
  176. stdcall, dynlib: "kernel32", sideEffect.}
  177. proc formatMessageW*(dwFlags: int32, lpSource: pointer,
  178. dwMessageId, dwLanguageId: int32,
  179. lpBuffer: pointer, nSize: int32,
  180. arguments: pointer): int32 {.
  181. importc: "FormatMessageW", stdcall, dynlib: "kernel32".}
  182. proc localFree*(p: pointer) {.
  183. importc: "LocalFree", stdcall, dynlib: "kernel32".}
  184. proc getCurrentDirectoryW*(nBufferLength: int32,
  185. lpBuffer: WideCString): int32 {.
  186. importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
  187. proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
  188. importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
  189. proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {.
  190. importc: "CreateDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
  191. proc removeDirectoryW*(lpPathName: WideCString): int32 {.
  192. importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
  193. proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
  194. stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW", sideEffect.}
  195. proc getModuleFileNameW*(handle: Handle, buf: WideCString,
  196. size: int32): int32 {.importc: "GetModuleFileNameW",
  197. dynlib: "kernel32", stdcall.}
  198. proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString,
  199. flags: DWORD): int32 {.
  200. importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall, sideEffect.}
  201. proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
  202. security: pointer=nil): int32 {.
  203. importc:"CreateHardLinkW", dynlib: "kernel32", stdcall, sideEffect.}
  204. const
  205. FILE_ATTRIBUTE_READONLY* = 0x00000001'i32
  206. FILE_ATTRIBUTE_HIDDEN* = 0x00000002'i32
  207. FILE_ATTRIBUTE_SYSTEM* = 0x00000004'i32
  208. FILE_ATTRIBUTE_DIRECTORY* = 0x00000010'i32
  209. FILE_ATTRIBUTE_ARCHIVE* = 0x00000020'i32
  210. FILE_ATTRIBUTE_DEVICE* = 0x00000040'i32
  211. FILE_ATTRIBUTE_NORMAL* = 0x00000080'i32
  212. FILE_ATTRIBUTE_TEMPORARY* = 0x00000100'i32
  213. FILE_ATTRIBUTE_SPARSE_FILE* = 0x00000200'i32
  214. FILE_ATTRIBUTE_REPARSE_POINT* = 0x00000400'i32
  215. FILE_ATTRIBUTE_COMPRESSED* = 0x00000800'i32
  216. FILE_ATTRIBUTE_OFFLINE* = 0x00001000'i32
  217. FILE_ATTRIBUTE_NOT_CONTENT_INDEXED* = 0x00002000'i32
  218. FILE_FLAG_FIRST_PIPE_INSTANCE* = 0x00080000'i32
  219. FILE_FLAG_OPEN_NO_RECALL* = 0x00100000'i32
  220. FILE_FLAG_OPEN_REPARSE_POINT* = 0x00200000'i32
  221. FILE_FLAG_POSIX_SEMANTICS* = 0x01000000'i32
  222. FILE_FLAG_BACKUP_SEMANTICS* = 0x02000000'i32
  223. FILE_FLAG_DELETE_ON_CLOSE* = 0x04000000'i32
  224. FILE_FLAG_SEQUENTIAL_SCAN* = 0x08000000'i32
  225. FILE_FLAG_RANDOM_ACCESS* = 0x10000000'i32
  226. FILE_FLAG_NO_BUFFERING* = 0x20000000'i32
  227. FILE_FLAG_OVERLAPPED* = 0x40000000'i32
  228. FILE_FLAG_WRITE_THROUGH* = 0x80000000'i32
  229. MAX_PATH* = 260
  230. MOVEFILE_COPY_ALLOWED* = 0x2'i32
  231. MOVEFILE_CREATE_HARDLINK* = 0x10'i32
  232. MOVEFILE_DELAY_UNTIL_REBOOT* = 0x4'i32
  233. MOVEFILE_FAIL_IF_NOT_TRACKABLE* = 0x20'i32
  234. MOVEFILE_REPLACE_EXISTING* = 0x1'i32
  235. MOVEFILE_WRITE_THROUGH* = 0x8'i32
  236. type
  237. WIN32_FIND_DATA* {.pure.} = object
  238. dwFileAttributes*: int32
  239. ftCreationTime*: FILETIME
  240. ftLastAccessTime*: FILETIME
  241. ftLastWriteTime*: FILETIME
  242. nFileSizeHigh*: int32
  243. nFileSizeLow*: int32
  244. dwReserved0: int32
  245. dwReserved1: int32
  246. cFileName*: array[0..(MAX_PATH) - 1, WinChar]
  247. cAlternateFileName*: array[0..13, WinChar]
  248. proc findFirstFileW*(lpFileName: WideCString,
  249. lpFindFileData: var WIN32_FIND_DATA): Handle {.
  250. stdcall, dynlib: "kernel32", importc: "FindFirstFileW", sideEffect.}
  251. proc findNextFileW*(hFindFile: Handle,
  252. lpFindFileData: var WIN32_FIND_DATA): int32 {.
  253. stdcall, dynlib: "kernel32", importc: "FindNextFileW", sideEffect.}
  254. proc findClose*(hFindFile: Handle) {.stdcall, dynlib: "kernel32",
  255. importc: "FindClose".}
  256. proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
  257. lpBuffer: WideCString,
  258. lpFilePart: var WideCString): int32 {.
  259. stdcall, dynlib: "kernel32",
  260. importc: "GetFullPathNameW", sideEffect.}
  261. proc getFileAttributesW*(lpFileName: WideCString): int32 {.
  262. stdcall, dynlib: "kernel32",
  263. importc: "GetFileAttributesW", sideEffect.}
  264. proc setFileAttributesW*(lpFileName: WideCString,
  265. dwFileAttributes: int32): WINBOOL {.
  266. stdcall, dynlib: "kernel32", importc: "SetFileAttributesW", sideEffect.}
  267. proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString,
  268. bFailIfExists: WINBOOL): WINBOOL {.
  269. importc: "CopyFileW", stdcall, dynlib: "kernel32", sideEffect.}
  270. proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString): WINBOOL {.
  271. importc: "MoveFileW", stdcall, dynlib: "kernel32", sideEffect.}
  272. proc moveFileExW*(lpExistingFileName, lpNewFileName: WideCString,
  273. flags: DWORD): WINBOOL {.
  274. importc: "MoveFileExW", stdcall, dynlib: "kernel32", sideEffect.}
  275. proc getEnvironmentStringsW*(): WideCString {.
  276. stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW", sideEffect.}
  277. proc freeEnvironmentStringsW*(para1: WideCString): int32 {.
  278. stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW", sideEffect.}
  279. proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW",
  280. stdcall, dynlib: "kernel32", sideEffect.}
  281. proc rdFileTime*(f: FILETIME): int64 =
  282. result = int64(cast[uint32](f.dwLowDateTime)) or (int64(cast[uint32](f.dwHighDateTime)) shl 32)
  283. proc rdFileSize*(f: WIN32_FIND_DATA): int64 =
  284. result = int64(cast[uint32](f.nFileSizeLow)) or (int64(cast[uint32](f.nFileSizeHigh)) shl 32)
  285. proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {.
  286. importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall, sideEffect.}
  287. proc sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32",
  288. importc: "Sleep", sideEffect.}
  289. proc shellExecuteW*(hwnd: Handle, lpOperation, lpFile,
  290. lpParameters, lpDirectory: WideCString,
  291. nShowCmd: int32): Handle{.
  292. stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW", sideEffect.}
  293. proc getFileInformationByHandle*(hFile: Handle,
  294. lpFileInformation: ptr BY_HANDLE_FILE_INFORMATION): WINBOOL{.
  295. stdcall, dynlib: "kernel32", importc: "GetFileInformationByHandle", sideEffect.}
  296. const
  297. WSADESCRIPTION_LEN* = 256
  298. WSASYS_STATUS_LEN* = 128
  299. FD_SETSIZE* = 64
  300. MSG_PEEK* = 2
  301. INADDR_ANY* = 0'u32
  302. INADDR_LOOPBACK* = 0x7F000001
  303. INADDR_BROADCAST* = -1
  304. INADDR_NONE* = -1
  305. ws2dll = "Ws2_32.dll"
  306. proc wsaGetLastError*(): cint {.importc: "WSAGetLastError", dynlib: ws2dll, sideEffect.}
  307. type
  308. SocketHandle* = distinct int
  309. type
  310. WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object
  311. wVersion, wHighVersion: int16
  312. szDescription: array[0..WSADESCRIPTION_LEN, char]
  313. szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
  314. iMaxSockets, iMaxUdpDg: int16
  315. lpVendorInfo: cstring
  316. SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object
  317. sa_family*: uint16
  318. sa_data*: array[0..13, char]
  319. PSockAddr = ptr SockAddr
  320. InAddr* {.importc: "IN_ADDR", header: "winsock2.h", union.} = object
  321. s_addr*: uint32 # IP address
  322. Sockaddr_in* {.importc: "SOCKADDR_IN",
  323. header: "winsock2.h".} = object
  324. sin_family*: uint16
  325. sin_port*: uint16
  326. sin_addr*: InAddr
  327. sin_zero*: array[0..7, char]
  328. In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object
  329. bytes* {.importc: "u.Byte".}: array[0..15, char]
  330. Sockaddr_in6* {.importc: "SOCKADDR_IN6",
  331. header: "ws2tcpip.h".} = object
  332. sin6_family*: uint16
  333. sin6_port*: uint16
  334. sin6_flowinfo*: int32 # unsigned
  335. sin6_addr*: In6_addr
  336. sin6_scope_id*: int32 # unsigned
  337. Sockaddr_storage* {.importc: "SOCKADDR_STORAGE",
  338. header: "winsock2.h".} = object
  339. ss_family*: uint16
  340. ss_pad1 {.importc: "__ss_pad1".}: array[6, byte]
  341. ss_align {.importc: "__ss_align".}: int64
  342. ss_pad2 {.importc: "__ss_pad2".}: array[112, byte]
  343. Servent* = object
  344. s_name*: cstring
  345. s_aliases*: cstringArray
  346. when defined(cpu64):
  347. s_proto*: cstring
  348. s_port*: int16
  349. else:
  350. s_port*: int16
  351. s_proto*: cstring
  352. Hostent* = object
  353. h_name*: cstring
  354. h_aliases*: cstringArray
  355. h_addrtype*: int16
  356. h_length*: int16
  357. h_addr_list*: cstringArray
  358. TFdSet* = object
  359. fd_count*: cint # unsigned
  360. fd_array*: array[0..FD_SETSIZE-1, SocketHandle]
  361. AddrInfo* = object
  362. ai_flags*: cint ## Input flags.
  363. ai_family*: cint ## Address family of socket.
  364. ai_socktype*: cint ## Socket type.
  365. ai_protocol*: cint ## Protocol of socket.
  366. ai_addrlen*: csize_t ## Length of socket address.
  367. ai_canonname*: cstring ## Canonical name of service location.
  368. ai_addr*: ptr SockAddr ## Socket address of socket.
  369. ai_next*: ptr AddrInfo ## Pointer to next in list.
  370. SockLen* = cuint
  371. when defined(cpp):
  372. type
  373. Timeval* {.importc: "timeval", header: "<time.h>".} = object
  374. tv_sec*, tv_usec*: int32
  375. else:
  376. type
  377. Timeval* = object
  378. tv_sec*, tv_usec*: int32
  379. var
  380. SOMAXCONN* {.importc, header: "winsock2.h".}: cint
  381. INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle
  382. SOL_SOCKET* {.importc, header: "winsock2.h".}: cint
  383. SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording
  384. SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen()
  385. SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse
  386. 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.
  387. SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive
  388. SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses
  389. SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs
  390. SO_USELOOPBACK* {.importc, header: "winsock2.h".}: cint # bypass hardware when possible
  391. SO_LINGER* {.importc, header: "winsock2.h".}: cint # linger on close if data present
  392. SO_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line
  393. SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint
  394. SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse
  395. SO_ERROR* {.importc, header: "winsock2.h".}: cint
  396. TCP_NODELAY* {.importc, header: "winsock2.h".}: cint
  397. proc `==`*(x, y: SocketHandle): bool {.borrow.}
  398. proc getservbyname*(name, proto: cstring): ptr Servent {.
  399. stdcall, importc: "getservbyname", dynlib: ws2dll, sideEffect.}
  400. proc getservbyport*(port: cint, proto: cstring): ptr Servent {.
  401. stdcall, importc: "getservbyport", dynlib: ws2dll, sideEffect.}
  402. proc gethostbyaddr*(ip: ptr InAddr, len: cuint, theType: cint): ptr Hostent {.
  403. stdcall, importc: "gethostbyaddr", dynlib: ws2dll, sideEffect.}
  404. proc gethostbyname*(name: cstring): ptr Hostent {.
  405. stdcall, importc: "gethostbyname", dynlib: ws2dll, sideEffect.}
  406. proc gethostname*(hostname: cstring, len: cint): cint {.
  407. stdcall, importc: "gethostname", dynlib: ws2dll, sideEffect.}
  408. proc getprotobyname*(
  409. name: cstring
  410. ): ptr Protoent {.stdcall, importc: "getprotobyname", dynlib: ws2dll, sideEffect.}
  411. proc getprotobynumber*(
  412. proto: cint
  413. ): ptr Protoent {.stdcall, importc: "getprotobynumber", dynlib: ws2dll, sideEffect.}
  414. proc socket*(af, typ, protocol: cint): SocketHandle {.
  415. stdcall, importc: "socket", dynlib: ws2dll.}
  416. proc closesocket*(s: SocketHandle): cint {.
  417. stdcall, importc: "closesocket", dynlib: ws2dll.}
  418. proc accept*(s: SocketHandle, a: ptr SockAddr, addrlen: ptr SockLen): SocketHandle {.
  419. stdcall, importc: "accept", dynlib: ws2dll.}
  420. proc bindSocket*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
  421. stdcall, importc: "bind", dynlib: ws2dll.}
  422. proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
  423. stdcall, importc: "connect", dynlib: ws2dll.}
  424. proc getsockname*(s: SocketHandle, name: ptr SockAddr,
  425. namelen: ptr SockLen): cint {.
  426. stdcall, importc: "getsockname", dynlib: ws2dll.}
  427. proc getpeername*(s: SocketHandle, name: ptr SockAddr,
  428. namelen: ptr SockLen): cint {.
  429. stdcall, importc, dynlib: ws2dll.}
  430. proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
  431. optlen: ptr SockLen): cint {.
  432. stdcall, importc: "getsockopt", dynlib: ws2dll.}
  433. proc setsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
  434. optlen: SockLen): cint {.
  435. stdcall, importc: "setsockopt", dynlib: ws2dll.}
  436. proc listen*(s: SocketHandle, backlog: cint): cint {.
  437. stdcall, importc: "listen", dynlib: ws2dll.}
  438. proc recv*(s: SocketHandle, buf: pointer, len, flags: cint): cint {.
  439. stdcall, importc: "recv", dynlib: ws2dll.}
  440. proc recvfrom*(s: SocketHandle, buf: cstring, len, flags: cint,
  441. fromm: ptr SockAddr, fromlen: ptr SockLen): cint {.
  442. stdcall, importc: "recvfrom", dynlib: ws2dll.}
  443. proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet,
  444. timeout: ptr Timeval): cint {.
  445. stdcall, importc: "select", dynlib: ws2dll.}
  446. proc send*(s: SocketHandle, buf: pointer, len, flags: cint): cint {.
  447. stdcall, importc: "send", dynlib: ws2dll.}
  448. proc sendto*(s: SocketHandle, buf: pointer, len, flags: cint,
  449. to: ptr SockAddr, tolen: SockLen): cint {.
  450. stdcall, importc: "sendto", dynlib: ws2dll.}
  451. proc shutdown*(s: SocketHandle, how: cint): cint {.
  452. stdcall, importc: "shutdown", dynlib: ws2dll.}
  453. proc getnameinfo*(a1: ptr SockAddr, a2: SockLen,
  454. a3: cstring, a4: SockLen, a5: cstring,
  455. a6: SockLen, a7: cint): cint {.
  456. stdcall, importc: "getnameinfo", dynlib: ws2dll.}
  457. proc inet_addr*(cp: cstring): uint32 {.
  458. stdcall, importc: "inet_addr", dynlib: ws2dll.}
  459. proc WSAFDIsSet(s: SocketHandle, set: var TFdSet): bool {.
  460. stdcall, importc: "__WSAFDIsSet", dynlib: ws2dll, noSideEffect.}
  461. proc FD_ISSET*(socket: SocketHandle, set: var TFdSet): cint =
  462. result = if WSAFDIsSet(socket, set): 1'i32 else: 0'i32
  463. proc FD_SET*(socket: SocketHandle, s: var TFdSet) =
  464. if s.fd_count < FD_SETSIZE:
  465. s.fd_array[int(s.fd_count)] = socket
  466. inc(s.fd_count)
  467. proc FD_ZERO*(s: var TFdSet) =
  468. s.fd_count = 0
  469. proc wsaStartup*(wVersionRequired: int16, WSData: ptr WSAData): cint {.
  470. stdcall, importc: "WSAStartup", dynlib: ws2dll.}
  471. proc getaddrinfo*(nodename, servname: cstring, hints: ptr AddrInfo,
  472. res: var ptr AddrInfo): cint {.
  473. stdcall, importc: "getaddrinfo", dynlib: ws2dll.}
  474. proc freeAddrInfo*(ai: ptr AddrInfo) {.
  475. stdcall, importc: "freeaddrinfo", dynlib: ws2dll.}
  476. proc inet_ntoa*(i: InAddr): cstring {.
  477. stdcall, importc, dynlib: ws2dll.}
  478. const
  479. MAXIMUM_WAIT_OBJECTS* = 0x00000040
  480. type
  481. WOHandleArray* = array[0..MAXIMUM_WAIT_OBJECTS - 1, Handle]
  482. PWOHandleArray* = ptr WOHandleArray
  483. proc waitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray,
  484. bWaitAll: WINBOOL, dwMilliseconds: DWORD): DWORD{.
  485. stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
  486. # for memfiles.nim:
  487. const
  488. GENERIC_READ* = 0x80000000'i32
  489. GENERIC_WRITE* = 0x40000000'i32
  490. GENERIC_ALL* = 0x10000000'i32
  491. FILE_SHARE_READ* = 1'i32
  492. FILE_SHARE_DELETE* = 4'i32
  493. FILE_SHARE_WRITE* = 2'i32
  494. CREATE_ALWAYS* = 2'i32
  495. CREATE_NEW* = 1'i32
  496. OPEN_EXISTING* = 3'i32
  497. OPEN_ALWAYS* = 4'i32
  498. FILE_BEGIN* = 0'i32
  499. INVALID_SET_FILE_POINTER* = -1'i32
  500. NO_ERROR* = 0'i32
  501. PAGE_NOACCESS* = 0x01'i32
  502. PAGE_EXECUTE* = 0x10'i32
  503. PAGE_EXECUTE_READ* = 0x20'i32
  504. PAGE_EXECUTE_READWRITE* = 0x40'i32
  505. PAGE_READONLY* = 2'i32
  506. PAGE_READWRITE* = 4'i32
  507. FILE_MAP_READ* = 4'i32
  508. FILE_MAP_WRITE* = 2'i32
  509. INVALID_FILE_SIZE* = -1'i32
  510. DUPLICATE_SAME_ACCESS* = 2
  511. FILE_READ_DATA* = 0x00000001 # file & pipe
  512. FILE_WRITE_DATA* = 0x00000002 # file & pipe
  513. # Error Constants
  514. const
  515. ERROR_FILE_NOT_FOUND* = 2 ## https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
  516. ERROR_PATH_NOT_FOUND* = 3
  517. ERROR_ACCESS_DENIED* = 5
  518. ERROR_NO_MORE_FILES* = 18
  519. ERROR_LOCK_VIOLATION* = 33
  520. ERROR_HANDLE_EOF* = 38
  521. ERROR_FILE_EXISTS* = 80
  522. ERROR_BAD_ARGUMENTS* = 165
  523. proc duplicateHandle*(hSourceProcessHandle: Handle, hSourceHandle: Handle,
  524. hTargetProcessHandle: Handle,
  525. lpTargetHandle: ptr Handle,
  526. dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
  527. dwOptions: DWORD): WINBOOL{.stdcall, dynlib: "kernel32",
  528. importc: "DuplicateHandle".}
  529. proc getHandleInformation*(hObject: Handle, lpdwFlags: ptr DWORD): WINBOOL {.
  530. stdcall, dynlib: "kernel32", importc: "GetHandleInformation".}
  531. proc setHandleInformation*(hObject: Handle, dwMask: DWORD,
  532. dwFlags: DWORD): WINBOOL {.stdcall,
  533. dynlib: "kernel32", importc: "SetHandleInformation".}
  534. proc getCurrentProcess*(): Handle{.stdcall, dynlib: "kernel32",
  535. importc: "GetCurrentProcess".}
  536. proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD,
  537. lpSecurityAttributes: pointer,
  538. dwCreationDisposition, dwFlagsAndAttributes: DWORD,
  539. hTemplateFile: Handle): Handle {.
  540. stdcall, dynlib: "kernel32", importc: "CreateFileW".}
  541. proc deleteFileW*(pathName: WideCString): int32 {.
  542. importc: "DeleteFileW", dynlib: "kernel32", stdcall.}
  543. proc createFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
  544. lpSecurityAttributes: pointer,
  545. dwCreationDisposition, dwFlagsAndAttributes: DWORD,
  546. hTemplateFile: Handle): Handle {.
  547. stdcall, dynlib: "kernel32", importc: "CreateFileA".}
  548. proc deleteFileA*(pathName: cstring): int32 {.
  549. importc: "DeleteFileA", dynlib: "kernel32", stdcall.}
  550. proc setEndOfFile*(hFile: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
  551. importc: "SetEndOfFile".}
  552. proc setFilePointer*(hFile: Handle, lDistanceToMove: LONG,
  553. lpDistanceToMoveHigh: ptr LONG,
  554. dwMoveMethod: DWORD): DWORD {.
  555. stdcall, dynlib: "kernel32", importc: "SetFilePointer".}
  556. proc getFileSize*(hFile: Handle, lpFileSizeHigh: ptr DWORD): DWORD{.stdcall,
  557. dynlib: "kernel32", importc: "GetFileSize".}
  558. when defined(cpu32):
  559. type
  560. WinSizeT* = uint32
  561. else:
  562. type
  563. WinSizeT* = uint64
  564. proc mapViewOfFileEx*(hFileMappingObject: Handle, dwDesiredAccess: DWORD,
  565. dwFileOffsetHigh, dwFileOffsetLow: DWORD,
  566. dwNumberOfBytesToMap: WinSizeT,
  567. lpBaseAddress: pointer): pointer{.
  568. stdcall, dynlib: "kernel32", importc: "MapViewOfFileEx".}
  569. proc createFileMappingW*(hFile: Handle,
  570. lpFileMappingAttributes: pointer,
  571. flProtect, dwMaximumSizeHigh: DWORD,
  572. dwMaximumSizeLow: DWORD,
  573. lpName: pointer): Handle {.
  574. stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
  575. proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
  576. dynlib: "kernel32", importc: "UnmapViewOfFile".}
  577. proc flushViewOfFile*(lpBaseAddress: pointer, dwNumberOfBytesToFlush: DWORD): WINBOOL {.
  578. stdcall, dynlib: "kernel32", importc: "FlushViewOfFile".}
  579. type
  580. OVERLAPPED* {.pure, inheritable.} = object
  581. internal*: PULONG
  582. internalHigh*: PULONG
  583. offset*: DWORD
  584. offsetHigh*: DWORD
  585. hEvent*: Handle
  586. POVERLAPPED* = ptr OVERLAPPED
  587. POVERLAPPED_COMPLETION_ROUTINE* = proc (para1: DWORD, para2: DWORD,
  588. para3: POVERLAPPED){.stdcall.}
  589. GUID* = object
  590. D1*: int32
  591. D2*: int16
  592. D3*: int16
  593. D4*: array[0..7, int8]
  594. const
  595. ERROR_IO_PENDING* = 997 # a.k.a WSA_IO_PENDING
  596. WSAECONNABORTED* = 10053
  597. WSAEADDRINUSE* = 10048
  598. WSAECONNRESET* = 10054
  599. WSAEDISCON* = 10101
  600. WSAENETRESET* = 10052
  601. WSAETIMEDOUT* = 10060
  602. WSANOTINITIALISED* = 10093
  603. WSAENOTSOCK* = 10038
  604. WSAEINPROGRESS* = 10036
  605. WSAEINTR* = 10004
  606. WSAEWOULDBLOCK* = 10035
  607. WSAESHUTDOWN* = 10058
  608. ERROR_NETNAME_DELETED* = 64
  609. STATUS_PENDING* = 0x103
  610. proc createIoCompletionPort*(FileHandle: Handle, ExistingCompletionPort: Handle,
  611. CompletionKey: ULONG_PTR,
  612. NumberOfConcurrentThreads: DWORD): Handle{.stdcall,
  613. dynlib: "kernel32", importc: "CreateIoCompletionPort".}
  614. proc getQueuedCompletionStatus*(CompletionPort: Handle,
  615. lpNumberOfBytesTransferred: PDWORD, lpCompletionKey: PULONG_PTR,
  616. lpOverlapped: ptr POVERLAPPED,
  617. dwMilliseconds: DWORD): WINBOOL{.stdcall,
  618. dynlib: "kernel32", importc: "GetQueuedCompletionStatus".}
  619. proc getOverlappedResult*(hFile: Handle, lpOverlapped: POVERLAPPED,
  620. lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{.
  621. stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".}
  622. # this is copy of HasOverlappedIoCompleted() macro from <winbase.h>
  623. # because we have declared own OVERLAPPED structure with member names not
  624. # compatible with original names.
  625. template hasOverlappedIoCompleted*(lpOverlapped): bool =
  626. (cast[uint](lpOverlapped.internal) != STATUS_PENDING)
  627. const
  628. IOC_OUT* = 0x40000000'i32
  629. IOC_IN* = 0x80000000'i32
  630. IOC_WS2* = 0x08000000'i32
  631. IOC_INOUT* = IOC_IN or IOC_OUT
  632. template WSAIORW*(x,y): untyped = (IOC_INOUT or x or y)
  633. const
  634. SIO_GET_EXTENSION_FUNCTION_POINTER* = WSAIORW(IOC_WS2,6).DWORD
  635. SO_UPDATE_ACCEPT_CONTEXT* = 0x700B
  636. AI_V4MAPPED* = 0x0008
  637. AF_UNSPEC* = 0
  638. AF_INET* = 2
  639. AF_INET6* = 23
  640. var
  641. WSAID_CONNECTEX*: GUID = GUID(D1: 0x25a207b9, D2: 0xddf3'i16, D3: 0x4660, D4: [
  642. 0x8e'i8, 0xe9'i8, 0x76'i8, 0xe5'i8, 0x8c'i8, 0x74'i8, 0x06'i8, 0x3e'i8])
  643. WSAID_ACCEPTEX*: GUID = GUID(D1: 0xb5367df1'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [
  644. 0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8])
  645. WSAID_GETACCEPTEXSOCKADDRS*: GUID = GUID(D1: 0xb5367df2'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [
  646. 0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8])
  647. proc WSAIoctl*(s: SocketHandle, dwIoControlCode: DWORD, lpvInBuffer: pointer,
  648. cbInBuffer: DWORD, lpvOutBuffer: pointer, cbOutBuffer: DWORD,
  649. lpcbBytesReturned: PDWORD, lpOverlapped: POVERLAPPED,
  650. lpCompletionRoutine: POVERLAPPED_COMPLETION_ROUTINE): cint
  651. {.stdcall, importc: "WSAIoctl", dynlib: "Ws2_32.dll".}
  652. type
  653. TWSABuf* {.importc: "WSABUF", header: "winsock2.h".} = object
  654. len*: ULONG
  655. buf*: cstring
  656. proc WSARecv*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
  657. bytesReceived, flags: PDWORD, lpOverlapped: POVERLAPPED,
  658. completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
  659. stdcall, importc: "WSARecv", dynlib: "Ws2_32.dll".}
  660. proc WSARecvFrom*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
  661. bytesReceived: PDWORD, flags: PDWORD, name: ptr SockAddr,
  662. namelen: ptr cint, lpOverlapped: POVERLAPPED,
  663. completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
  664. stdcall, importc: "WSARecvFrom", dynlib: "Ws2_32.dll".}
  665. proc WSASend*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
  666. bytesSent: PDWORD, flags: DWORD, lpOverlapped: POVERLAPPED,
  667. completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
  668. stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".}
  669. proc WSASendTo*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
  670. bytesSent: PDWORD, flags: DWORD, name: ptr SockAddr,
  671. namelen: cint, lpOverlapped: POVERLAPPED,
  672. completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
  673. stdcall, importc: "WSASendTo", dynlib: "Ws2_32.dll".}
  674. proc get_osfhandle*(fd:FileHandle): Handle {.
  675. importc: "_get_osfhandle", header:"<io.h>".}
  676. proc getSystemTimes*(lpIdleTime, lpKernelTime,
  677. lpUserTime: var FILETIME): WINBOOL {.stdcall,
  678. dynlib: "kernel32", importc: "GetSystemTimes".}
  679. proc getProcessTimes*(hProcess: Handle; lpCreationTime, lpExitTime,
  680. lpKernelTime, lpUserTime: var FILETIME): WINBOOL {.stdcall,
  681. dynlib: "kernel32", importc: "GetProcessTimes".}
  682. proc getSystemTimePreciseAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {.
  683. importc: "GetSystemTimePreciseAsFileTime", dynlib: "kernel32", stdcall, sideEffect.}
  684. type inet_ntop_proc = proc(family: cint, paddr: pointer, pStringBuffer: cstring,
  685. stringBufSize: int32): cstring {.gcsafe, stdcall, tags: [].}
  686. var inet_ntop_real: inet_ntop_proc = nil
  687. let ws2 = loadLib(ws2dll)
  688. if ws2 != nil:
  689. inet_ntop_real = cast[inet_ntop_proc](symAddr(ws2, "inet_ntop"))
  690. proc WSAAddressToStringA(pAddr: ptr SockAddr, addrSize: DWORD, unused: pointer, pBuff: cstring, pBuffSize: ptr DWORD): cint {.stdcall, importc, dynlib: ws2dll.}
  691. proc inet_ntop_emulated(family: cint, paddr: pointer, pStringBuffer: cstring,
  692. stringBufSize: int32): cstring {.stdcall.} =
  693. case family
  694. of AF_INET:
  695. var sa: Sockaddr_in
  696. sa.sin_family = AF_INET
  697. sa.sin_addr = cast[ptr InAddr](paddr)[]
  698. var bs = stringBufSize.DWORD
  699. let r = WSAAddressToStringA(cast[ptr SockAddr](sa.addr), sa.sizeof.DWORD, nil, pStringBuffer, bs.addr)
  700. if r != 0:
  701. result = nil
  702. else:
  703. result = pStringBuffer
  704. of AF_INET6:
  705. var sa: Sockaddr_in6
  706. sa.sin6_family = AF_INET6
  707. sa.sin6_addr = cast[ptr In6_addr](paddr)[]
  708. var bs = stringBufSize.DWORD
  709. let r = WSAAddressToStringA(cast[ptr SockAddr](sa.addr), sa.sizeof.DWORD, nil, pStringBuffer, bs.addr)
  710. if r != 0:
  711. result = nil
  712. else:
  713. result = pStringBuffer
  714. else:
  715. setLastError(ERROR_BAD_ARGUMENTS)
  716. result = nil
  717. proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
  718. stringBufSize: int32): cstring {.stdcall.} =
  719. var ver: OSVERSIONINFO
  720. ver.dwOSVersionInfoSize = sizeof(ver).DWORD
  721. let res = getVersionExW(ver.addr)
  722. if res == 0:
  723. result = nil
  724. elif ver.dwMajorVersion >= 6:
  725. if inet_ntop_real == nil:
  726. quit("Can't load inet_ntop proc from " & ws2dll)
  727. result = inet_ntop_real(family, paddr, pStringBuffer, stringBufSize)
  728. else:
  729. result = inet_ntop_emulated(family, paddr, pStringBuffer, stringBufSize)
  730. type
  731. WSAPROC_ACCEPTEX* = proc (sListenSocket: SocketHandle,
  732. sAcceptSocket: SocketHandle,
  733. lpOutputBuffer: pointer, dwReceiveDataLength: DWORD,
  734. dwLocalAddressLength: DWORD,
  735. dwRemoteAddressLength: DWORD,
  736. lpdwBytesReceived: ptr DWORD,
  737. lpOverlapped: POVERLAPPED): bool {.
  738. stdcall, gcsafe, raises: [].}
  739. WSAPROC_CONNECTEX* = proc (s: SocketHandle, name: ptr SockAddr, namelen: cint,
  740. lpSendBuffer: pointer, dwSendDataLength: DWORD,
  741. lpdwBytesSent: ptr DWORD,
  742. lpOverlapped: POVERLAPPED): bool {.
  743. stdcall, gcsafe, raises: [].}
  744. WSAPROC_GETACCEPTEXSOCKADDRS* = proc(lpOutputBuffer: pointer,
  745. dwReceiveDataLength: DWORD,
  746. dwLocalAddressLength: DWORD,
  747. dwRemoteAddressLength: DWORD,
  748. LocalSockaddr: ptr PSockAddr,
  749. LocalSockaddrLength: ptr cint,
  750. RemoteSockaddr: ptr PSockAddr,
  751. RemoteSockaddrLength: ptr cint) {.
  752. stdcall, gcsafe, raises: [].}
  753. const
  754. WT_EXECUTEDEFAULT* = 0x00000000'i32
  755. WT_EXECUTEINIOTHREAD* = 0x00000001'i32
  756. WT_EXECUTEINUITHREAD* = 0x00000002'i32
  757. WT_EXECUTEINWAITTHREAD* = 0x00000004'i32
  758. WT_EXECUTEONLYONCE* = 0x00000008'i32
  759. WT_EXECUTELONGFUNCTION* = 0x00000010'i32
  760. WT_EXECUTEINTIMERTHREAD* = 0x00000020'i32
  761. WT_EXECUTEINPERSISTENTIOTHREAD* = 0x00000040'i32
  762. WT_EXECUTEINPERSISTENTTHREAD* = 0x00000080'i32
  763. WT_TRANSFER_IMPERSONATION* = 0x00000100'i32
  764. PROCESS_TERMINATE* = 0x00000001'i32
  765. PROCESS_CREATE_THREAD* = 0x00000002'i32
  766. PROCESS_SET_SESSIONID* = 0x00000004'i32
  767. PROCESS_VM_OPERATION* = 0x00000008'i32
  768. PROCESS_VM_READ* = 0x00000010'i32
  769. PROCESS_VM_WRITE* = 0x00000020'i32
  770. PROCESS_DUP_HANDLE* = 0x00000040'i32
  771. PROCESS_CREATE_PROCESS* = 0x00000080'i32
  772. PROCESS_SET_QUOTA* = 0x00000100'i32
  773. PROCESS_SET_INFORMATION* = 0x00000200'i32
  774. PROCESS_QUERY_INFORMATION* = 0x00000400'i32
  775. PROCESS_SUSPEND_RESUME* = 0x00000800'i32
  776. PROCESS_QUERY_LIMITED_INFORMATION* = 0x00001000'i32
  777. PROCESS_SET_LIMITED_INFORMATION* = 0x00002000'i32
  778. type
  779. WAITORTIMERCALLBACK* = proc(para1: pointer, para2: int32) {.stdcall.}
  780. proc postQueuedCompletionStatus*(CompletionPort: Handle,
  781. dwNumberOfBytesTransferred: DWORD,
  782. dwCompletionKey: ULONG_PTR,
  783. lpOverlapped: pointer): bool
  784. {.stdcall, dynlib: "kernel32", importc: "PostQueuedCompletionStatus".}
  785. proc registerWaitForSingleObject*(phNewWaitObject: ptr Handle, hObject: Handle,
  786. Callback: WAITORTIMERCALLBACK,
  787. Context: pointer,
  788. dwMilliseconds: ULONG,
  789. dwFlags: ULONG): bool
  790. {.stdcall, dynlib: "kernel32", importc: "RegisterWaitForSingleObject".}
  791. proc unregisterWait*(WaitHandle: Handle): DWORD
  792. {.stdcall, dynlib: "kernel32", importc: "UnregisterWait".}
  793. proc openProcess*(dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
  794. dwProcessId: DWORD): Handle
  795. {.stdcall, dynlib: "kernel32", importc: "OpenProcess".}
  796. proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES,
  797. bManualReset: DWORD, bInitialState: DWORD,
  798. lpName: ptr Utf16Char): Handle
  799. {.stdcall, dynlib: "kernel32", importc: "CreateEventW".}
  800. proc setEvent*(hEvent: Handle): cint
  801. {.stdcall, dynlib: "kernel32", importc: "SetEvent".}
  802. const
  803. FD_READ* = 0x00000001'i32
  804. FD_WRITE* = 0x00000002'i32
  805. FD_OOB* = 0x00000004'i32
  806. FD_ACCEPT* = 0x00000008'i32
  807. FD_CONNECT* = 0x00000010'i32
  808. FD_CLOSE* = 0x00000020'i32
  809. FD_QQS* = 0x00000040'i32
  810. FD_GROUP_QQS* = 0x00000080'i32
  811. FD_ROUTING_INTERFACE_CHANGE* = 0x00000100'i32
  812. FD_ADDRESS_LIST_CHANGE* = 0x00000200'i32
  813. FD_ALL_EVENTS* = 0x000003FF'i32
  814. proc wsaEventSelect*(s: SocketHandle, hEventObject: Handle,
  815. lNetworkEvents: clong): cint
  816. {.stdcall, importc: "WSAEventSelect", dynlib: "ws2_32.dll".}
  817. proc wsaCreateEvent*(): Handle
  818. {.stdcall, importc: "WSACreateEvent", dynlib: "ws2_32.dll".}
  819. proc wsaCloseEvent*(hEvent: Handle): bool
  820. {.stdcall, importc: "WSACloseEvent", dynlib: "ws2_32.dll".}
  821. proc wsaResetEvent*(hEvent: Handle): bool
  822. {.stdcall, importc: "WSAResetEvent", dynlib: "ws2_32.dll".}
  823. type
  824. KEY_EVENT_RECORD* = object
  825. eventType*: int16
  826. bKeyDown*: WINBOOL
  827. wRepeatCount*: int16
  828. wVirtualKeyCode*: int16
  829. wVirtualScanCode*: int16
  830. uChar*: int16
  831. dwControlKeyState*: DWORD
  832. proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
  833. lpNumberOfEventsRead: ptr cint): cint
  834. {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
  835. type
  836. LPFIBER_START_ROUTINE* = proc (param: pointer) {.stdcall.}
  837. const
  838. FIBER_FLAG_FLOAT_SWITCH* = 0x01
  839. proc CreateFiber*(stackSize: int, fn: LPFIBER_START_ROUTINE, param: pointer): pointer {.stdcall, discardable, dynlib: "kernel32", importc.}
  840. proc CreateFiberEx*(stkCommit: int, stkReserve: int, flags: int32, fn: LPFIBER_START_ROUTINE, param: pointer): pointer {.stdcall, discardable, dynlib: "kernel32", importc.}
  841. proc ConvertThreadToFiber*(param: pointer): pointer {.stdcall, discardable, dynlib: "kernel32", importc.}
  842. proc ConvertThreadToFiberEx*(param: pointer, flags: int32): pointer {.stdcall, discardable, dynlib: "kernel32", importc.}
  843. proc DeleteFiber*(fiber: pointer) {.stdcall, discardable, dynlib: "kernel32", importc.}
  844. proc SwitchToFiber*(fiber: pointer) {.stdcall, discardable, dynlib: "kernel32", importc.}
  845. proc GetCurrentFiber*(): pointer {.stdcall, importc, header: "windows.h".}
  846. proc toFILETIME*(t: int64): FILETIME =
  847. ## Convert the Windows file time timestamp `t` to `FILETIME`.
  848. result = FILETIME(dwLowDateTime: cast[DWORD](t), dwHighDateTime: DWORD(t shr 32))
  849. type
  850. LPFILETIME* = ptr FILETIME
  851. proc setFileTime*(hFile: Handle, lpCreationTime: LPFILETIME,
  852. lpLastAccessTime: LPFILETIME, lpLastWriteTime: LPFILETIME): WINBOOL
  853. {.stdcall, dynlib: "kernel32", importc: "SetFileTime".}
  854. type
  855. # https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid_identifier_authority
  856. SID_IDENTIFIER_AUTHORITY* {.importc, header: "<windows.h>".} = object
  857. value* {.importc: "Value".}: array[6, BYTE]
  858. # https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid
  859. SID* {.importc, header: "<windows.h>".} = object
  860. Revision: BYTE
  861. SubAuthorityCount: BYTE
  862. IdentifierAuthority: SID_IDENTIFIER_AUTHORITY
  863. SubAuthority: ptr ptr DWORD
  864. PSID* = ptr SID
  865. const
  866. # https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-components
  867. # https://github.com/mirror/mingw-w64/blob/84c950bdab7c999ace49fe8383856be77f88c4a8/mingw-w64-headers/include/winnt.h#L2994
  868. SECURITY_NT_AUTHORITY* = [BYTE(0), BYTE(0), BYTE(0), BYTE(0), BYTE(0), BYTE(5)]
  869. SECURITY_BUILTIN_DOMAIN_RID* = 32
  870. DOMAIN_ALIAS_RID_ADMINS* = 544
  871. proc allocateAndInitializeSid*(pIdentifierAuthority: ptr SID_IDENTIFIER_AUTHORITY,
  872. nSubAuthorityCount: BYTE,
  873. nSubAuthority0: DWORD,
  874. nSubAuthority1: DWORD,
  875. nSubAuthority2: DWORD,
  876. nSubAuthority3: DWORD,
  877. nSubAuthority4: DWORD,
  878. nSubAuthority5: DWORD,
  879. nSubAuthority6: DWORD,
  880. nSubAuthority7: DWORD,
  881. pSid: ptr PSID): WINBOOL
  882. {.stdcall, dynlib: "Advapi32", importc: "AllocateAndInitializeSid".}
  883. proc checkTokenMembership*(tokenHandle: Handle, sidToCheck: PSID,
  884. isMember: PBOOL): WINBOOL
  885. {.stdcall, dynlib: "Advapi32", importc: "CheckTokenMembership".}
  886. proc freeSid*(pSid: PSID): PSID
  887. {.stdcall, dynlib: "Advapi32", importc: "FreeSid".}
  888. when defined(nimHasStyleChecks):
  889. {.pop.} # {.push styleChecks: off.}