winlean.nim 47 KB

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