remove decades-deprecated Win32 API *A function support (#21315)

This commit is contained in:
tersec 2023-03-02 04:51:54 +00:00 • committed by GitHub
commit 612abda4f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 173 additions and 414 deletions

View file

@ -102,14 +102,9 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile =
let flags = FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL let flags = FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL
let desiredAccess = getDesiredAccess(mode) let desiredAccess = getDesiredAccess(mode)
let creationDisposition = getCreationDisposition(mode, filename) let creationDisposition = getCreationDisposition(mode, filename)
when useWinUnicode: let fd = createFileW(newWideCString(filename), desiredAccess,
let fd = createFileW(newWideCString(filename), desiredAccess, FILE_SHARE_READ,
FILE_SHARE_READ, nil, creationDisposition, flags, 0)
nil, creationDisposition, flags, 0)
else:
let fd = createFileA(filename, desiredAccess,
FILE_SHARE_READ,
nil, creationDisposition, flags, 0)
if fd == INVALID_HANDLE_VALUE: if fd == INVALID_HANDLE_VALUE:
raiseOSError(osLastError()) raiseOSError(osLastError())

View file

@ -21,7 +21,7 @@ when defined(nimPreviewSlimSystem):
when defined(windows): when defined(windows):
import winlean import winlean
when useWinUnicode and defined(nimPreviewSlimSystem): when defined(nimPreviewSlimSystem):
import std/widestrs import std/widestrs
from os import absolutePath from os import absolutePath
else: else:

View file

@ -17,7 +17,7 @@
when defined(windows): when defined(windows):
import winlean import winlean
when useWinUnicode and defined(nimPreviewSlimSystem): when defined(nimPreviewSlimSystem):
import std/widestrs import std/widestrs
elif defined(posix): elif defined(posix):
import posix import posix
@ -199,10 +199,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
else: FILE_ATTRIBUTE_NORMAL or flags, else: FILE_ATTRIBUTE_NORMAL or flags,
0) 0)
when useWinUnicode: result.fHandle = callCreateFile(createFileW, newWideCString(filename))
result.fHandle = callCreateFile(createFileW, newWideCString(filename))
else:
result.fHandle = callCreateFile(createFileA, filename)
if result.fHandle == INVALID_HANDLE_VALUE: if result.fHandle == INVALID_HANDLE_VALUE:
fail(osLastError(), "error opening file") fail(osLastError(), "error opening file")

View file

@ -422,32 +422,18 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
## Raises `OSError` in case of an error. Follows symlinks. ## Raises `OSError` in case of an error. Follows symlinks.
when defined(windows): when defined(windows):
var bufsize = MAX_PATH.int32 var bufsize = MAX_PATH.int32
when useWinUnicode: var unused: WideCString = nil
var unused: WideCString = nil var res = newWideCString("", bufsize)
var res = newWideCString("", bufsize) while true:
while true: var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused)
var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused) if L == 0'i32:
if L == 0'i32: raiseOSError(osLastError(), filename)
raiseOSError(osLastError(), filename) elif L > bufsize:
elif L > bufsize: res = newWideCString("", L)
res = newWideCString("", L) bufsize = L
bufsize = L else:
else: result = res$L
result = res$L break
break
else:
var unused: cstring = nil
result = newString(bufsize)
while true:
var L = getFullPathNameA(filename, bufsize, result, unused)
if L == 0'i32:
raiseOSError(osLastError(), filename)
elif L > bufsize:
result = newString(L)
bufsize = L
else:
setLen(result, L)
break
# getFullPathName doesn't do case corrections, so we have to use this convoluted # getFullPathName doesn't do case corrections, so we have to use this convoluted
# way of retrieving the true filename # way of retrieving the true filename
for x in walkFiles(result): for x in walkFiles(result):
@ -483,14 +469,10 @@ proc createHardlink*(src, dest: string) {.noWeirdTarget.} =
## See also: ## See also:
## * `createSymlink proc`_ ## * `createSymlink proc`_
when defined(windows): when defined(windows):
when useWinUnicode: var wSrc = newWideCString(src)
var wSrc = newWideCString(src) var wDst = newWideCString(dest)
var wDst = newWideCString(dest) if createHardLinkW(wDst, wSrc, nil) == 0:
if createHardLinkW(wDst, wSrc, nil) == 0: raiseOSError(osLastError(), $(src, dest))
raiseOSError(osLastError(), $(src, dest))
else:
if createHardLinkA(dest, src, nil) == 0:
raiseOSError(osLastError(), $(src, dest))
else: else:
if link(src, dest) != 0: if link(src, dest) != 0:
raiseOSError(osLastError(), $(src, dest)) raiseOSError(osLastError(), $(src, dest))
@ -655,32 +637,18 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW
# /proc/<pid>/path/a.out (complete pathname) # /proc/<pid>/path/a.out (complete pathname)
when defined(windows): when defined(windows):
var bufsize = int32(MAX_PATH) var bufsize = int32(MAX_PATH)
when useWinUnicode: var buf = newWideCString("", bufsize)
var buf = newWideCString("", bufsize) while true:
while true: var L = getModuleFileNameW(0, buf, bufsize)
var L = getModuleFileNameW(0, buf, bufsize) if L == 0'i32:
if L == 0'i32: result = "" # error!
result = "" # error! break
break elif L > bufsize:
elif L > bufsize: buf = newWideCString("", L)
buf = newWideCString("", L) bufsize = L
bufsize = L else:
else: result = buf$L
result = buf$L break
break
else:
result = newString(bufsize)
while true:
var L = getModuleFileNameA(0, result, bufsize)
if L == 0'i32:
result = "" # error!
break
elif L > bufsize:
result = newString(L)
bufsize = L
else:
setLen(result, L)
break
elif defined(macosx): elif defined(macosx):
var size = cuint32(0) var size = cuint32(0)
getExecPath1(nil, size) getExecPath1(nil, size)
@ -977,10 +945,7 @@ proc isHidden*(path: string): bool {.noWeirdTarget.} =
assert ".foo/".isHidden assert ".foo/".isHidden
when defined(windows): when defined(windows):
when useWinUnicode: wrapUnary(attributes, getFileAttributesW, path)
wrapUnary(attributes, getFileAttributesW, path)
else:
var attributes = getFileAttributesA(path)
if attributes != -1'i32: if attributes != -1'i32:
result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32 result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
else: else:

View file

@ -714,22 +714,15 @@ when defined(windows) and not defined(useNimRtl):
if len(workingDir) > 0: wd = workingDir if len(workingDir) > 0: wd = workingDir
if env != nil: e = buildEnv(env) if env != nil: e = buildEnv(env)
if poEchoCmd in options: echo($cmdl) if poEchoCmd in options: echo($cmdl)
when useWinUnicode: var tmp = newWideCString(cmdl)
var tmp = newWideCString(cmdl) var ee =
var ee = if e.str.isNil: newWideCString(cstring(nil))
if e.str.isNil: newWideCString(cstring(nil)) else: newWideCString(e.str, e.len)
else: newWideCString(e.str, e.len) var wwd = newWideCString(wd)
var wwd = newWideCString(wd) var flags = NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT
var flags = NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT if poDaemon in options: flags = flags or CREATE_NO_WINDOW
if poDaemon in options: flags = flags or CREATE_NO_WINDOW success = winlean.createProcessW(nil, tmp, nil, nil, 1, flags,
success = winlean.createProcessW(nil, tmp, nil, nil, 1, flags, ee, wwd, si, procInfo)
ee, wwd, si, procInfo)
else:
var ee =
if e.str.isNil: cstring(nil)
else: cstring(e.str)
success = winlean.createProcessA(nil,
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, ee, wd, si, procInfo)
let lastError = osLastError() let lastError = osLastError()
if poParentStreams notin options: if poParentStreams notin options:
@ -870,13 +863,9 @@ when defined(windows) and not defined(useNimRtl):
si.hStdError = getStdHandle(STD_ERROR_HANDLE) si.hStdError = getStdHandle(STD_ERROR_HANDLE)
si.hStdInput = getStdHandle(STD_INPUT_HANDLE) si.hStdInput = getStdHandle(STD_INPUT_HANDLE)
si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE) si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE)
when useWinUnicode: var c = newWideCString(command)
var c = newWideCString(command) var res = winlean.createProcessW(nil, c, nil, nil, 0,
var res = winlean.createProcessW(nil, c, nil, nil, 0, NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
else:
var res = winlean.createProcessA(nil, command, nil, nil, 0,
NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
if res == 0: if res == 0:
raiseOSError(osLastError()) raiseOSError(osLastError())
else: else:

View file

@ -40,10 +40,7 @@ else:
# Needed by windows in order to obtain the command line for targets # Needed by windows in order to obtain the command line for targets
# other than command line targets # other than command line targets
when defined(windows) and not weirdTarget: when defined(windows) and not weirdTarget:
when useWinUnicode: template getCommandLine*(): untyped = getCommandLineW()
template getCommandLine*(): untyped = getCommandLineW()
else:
template getCommandLine*(): untyped = getCommandLineA()
proc parseCmdLine*(c: string): seq[string] {. proc parseCmdLine*(c: string): seq[string] {.

View file

@ -47,23 +47,17 @@ else:
when defined(windows) and not weirdTarget: when defined(windows) and not weirdTarget:
when useWinUnicode: template wrapUnary*(varname, winApiProc, arg: untyped) =
template wrapUnary*(varname, winApiProc, arg: untyped) = var varname = winApiProc(newWideCString(arg))
var varname = winApiProc(newWideCString(arg))
template wrapBinary*(varname, winApiProc, arg, arg2: untyped) = template wrapBinary*(varname, winApiProc, arg, arg2: untyped) =
var varname = winApiProc(newWideCString(arg), arg2) var varname = winApiProc(newWideCString(arg), arg2)
proc findFirstFile*(a: string, b: var WIN32_FIND_DATA): Handle = proc findFirstFile*(a: string, b: var WIN32_FIND_DATA): Handle =
result = findFirstFileW(newWideCString(a), b) result = findFirstFileW(newWideCString(a), b)
template findNextFile*(a, b: untyped): untyped = findNextFileW(a, b) template findNextFile*(a, b: untyped): untyped = findNextFileW(a, b)
template getFilename*(f: untyped): untyped = template getFilename*(f: untyped): untyped =
$cast[WideCString](addr(f.cFileName[0])) $cast[WideCString](addr(f.cFileName[0]))
else:
template findFirstFile*(a, b: untyped): untyped = findFirstFileA(a, b)
template findNextFile*(a, b: untyped): untyped = findNextFileA(a, b)
template getFilename*(f: untyped): untyped = $cast[cstring](addr f.cFileName)
proc skipFindData*(f: WIN32_FIND_DATA): bool {.inline.} = proc skipFindData*(f: WIN32_FIND_DATA): bool {.inline.} =
# Note - takes advantage of null delimiter in the cstring # Note - takes advantage of null delimiter in the cstring
@ -104,12 +98,9 @@ proc tryMoveFSObject*(source, dest: string, isDir: bool): bool {.noWeirdTarget.}
## In case of other errors `OSError` is raised. ## In case of other errors `OSError` is raised.
## Returns true in case of success. ## Returns true in case of success.
when defined(windows): when defined(windows):
when useWinUnicode: let s = newWideCString(source)
let s = newWideCString(source) let d = newWideCString(dest)
let d = newWideCString(dest) result = moveFileExW(s, d, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
result = moveFileExW(s, d, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
else:
result = moveFileExA(source, dest, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
else: else:
result = c_rename(source, dest) == 0'i32 result = c_rename(source, dest) == 0'i32
@ -137,10 +128,7 @@ proc fileExists*(filename: string): bool {.rtl, extern: "nos$1",
## * `dirExists proc`_ ## * `dirExists proc`_
## * `symlinkExists proc`_ ## * `symlinkExists proc`_
when defined(windows): when defined(windows):
when useWinUnicode: wrapUnary(a, getFileAttributesW, filename)
wrapUnary(a, getFileAttributesW, filename)
else:
var a = getFileAttributesA(filename)
if a != -1'i32: if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32 result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32
else: else:
@ -157,10 +145,7 @@ proc dirExists*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect]
## * `fileExists proc`_ ## * `fileExists proc`_
## * `symlinkExists proc`_ ## * `symlinkExists proc`_
when defined(windows): when defined(windows):
when useWinUnicode: wrapUnary(a, getFileAttributesW, dir)
wrapUnary(a, getFileAttributesW, dir)
else:
var a = getFileAttributesA(dir)
if a != -1'i32: if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32 result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32
else: else:
@ -178,10 +163,7 @@ proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
## * `fileExists proc`_ ## * `fileExists proc`_
## * `dirExists proc`_ ## * `dirExists proc`_
when defined(windows): when defined(windows):
when useWinUnicode: wrapUnary(a, getFileAttributesW, link)
wrapUnary(a, getFileAttributesW, link)
else:
var a = getFileAttributesA(link)
if a != -1'i32: if a != -1'i32:
# xxx see: bug #16784 (bug9); checking `IO_REPARSE_TAG_SYMLINK` # xxx see: bug #16784 (bug9); checking `IO_REPARSE_TAG_SYMLINK`
# may also be needed. # may also be needed.
@ -197,15 +179,8 @@ when defined(windows) and not weirdTarget:
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
let access = if writeAccess: GENERIC_WRITE else: 0'i32 let access = if writeAccess: GENERIC_WRITE else: 0'i32
when useWinUnicode: result = createFileW(
result = createFileW( newWideCString(path), access,
newWideCString(path), access, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0
nil, OPEN_EXISTING, flags, 0 )
)
else:
result = createFileA(
path, access,
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, flags, 0
)

View file

@ -328,10 +328,7 @@ iterator walkDirRec*(dir: string,
proc rawRemoveDir(dir: string) {.noWeirdTarget.} = proc rawRemoveDir(dir: string) {.noWeirdTarget.} =
when defined(windows): when defined(windows):
when useWinUnicode: wrapUnary(res, removeDirectoryW, dir)
wrapUnary(res, removeDirectoryW, dir)
else:
var res = removeDirectoryA(dir)
let lastError = osLastError() let lastError = osLastError()
if res == 0'i32 and lastError.int32 != 3'i32 and if res == 0'i32 and lastError.int32 != 3'i32 and
lastError.int32 != 18'i32 and lastError.int32 != 2'i32: lastError.int32 != 18'i32 and lastError.int32 != 2'i32:
@ -396,10 +393,7 @@ proc rawCreateDir(dir: string): bool {.noWeirdTarget.} =
#echo res #echo res
raiseOSError(osLastError(), dir) raiseOSError(osLastError(), dir)
else: else:
when useWinUnicode: wrapUnary(res, createDirectoryW, dir)
wrapUnary(res, createDirectoryW, dir)
else:
let res = createDirectoryA(dir)
if res != 0'i32: if res != 0'i32:
result = true result = true
@ -561,10 +555,7 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [], noWeirdTarget.} =
## * `getTempDir proc`_ ## * `getTempDir proc`_
## * `getCurrentDir proc`_ ## * `getCurrentDir proc`_
when defined(windows): when defined(windows):
when useWinUnicode: if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32: raiseOSError(osLastError(), newDir)
raiseOSError(osLastError(), newDir)
else:
if setCurrentDirectoryA(newDir) == 0'i32: raiseOSError(osLastError(), newDir)
else: else:
if chdir(newDir) != 0'i32: raiseOSError(osLastError(), newDir) if chdir(newDir) != 0'i32: raiseOSError(osLastError(), newDir)

View file

@ -84,10 +84,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {.
if (a.st_mode and S_IWOTH.Mode) != 0.Mode: result.incl(fpOthersWrite) if (a.st_mode and S_IWOTH.Mode) != 0.Mode: result.incl(fpOthersWrite)
if (a.st_mode and S_IXOTH.Mode) != 0.Mode: result.incl(fpOthersExec) if (a.st_mode and S_IXOTH.Mode) != 0.Mode: result.incl(fpOthersExec)
else: else:
when useWinUnicode: wrapUnary(res, getFileAttributesW, filename)
wrapUnary(res, getFileAttributesW, filename)
else:
var res = getFileAttributesA(filename)
if res == -1'i32: raiseOSError(osLastError(), filename) if res == -1'i32: raiseOSError(osLastError(), filename)
if (res and FILE_ATTRIBUTE_READONLY) != 0'i32: if (res and FILE_ATTRIBUTE_READONLY) != 0'i32:
result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead,
@ -136,19 +133,13 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission],
if chmod(filename, cast[Mode](p)) != 0: if chmod(filename, cast[Mode](p)) != 0:
raiseOSError(osLastError(), $(filename, permissions)) raiseOSError(osLastError(), $(filename, permissions))
else: else:
when useWinUnicode: wrapUnary(res, getFileAttributesW, filename)
wrapUnary(res, getFileAttributesW, filename)
else:
var res = getFileAttributesA(filename)
if res == -1'i32: raiseOSError(osLastError(), filename) if res == -1'i32: raiseOSError(osLastError(), filename)
if fpUserWrite in permissions: if fpUserWrite in permissions:
res = res and not FILE_ATTRIBUTE_READONLY res = res and not FILE_ATTRIBUTE_READONLY
else: else:
res = res or FILE_ATTRIBUTE_READONLY res = res or FILE_ATTRIBUTE_READONLY
when useWinUnicode: wrapBinary(res2, setFileAttributesW, filename, res)
wrapBinary(res2, setFileAttributesW, filename, res)
else:
var res2 = setFileAttributesA(filename, res)
if res2 == - 1'i32: raiseOSError(osLastError(), $(filename, permissions)) if res2 == - 1'i32: raiseOSError(osLastError(), $(filename, permissions))
@ -221,14 +212,10 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl,
if isSymlink and (cfSymlinkIgnore in options or defined(windows)): if isSymlink and (cfSymlinkIgnore in options or defined(windows)):
return return
when defined(windows): when defined(windows):
when useWinUnicode: let s = newWideCString(source)
let s = newWideCString(source) let d = newWideCString(dest)
let d = newWideCString(dest) if copyFileW(s, d, 0'i32) == 0'i32:
if copyFileW(s, d, 0'i32) == 0'i32: raiseOSError(osLastError(), $(source, dest))
raiseOSError(osLastError(), $(source, dest))
else:
if copyFileA(source, dest, 0'i32) == 0'i32:
raiseOSError(osLastError(), $(source, dest))
else: else:
if isSymlink and cfSymlinkAsIs in options: if isSymlink and cfSymlinkAsIs in options:
createSymlink(expandSymlink(source), dest) createSymlink(expandSymlink(source), dest)
@ -334,14 +321,9 @@ when not declared(ENOENT) and not defined(windows):
var ENOENT {.importc, header: "<errno.h>".}: cint var ENOENT {.importc, header: "<errno.h>".}: cint
when defined(windows) and not weirdTarget: when defined(windows) and not weirdTarget:
when useWinUnicode: template deleteFile(file: untyped): untyped = deleteFileW(file)
template deleteFile(file: untyped): untyped = deleteFileW(file) template setFileAttributes(file, attrs: untyped): untyped =
template setFileAttributes(file, attrs: untyped): untyped = setFileAttributesW(file, attrs)
setFileAttributesW(file, attrs)
else:
template deleteFile(file: untyped): untyped = deleteFileA(file)
template setFileAttributes(file, attrs: untyped): untyped =
setFileAttributesA(file, attrs)
proc tryRemoveFile*(file: string): bool {.rtl, extern: "nos$1", tags: [WriteDirEffect], noWeirdTarget.} = proc tryRemoveFile*(file: string): bool {.rtl, extern: "nos$1", tags: [WriteDirEffect], noWeirdTarget.} =
## Removes the `file`. ## Removes the `file`.
@ -358,10 +340,7 @@ proc tryRemoveFile*(file: string): bool {.rtl, extern: "nos$1", tags: [WriteDirE
## * `moveFile proc`_ ## * `moveFile proc`_
result = true result = true
when defined(windows): when defined(windows):
when useWinUnicode: let f = newWideCString(file)
let f = newWideCString(file)
else:
let f = file
if deleteFile(f) == 0: if deleteFile(f) == 0:
result = false result = false
let err = getLastError() let err = getLastError()

View file

@ -849,30 +849,17 @@ when not defined(nimscript):
doAssert false, "use -d:nodejs to have `getCurrentDir` defined" doAssert false, "use -d:nodejs to have `getCurrentDir` defined"
elif defined(windows): elif defined(windows):
var bufsize = MAX_PATH.int32 var bufsize = MAX_PATH.int32
when useWinUnicode: var res = newWideCString("", bufsize)
var res = newWideCString("", bufsize) while true:
while true: var L = getCurrentDirectoryW(bufsize, res)
var L = getCurrentDirectoryW(bufsize, res) if L == 0'i32:
if L == 0'i32: raiseOSError(osLastError())
raiseOSError(osLastError()) elif L > bufsize:
elif L > bufsize: res = newWideCString("", L)
res = newWideCString("", L) bufsize = L
bufsize = L else:
else: result = res$L
result = res$L break
break
else:
result = newString(bufsize)
while true:
var L = getCurrentDirectoryA(bufsize, result)
if L == 0'i32:
raiseOSError(osLastError())
elif L > bufsize:
result = newString(L)
bufsize = L
else:
setLen(result, L)
break
else: else:
var bufsize = 1024 # should be enough var bufsize = 1024 # should be enough
result = newString(bufsize) result = newString(bufsize)

View file

@ -48,14 +48,10 @@ proc createSymlink*(src, dest: string) {.noWeirdTarget.} =
const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 2 const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 2
# allows anyone with developer mode on to create a link # allows anyone with developer mode on to create a link
let flag = dirExists(src).int32 or SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE let flag = dirExists(src).int32 or SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
when useWinUnicode: var wSrc = newWideCString(src)
var wSrc = newWideCString(src) var wDst = newWideCString(dest)
var wDst = newWideCString(dest) if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0: raiseOSError(osLastError(), $(src, dest))
raiseOSError(osLastError(), $(src, dest))
else:
if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
raiseOSError(osLastError(), $(src, dest))
else: else:
if symlink(src, dest) != 0: if symlink(src, dest) != 0:
raiseOSError(osLastError(), $(src, dest)) raiseOSError(osLastError(), $(src, dest))

View file

@ -390,7 +390,7 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
proc c_memchr(s: pointer, c: cint, n: csize_t): pointer {. proc c_memchr(s: pointer, c: cint, n: csize_t): pointer {.
importc: "memchr", header: "<string.h>".} importc: "memchr", header: "<string.h>".}
when defined(windows) and not defined(useWinAnsi): when defined(windows):
proc readConsole(hConsoleInput: FileHandle, lpBuffer: pointer, proc readConsole(hConsoleInput: FileHandle, lpBuffer: pointer,
nNumberOfCharsToRead: int32, nNumberOfCharsToRead: int32,
lpNumberOfCharsRead: ptr int32, lpNumberOfCharsRead: ptr int32,
@ -612,7 +612,7 @@ proc writeLine*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
# interface to the C procs: # interface to the C procs:
when defined(windows) and not defined(useWinAnsi): when defined(windows):
when defined(cpp): when defined(cpp):
proc wfopen(filename, mode: WideCString): pointer {. proc wfopen(filename, mode: WideCString): pointer {.
importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.} importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.}

View file

@ -21,13 +21,7 @@ when defined(nimPreviewSlimSystem):
from std/syncio import FileHandle from std/syncio import FileHandle
import std/widestrs import std/widestrs
const type WinChar* = Utf16Char
useWinUnicode* = not defined(useWinAnsi)
when useWinUnicode:
type WinChar* = Utf16Char
else:
type WinChar* = char
# See https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types # See https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
type type
@ -184,26 +178,14 @@ proc peekNamedPipe*(hNamedPipe: Handle, lpBuffer: pointer=nil,
lpBytesLeftThisMessage: ptr int32 = nil): bool {. lpBytesLeftThisMessage: ptr int32 = nil): bool {.
stdcall, dynlib: "kernel32", importc: "PeekNamedPipe".} stdcall, dynlib: "kernel32", importc: "PeekNamedPipe".}
when useWinUnicode: proc createProcessW*(lpApplicationName, lpCommandLine: WideCString,
proc createProcessW*(lpApplicationName, lpCommandLine: WideCString, lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
lpProcessAttributes: ptr SECURITY_ATTRIBUTES, lpThreadAttributes: ptr SECURITY_ATTRIBUTES,
lpThreadAttributes: ptr SECURITY_ATTRIBUTES, bInheritHandles: WINBOOL, dwCreationFlags: int32,
bInheritHandles: WINBOOL, dwCreationFlags: int32, lpEnvironment, lpCurrentDirectory: WideCString,
lpEnvironment, lpCurrentDirectory: WideCString, lpStartupInfo: var STARTUPINFO,
lpStartupInfo: var STARTUPINFO, lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{.
lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{. stdcall, dynlib: "kernel32", importc: "CreateProcessW", sideEffect.}
stdcall, dynlib: "kernel32", importc: "CreateProcessW", sideEffect.}
else:
proc createProcessA*(lpApplicationName, lpCommandLine: cstring,
lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
lpThreadAttributes: ptr SECURITY_ATTRIBUTES,
bInheritHandles: WINBOOL, dwCreationFlags: int32,
lpEnvironment: pointer, lpCurrentDirectory: cstring,
lpStartupInfo: var STARTUPINFO,
lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "CreateProcessA", sideEffect.}
proc suspendThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32", proc suspendThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32",
importc: "SuspendThread", sideEffect.} importc: "SuspendThread", sideEffect.}
@ -232,67 +214,37 @@ proc getLastError*(): int32 {.importc: "GetLastError",
proc setLastError*(error: int32) {.importc: "SetLastError", proc setLastError*(error: int32) {.importc: "SetLastError",
stdcall, dynlib: "kernel32", sideEffect.} stdcall, dynlib: "kernel32", sideEffect.}
when useWinUnicode: proc formatMessageW*(dwFlags: int32, lpSource: pointer,
proc formatMessageW*(dwFlags: int32, lpSource: pointer,
dwMessageId, dwLanguageId: int32,
lpBuffer: pointer, nSize: int32,
arguments: pointer): int32 {.
importc: "FormatMessageW", stdcall, dynlib: "kernel32".}
else:
proc formatMessageA*(dwFlags: int32, lpSource: pointer,
dwMessageId, dwLanguageId: int32, dwMessageId, dwLanguageId: int32,
lpBuffer: pointer, nSize: int32, lpBuffer: pointer, nSize: int32,
arguments: pointer): int32 {. arguments: pointer): int32 {.
importc: "FormatMessageA", stdcall, dynlib: "kernel32".} importc: "FormatMessageW", stdcall, dynlib: "kernel32".}
proc localFree*(p: pointer) {. proc localFree*(p: pointer) {.
importc: "LocalFree", stdcall, dynlib: "kernel32".} importc: "LocalFree", stdcall, dynlib: "kernel32".}
when useWinUnicode: proc getCurrentDirectoryW*(nBufferLength: int32,
proc getCurrentDirectoryW*(nBufferLength: int32, lpBuffer: WideCString): int32 {.
lpBuffer: WideCString): int32 {. importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.} proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {. importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.} proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {.
proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {. importc: "CreateDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
importc: "CreateDirectoryW", dynlib: "kernel32", stdcall, sideEffect.} proc removeDirectoryW*(lpPathName: WideCString): int32 {.
proc removeDirectoryW*(lpPathName: WideCString): int32 {. importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall, sideEffect.} proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {. stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW", sideEffect.}
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW", sideEffect.}
proc getModuleFileNameW*(handle: Handle, buf: WideCString, proc getModuleFileNameW*(handle: Handle, buf: WideCString,
size: int32): int32 {.importc: "GetModuleFileNameW", size: int32): int32 {.importc: "GetModuleFileNameW",
dynlib: "kernel32", stdcall.} dynlib: "kernel32", stdcall.}
else:
proc getCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
proc setCurrentDirectoryA*(lpPathName: cstring): int32 {.
importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {.
importc: "CreateDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
proc removeDirectoryA*(lpPathName: cstring): int32 {.
importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA", sideEffect.}
proc getModuleFileNameA*(handle: Handle, buf: cstring, size: int32): int32 {. proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString,
importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.} flags: DWORD): int32 {.
importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall, sideEffect.}
when useWinUnicode: proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString, security: pointer=nil): int32 {.
flags: DWORD): int32 {. importc:"CreateHardLinkW", dynlib: "kernel32", stdcall, sideEffect.}
importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall, sideEffect.}
proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
security: pointer=nil): int32 {.
importc:"CreateHardLinkW", dynlib: "kernel32", stdcall, sideEffect.}
else:
proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring,
flags: DWORD): int32 {.
importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall, sideEffect.}
proc createHardLinkA*(lpFileName, lpExistingFileName: cstring,
security: pointer=nil): int32 {.
importc:"CreateHardLinkA", dynlib: "kernel32", stdcall, sideEffect.}
const const
FILE_ATTRIBUTE_READONLY* = 0x00000001'i32 FILE_ATTRIBUTE_READONLY* = 0x00000001'i32
@ -343,84 +295,45 @@ type
cFileName*: array[0..(MAX_PATH) - 1, WinChar] cFileName*: array[0..(MAX_PATH) - 1, WinChar]
cAlternateFileName*: array[0..13, WinChar] cAlternateFileName*: array[0..13, WinChar]
when useWinUnicode: proc findFirstFileW*(lpFileName: WideCString,
proc findFirstFileW*(lpFileName: WideCString, lpFindFileData: var WIN32_FIND_DATA): Handle {.
lpFindFileData: var WIN32_FIND_DATA): Handle {. stdcall, dynlib: "kernel32", importc: "FindFirstFileW", sideEffect.}
stdcall, dynlib: "kernel32", importc: "FindFirstFileW", sideEffect.} proc findNextFileW*(hFindFile: Handle,
proc findNextFileW*(hFindFile: Handle, lpFindFileData: var WIN32_FIND_DATA): int32 {.
lpFindFileData: var WIN32_FIND_DATA): int32 {. stdcall, dynlib: "kernel32", importc: "FindNextFileW", sideEffect.}
stdcall, dynlib: "kernel32", importc: "FindNextFileW", sideEffect.}
else:
proc findFirstFileA*(lpFileName: cstring,
lpFindFileData: var WIN32_FIND_DATA): Handle {.
stdcall, dynlib: "kernel32", importc: "FindFirstFileA", sideEffect.}
proc findNextFileA*(hFindFile: Handle,
lpFindFileData: var WIN32_FIND_DATA): int32 {.
stdcall, dynlib: "kernel32", importc: "FindNextFileA", sideEffect.}
proc findClose*(hFindFile: Handle) {.stdcall, dynlib: "kernel32", proc findClose*(hFindFile: Handle) {.stdcall, dynlib: "kernel32",
importc: "FindClose".} importc: "FindClose".}
when useWinUnicode: proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32, lpBuffer: WideCString,
lpBuffer: WideCString, lpFilePart: var WideCString): int32 {.
lpFilePart: var WideCString): int32 {. stdcall, dynlib: "kernel32",
importc: "GetFullPathNameW", sideEffect.}
proc getFileAttributesW*(lpFileName: WideCString): int32 {.
stdcall, dynlib: "kernel32", stdcall, dynlib: "kernel32",
importc: "GetFullPathNameW", sideEffect.} importc: "GetFileAttributesW", sideEffect.}
proc getFileAttributesW*(lpFileName: WideCString): int32 {. proc setFileAttributesW*(lpFileName: WideCString,
stdcall, dynlib: "kernel32", dwFileAttributes: int32): WINBOOL {.
importc: "GetFileAttributesW", sideEffect.} stdcall, dynlib: "kernel32", importc: "SetFileAttributesW", sideEffect.}
proc setFileAttributesW*(lpFileName: WideCString,
dwFileAttributes: int32): WINBOOL {.
stdcall, dynlib: "kernel32", importc: "SetFileAttributesW", sideEffect.}
proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString, proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString,
bFailIfExists: WINBOOL): WINBOOL {. bFailIfExists: WINBOOL): WINBOOL {.
importc: "CopyFileW", stdcall, dynlib: "kernel32", sideEffect.} importc: "CopyFileW", stdcall, dynlib: "kernel32", sideEffect.}
proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString): WINBOOL {. proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString): WINBOOL {.
importc: "MoveFileW", stdcall, dynlib: "kernel32", sideEffect.} importc: "MoveFileW", stdcall, dynlib: "kernel32", sideEffect.}
proc moveFileExW*(lpExistingFileName, lpNewFileName: WideCString, proc moveFileExW*(lpExistingFileName, lpNewFileName: WideCString,
flags: DWORD): WINBOOL {. flags: DWORD): WINBOOL {.
importc: "MoveFileExW", stdcall, dynlib: "kernel32", sideEffect.} importc: "MoveFileExW", stdcall, dynlib: "kernel32", sideEffect.}
proc getEnvironmentStringsW*(): WideCString {. proc getEnvironmentStringsW*(): WideCString {.
stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW", sideEffect.} stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW", sideEffect.}
proc freeEnvironmentStringsW*(para1: WideCString): int32 {. proc freeEnvironmentStringsW*(para1: WideCString): int32 {.
stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW", sideEffect.} stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW", sideEffect.}
proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW", proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW",
stdcall, dynlib: "kernel32", sideEffect.} stdcall, dynlib: "kernel32", sideEffect.}
else:
proc getFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
lpBuffer: cstring, lpFilePart: var cstring): int32 {.
stdcall, dynlib: "kernel32",
importc: "GetFullPathNameA", sideEffect.}
proc getFileAttributesA*(lpFileName: cstring): int32 {.
stdcall, dynlib: "kernel32",
importc: "GetFileAttributesA", sideEffect.}
proc setFileAttributesA*(lpFileName: cstring,
dwFileAttributes: int32): WINBOOL {.
stdcall, dynlib: "kernel32", importc: "SetFileAttributesA", sideEffect.}
proc copyFileA*(lpExistingFileName, lpNewFileName: cstring,
bFailIfExists: cint): cint {.
importc: "CopyFileA", stdcall, dynlib: "kernel32", sideEffect.}
proc moveFileA*(lpExistingFileName, lpNewFileName: cstring): WINBOOL {.
importc: "MoveFileA", stdcall, dynlib: "kernel32", sideEffect.}
proc moveFileExA*(lpExistingFileName, lpNewFileName: cstring,
flags: DWORD): WINBOOL {.
importc: "MoveFileExA", stdcall, dynlib: "kernel32", sideEffect.}
proc getEnvironmentStringsA*(): cstring {.
stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsA", sideEffect.}
proc freeEnvironmentStringsA*(para1: cstring): int32 {.
stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsA", sideEffect.}
proc getCommandLineA*(): cstring {.
importc: "GetCommandLineA", stdcall, dynlib: "kernel32", sideEffect.}
proc rdFileTime*(f: FILETIME): int64 = proc rdFileTime*(f: FILETIME): int64 =
result = int64(cast[uint32](f.dwLowDateTime)) or (int64(cast[uint32](f.dwHighDateTime)) shl 32) result = int64(cast[uint32](f.dwLowDateTime)) or (int64(cast[uint32](f.dwHighDateTime)) shl 32)
@ -434,17 +347,10 @@ proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {.
proc sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32", proc sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32",
importc: "Sleep", sideEffect.} importc: "Sleep", sideEffect.}
when useWinUnicode: proc shellExecuteW*(hwnd: Handle, lpOperation, lpFile,
proc shellExecuteW*(hwnd: Handle, lpOperation, lpFile, lpParameters, lpDirectory: WideCString,
lpParameters, lpDirectory: WideCString, nShowCmd: int32): Handle{.
nShowCmd: int32): Handle{. stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW", sideEffect.}
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW", sideEffect.}
else:
proc shellExecuteA*(hwnd: Handle, lpOperation, lpFile,
lpParameters, lpDirectory: cstring,
nShowCmd: int32): Handle{.
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA", sideEffect.}
proc getFileInformationByHandle*(hFile: Handle, proc getFileInformationByHandle*(hFile: Handle,
lpFileInformation: ptr BY_HANDLE_FILE_INFORMATION): WINBOOL{. lpFileInformation: ptr BY_HANDLE_FILE_INFORMATION): WINBOOL{.
@ -794,13 +700,6 @@ proc createFileMappingW*(hFile: Handle,
lpName: pointer): Handle {. lpName: pointer): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".} stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
when not useWinUnicode:
proc createFileMappingA*(hFile: Handle,
lpFileMappingAttributes: pointer,
flProtect, dwMaximumSizeHigh: DWORD,
dwMaximumSizeLow: DWORD, lpName: cstring): Handle {.
stdcall, dynlib: "kernel32", importc: "CreateFileMappingA".}
proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall, proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
dynlib: "kernel32", importc: "UnmapViewOfFile".} dynlib: "kernel32", importc: "UnmapViewOfFile".}
@ -976,7 +875,7 @@ proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
stringBufSize: int32): cstring {.stdcall.} = stringBufSize: int32): cstring {.stdcall.} =
var ver: OSVERSIONINFO var ver: OSVERSIONINFO
ver.dwOSVersionInfoSize = sizeof(ver).DWORD ver.dwOSVersionInfoSize = sizeof(ver).DWORD
let res = when useWinUnicode: getVersionExW(ver.addr) else: getVersionExA(ver.addr) let res = getVersionExW(ver.addr)
if res == 0: if res == 0:
result = nil result = nil
elif ver.dwMajorVersion >= 6: elif ver.dwMajorVersion >= 6:
@ -1060,16 +959,10 @@ proc openProcess*(dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
dwProcessId: DWORD): Handle dwProcessId: DWORD): Handle
{.stdcall, dynlib: "kernel32", importc: "OpenProcess".} {.stdcall, dynlib: "kernel32", importc: "OpenProcess".}
when defined(useWinAnsi): proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES,
proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES, bManualReset: DWORD, bInitialState: DWORD,
bManualReset: DWORD, bInitialState: DWORD, lpName: ptr Utf16Char): Handle
lpName: cstring): Handle {.stdcall, dynlib: "kernel32", importc: "CreateEventW".}
{.stdcall, dynlib: "kernel32", importc: "CreateEventA".}
else:
proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES,
bManualReset: DWORD, bInitialState: DWORD,
lpName: ptr Utf16Char): Handle
{.stdcall, dynlib: "kernel32", importc: "CreateEventW".}
proc setEvent*(hEvent: Handle): cint proc setEvent*(hEvent: Handle): cint
{.stdcall, dynlib: "kernel32", importc: "SetEvent".} {.stdcall, dynlib: "kernel32", importc: "SetEvent".}
@ -1110,14 +1003,9 @@ type
uChar*: int16 uChar*: int16
dwControlKeyState*: DWORD dwControlKeyState*: DWORD
when defined(useWinAnsi): proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint, lpNumberOfEventsRead: ptr cint): cint
lpNumberOfEventsRead: ptr cint): cint {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
{.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputA".}
else:
proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
lpNumberOfEventsRead: ptr cint): cint
{.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
type type
LPFIBER_START_ROUTINE* = proc (param: pointer) {.stdcall.} LPFIBER_START_ROUTINE* = proc (param: pointer) {.stdcall.}