winlean.nim 46 KB

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