2016-03-01 22:57:46 +00:00
// Copyright 2009 The Go Authors. All rights reserved.
2010-03-09 15:09:09 -08:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Windows system calls.
package syscall
2010-03-16 23:10:07 -07:00
import (
2013-01-11 12:42:09 +11:00
errorspkg "errors"
2024-02-25 21:21:31 +00:00
"internal/asan"
2022-03-17 11:41:24 +01:00
"internal/bytealg"
2021-03-13 16:52:16 -08:00
"internal/itoa"
2024-02-25 21:21:31 +00:00
"internal/msan"
2019-02-19 13:03:55 -08:00
"internal/oserror"
2015-09-23 10:03:54 +02:00
"internal/race"
2018-08-08 15:00:56 -07:00
"runtime"
2013-01-11 12:42:09 +11:00
"sync"
2010-03-16 23:10:07 -07:00
"unsafe"
)
2010-03-09 15:09:09 -08:00
2011-07-01 10:18:07 -04:00
type Handle uintptr
const InvalidHandle = ^ Handle ( 0 )
2015-05-18 15:50:00 -04:00
// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s,
// with a terminating NUL added. If s contains a NUL byte this
// function panics instead of returning an error.
//
2023-11-04 15:21:26 +08:00
// Deprecated: Use [UTF16FromString] instead.
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
func StringToUTF16 ( s string ) [ ] uint16 {
a , err := UTF16FromString ( s )
if err != nil {
panic ( "syscall: string with NUL passed to StringToUTF16" )
}
return a
}
// UTF16FromString returns the UTF-16 encoding of the UTF-8 string
// s, with a terminating NUL added. If s contains a NUL byte at any
2023-11-04 15:21:26 +08:00
// location, it returns (nil, [EINVAL]). Unpaired surrogates
2023-05-05 18:17:18 +02:00
// are encoded using WTF-8.
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
func UTF16FromString ( s string ) ( [ ] uint16 , error ) {
2022-03-17 11:41:24 +01:00
if bytealg . IndexByteString ( s , 0 ) != - 1 {
return nil , EINVAL
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
}
2023-05-04 11:25:29 +01:00
// Valid UTF-8 characters between 1 and 3 bytes require one uint16.
// Valid UTF-8 characters of 4 bytes require two uint16.
// Bytes with invalid UTF-8 encoding require maximum one uint16 per byte.
// So the number of UTF-8 code units (len(s)) is always greater or
// equal than the number of UTF-16 code units.
// Also account for the terminating NUL character.
buf := make ( [ ] uint16 , 0 , len ( s ) + 1 )
2023-05-05 18:17:18 +02:00
buf = encodeWTF16 ( s , buf )
return append ( buf , 0 ) , nil
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
}
2010-03-09 15:09:09 -08:00
2010-03-16 23:10:07 -07:00
// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
2023-05-05 18:17:18 +02:00
// with a terminating NUL removed. Unpaired surrogates are decoded
// using WTF-8 instead of UTF-8 encoding.
2010-03-16 23:10:07 -07:00
func UTF16ToString ( s [ ] uint16 ) string {
2023-05-05 18:17:18 +02:00
maxLen := 0
2010-04-13 16:30:11 -07:00
for i , v := range s {
if v == 0 {
s = s [ 0 : i ]
break
}
2023-05-05 18:17:18 +02:00
switch {
case v <= rune1Max :
maxLen += 1
case v <= rune2Max :
maxLen += 2
default :
// r is a non-surrogate that decodes to 3 bytes,
// or is an unpaired surrogate (also 3 bytes in WTF-8),
// or is one half of a valid surrogate pair.
// If it is half of a pair, we will add 3 for the second surrogate
// (total of 6) and overestimate by 2 bytes for the pair,
// since the resulting rune only requires 4 bytes.
maxLen += 3
}
2010-03-09 15:09:09 -08:00
}
2023-05-05 18:17:18 +02:00
buf := decodeWTF16 ( s , make ( [ ] byte , 0 , maxLen ) )
return unsafe . String ( unsafe . SliceData ( buf ) , len ( buf ) )
2010-03-09 15:09:09 -08:00
}
2019-11-09 19:06:24 +11:00
// utf16PtrToString is like UTF16ToString, but takes *uint16
// as a parameter instead of []uint16.
2020-04-19 17:08:58 +10:00
func utf16PtrToString ( p * uint16 ) string {
2019-11-09 19:06:24 +11:00
if p == nil {
return ""
}
end := unsafe . Pointer ( p )
n := 0
2020-04-19 17:08:58 +10:00
for * ( * uint16 ) ( end ) != 0 {
2019-11-09 19:06:24 +11:00
end = unsafe . Pointer ( uintptr ( end ) + unsafe . Sizeof ( * p ) )
n ++
}
2023-05-05 18:17:18 +02:00
return UTF16ToString ( unsafe . Slice ( p , n ) )
2019-11-09 19:06:24 +11:00
}
2015-05-18 15:50:00 -04:00
// StringToUTF16Ptr returns pointer to the UTF-16 encoding of
// the UTF-8 string s, with a terminating NUL added. If s
2017-04-27 23:53:58 -05:00
// contains a NUL byte this function panics instead of
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
// returning an error.
2015-05-18 15:50:00 -04:00
//
2023-11-04 15:21:26 +08:00
// Deprecated: Use [UTF16PtrFromString] instead.
2010-03-16 23:10:07 -07:00
func StringToUTF16Ptr ( s string ) * uint16 { return & StringToUTF16 ( s ) [ 0 ] }
2010-03-09 15:09:09 -08:00
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
// UTF16PtrFromString returns pointer to the UTF-16 encoding of
// the UTF-8 string s, with a terminating NUL added. If s
// contains a NUL byte at any location, it returns (nil, EINVAL).
2023-05-05 18:17:18 +02:00
// Unpaired surrogates are encoded using WTF-8.
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
func UTF16PtrFromString ( s string ) ( * uint16 , error ) {
a , err := UTF16FromString ( s )
if err != nil {
return nil , err
}
return & a [ 0 ] , nil
}
2011-12-08 12:07:21 +11:00
// Errno is the Windows error number.
2019-08-22 12:40:52 -04:00
//
2023-11-04 15:21:26 +08:00
// Errno values can be tested against error values using [errors.Is].
2023-03-16 10:59:04 +01:00
// For example:
2019-08-22 12:40:52 -04:00
//
// _, _, err := syscall.Syscall(...)
2020-07-07 13:49:21 -04:00
// if errors.Is(err, fs.ErrNotExist) ...
2011-12-08 12:07:21 +11:00
type Errno uintptr
2012-02-20 09:51:25 +11:00
func langid ( pri , sub uint16 ) uint32 { return uint32 ( sub ) << 10 | uint32 ( pri ) }
2015-07-13 10:55:49 +10:00
// FormatMessage is deprecated (msgsrc should be uintptr, not uint32, but can
// not be changed due to the Go 1 compatibility guarantee).
//
// Deprecated: Use FormatMessage from golang.org/x/sys/windows instead.
func FormatMessage ( flags uint32 , msgsrc uint32 , msgid uint32 , langid uint32 , buf [ ] uint16 , args * byte ) ( n uint32 , err error ) {
return formatMessage ( flags , uintptr ( msgsrc ) , msgid , langid , buf , args )
}
2011-12-08 12:07:21 +11:00
func ( e Errno ) Error ( ) string {
// deal with special go errors
idx := int ( e - APPLICATION_ERROR )
if 0 <= idx && idx < len ( errors ) {
return errors [ idx ]
}
// ask windows for the remaining errors
var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
b := make ( [ ] uint16 , 300 )
2015-07-13 10:55:49 +10:00
n , err := formatMessage ( flags , 0 , uint32 ( e ) , langid ( LANG_ENGLISH , SUBLANG_ENGLISH_US ) , b , nil )
2011-12-08 12:07:21 +11:00
if err != nil {
2015-07-13 10:55:49 +10:00
n , err = formatMessage ( flags , 0 , uint32 ( e ) , 0 , b , nil )
2012-09-18 13:02:37 +10:00
if err != nil {
2021-03-13 16:52:16 -08:00
return "winapi error #" + itoa . Itoa ( int ( e ) )
2012-09-18 13:02:37 +10:00
}
2011-12-08 12:07:21 +11:00
}
// trim terminating \r and \n
for ; n > 0 && ( b [ n - 1 ] == '\n' || b [ n - 1 ] == '\r' ) ; n -- {
}
2023-05-05 18:17:18 +02:00
return UTF16ToString ( b [ : n ] )
2011-12-08 12:07:21 +11:00
}
2023-03-16 19:23:34 +01:00
const (
2023-03-29 10:28:33 +02:00
_ERROR_NOT_ENOUGH_MEMORY = Errno ( 8 )
2023-03-16 19:23:34 +01:00
_ERROR_NOT_SUPPORTED = Errno ( 50 )
_ERROR_BAD_NETPATH = Errno ( 53 )
_ERROR_CALL_NOT_IMPLEMENTED = Errno ( 120 )
)
2019-02-19 13:03:55 -08:00
func ( e Errno ) Is ( target error ) bool {
switch target {
case oserror . ErrPermission :
2023-03-16 10:59:04 +01:00
return e == ERROR_ACCESS_DENIED ||
e == EACCES ||
e == EPERM
2019-02-19 13:03:55 -08:00
case oserror . ErrExist :
return e == ERROR_ALREADY_EXISTS ||
e == ERROR_DIR_NOT_EMPTY ||
2023-03-16 10:59:04 +01:00
e == ERROR_FILE_EXISTS ||
e == EEXIST ||
e == ENOTEMPTY
2019-02-19 13:03:55 -08:00
case oserror . ErrNotExist :
return e == ERROR_FILE_NOT_FOUND ||
e == _ERROR_BAD_NETPATH ||
2023-03-16 10:59:04 +01:00
e == ERROR_PATH_NOT_FOUND ||
e == ENOENT
2023-03-15 19:26:33 +01:00
case errorspkg . ErrUnsupported :
2023-03-16 19:23:34 +01:00
return e == _ERROR_NOT_SUPPORTED ||
e == _ERROR_CALL_NOT_IMPLEMENTED ||
e == ENOSYS ||
2023-03-16 10:59:04 +01:00
e == ENOTSUP ||
e == EOPNOTSUPP ||
e == EWINDOWS
2019-02-19 13:03:55 -08:00
}
return false
}
2011-12-08 12:07:21 +11:00
func ( e Errno ) Temporary ( ) bool {
2018-04-30 20:23:37 -07:00
return e == EINTR || e == EMFILE || e . Timeout ( )
2011-12-08 12:07:21 +11:00
}
func ( e Errno ) Timeout ( ) bool {
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
}
2015-06-14 19:48:45 -07:00
// Implemented in runtime/syscall_windows.go.
2021-12-01 12:15:45 -05:00
func compileCallback ( fn any , cleanstack bool ) uintptr
2014-08-25 15:59:13 +10:00
2018-07-27 15:52:36 +00:00
// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
// This is useful when interoperating with Windows code requiring callbacks.
2018-10-06 06:10:25 +00:00
// The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
2021-05-19 15:46:44 +00:00
// Only a limited number of callbacks may be created in a single Go process, and any memory allocated
// for these callbacks is never released.
// Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created.
2021-12-01 12:15:45 -05:00
func NewCallback ( fn any ) uintptr {
2014-08-25 15:59:13 +10:00
return compileCallback ( fn , true )
}
2018-07-27 15:52:36 +00:00
// NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention.
// This is useful when interoperating with Windows code requiring callbacks.
2018-10-06 06:10:25 +00:00
// The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
2021-05-19 15:46:44 +00:00
// Only a limited number of callbacks may be created in a single Go process, and any memory allocated
// for these callbacks is never released.
// Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created.
2021-12-01 12:15:45 -05:00
func NewCallbackCDecl ( fn any ) uintptr {
2014-08-25 15:59:13 +10:00
return compileCallback ( fn , false )
}
2011-01-22 13:55:53 +11:00
2010-03-16 23:10:07 -07:00
// windows api calls
2011-12-08 12:07:21 +11:00
//sys GetLastError() (lasterr error)
2011-11-13 22:44:52 -05:00
//sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW
//sys FreeLibrary(handle Handle) (err error)
//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error)
//sys GetVersion() (ver uint32, err error)
2015-07-13 10:55:49 +10:00
//sys formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
2010-04-02 01:11:17 -07:00
//sys ExitProcess(exitcode uint32)
2011-11-13 22:44:52 -05:00
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
2022-03-14 17:39:35 -07:00
//sys readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = ReadFile
//sys writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = WriteFile
2011-11-13 22:44:52 -05:00
//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
//sys CloseHandle(handle Handle) (err error)
//sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle]
2012-06-08 13:54:48 -04:00
//sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW
//sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW
2011-11-13 22:44:52 -05:00
//sys FindClose(handle Handle) (err error)
//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error)
//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW
//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW
//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW
//sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW
//sys DeleteFile(path *uint16) (err error) = DeleteFileW
//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
//sys SetEndOfFile(handle Handle) (err error)
2010-04-26 23:17:14 -07:00
//sys GetSystemTimeAsFileTime(time *Filetime)
2011-11-13 22:44:52 -05:00
//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
2021-02-24 22:59:59 +01:00
//sys createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) = CreateIoCompletionPort
//sys getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) = GetQueuedCompletionStatus
//sys postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) = PostQueuedCompletionStatus
2011-11-13 22:44:52 -05:00
//sys CancelIo(s Handle) (err error)
net: fix connection resets when closed on windows
It is common to close network connection while another goroutine is
blocked reading on another goroutine. This sequence corresponds to
windows calls to WSARecv to start io, followed by GetQueuedCompletionStatus
that blocks until io completes, and, finally, closesocket called from
another thread. We were expecting that closesocket would unblock
GetQueuedCompletionStatus, and it does, but not always
(http://code.google.com/p/go/issues/detail?id=4170#c5). Also that sequence
results in connection is being reset.
This CL inserts CancelIo between GetQueuedCompletionStatus and closesocket,
and waits for both WSARecv and GetQueuedCompletionStatus to complete before
proceeding to closesocket. This seems to fix both connection resets and
issue 4170. It also makes windows code behave similar to unix version.
Unfortunately, CancelIo needs to be called on the same thread as WSARecv.
So we have to employ strategy we use for connections with deadlines to
every connection now. It means, there are 2 unavoidable thread switches
for every io. Some newer versions of windows have new CancelIoEx api that
doesn't have these drawbacks, and this CL uses this capability when available.
As time goes by, we should have less of CancelIo and more of CancelIoEx
systems. Computers with CancelIoEx are also not affected by issue 4195 anymore.
Fixes #3710
Fixes #3746
Fixes #4170
Partial fix for issue 4195
R=golang-dev, mikioh.mikioh, bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6604072
2012-10-31 10:24:37 +11:00
//sys CancelIoEx(s Handle, o *Overlapped) (err error)
2011-11-13 22:44:52 -05:00
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
2017-11-07 12:09:59 +11:00
//sys CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = advapi32.CreateProcessAsUserW
2011-11-13 22:44:52 -05:00
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
//sys TerminateProcess(handle Handle, exitcode uint32) (err error)
//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
2023-08-17 00:03:13 +02:00
//sys getStartupInfo(startupInfo *StartupInfo) = GetStartupInfoW
2011-11-13 22:44:52 -05:00
//sys GetCurrentProcess() (pseudoHandle Handle, err error)
2012-03-02 14:47:40 +11:00
//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
2011-11-13 22:44:52 -05:00
//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW
//sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error)
//sys GetFileType(filehandle Handle) (n uint32, err error)
//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW
//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext
//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom
//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW
//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW
//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW
//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
2010-12-16 12:18:18 +11:00
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
2011-11-13 22:44:52 -05:00
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
//sys FlushFileBuffers(handle Handle) (err error)
//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW
2012-03-08 10:00:25 +11:00
//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW
2012-03-27 15:53:08 +11:00
//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW
2011-11-13 22:44:52 -05:00
//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW
//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error)
//sys UnmapViewOfFile(addr uintptr) (err error)
//sys FlushViewOfFile(addr uintptr, length uintptr) (err error)
//sys VirtualLock(addr uintptr, length uintptr) (err error)
//sys VirtualUnlock(addr uintptr, length uintptr) (err error)
//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
2020-11-29 13:33:37 +01:00
//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore
2011-12-01 12:38:00 -05:00
//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
2012-03-07 13:12:35 -05:00
//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
2011-11-13 22:44:52 -05:00
//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
2012-03-07 13:12:35 -05:00
//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain
//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain
//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext
//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext
//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy
2011-12-08 12:07:21 +11:00
//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
2021-11-03 18:18:18 +00:00
//sys regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
2011-12-08 12:07:21 +11:00
//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
2012-06-08 14:28:29 -04:00
//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
2012-09-12 12:04:45 +10:00
//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
2013-02-26 14:18:48 +11:00
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
2014-06-14 15:51:00 +10:00
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
2014-07-17 17:02:46 +10:00
//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error)
2024-10-09 10:12:57 +02:00
//sys setFileInformationByHandle(handle Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
2014-07-17 17:02:46 +10:00
// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW
//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW
2021-01-31 17:37:20 +01:00
//sys initializeProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList
//sys deleteProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST) = DeleteProcThreadAttributeList
2021-02-28 12:18:18 +01:00
//sys updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute
2023-03-29 10:28:33 +02:00
//sys getFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) [n == 0 || n >= filePathSize] = kernel32.GetFinalPathNameByHandleW
2010-04-02 01:11:17 -07:00
// syscall interface implementation for other packages
2010-03-16 23:10:07 -07:00
2011-02-03 12:50:41 +11:00
func makeInheritSa ( ) * SecurityAttributes {
var sa SecurityAttributes
sa . Length = uint32 ( unsafe . Sizeof ( sa ) )
sa . InheritHandle = 1
return & sa
}
2024-10-10 11:09:13 +02:00
func Open ( name string , flag int , perm uint32 ) ( fd Handle , err error ) {
if len ( name ) == 0 {
2011-07-01 10:18:07 -04:00
return InvalidHandle , ERROR_FILE_NOT_FOUND
2010-04-02 01:11:17 -07:00
}
2024-10-10 11:09:13 +02:00
namep , err := UTF16PtrFromString ( name )
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
if err != nil {
return InvalidHandle , err
}
2010-04-13 22:30:41 -07:00
var access uint32
2024-10-10 11:09:13 +02:00
switch flag & ( O_RDONLY | O_WRONLY | O_RDWR ) {
2010-04-13 22:30:41 -07:00
case O_RDONLY :
2010-04-02 01:11:17 -07:00
access = GENERIC_READ
2010-04-13 22:30:41 -07:00
case O_WRONLY :
2010-04-02 01:11:17 -07:00
access = GENERIC_WRITE
2010-04-13 22:30:41 -07:00
case O_RDWR :
2010-04-02 01:11:17 -07:00
access = GENERIC_READ | GENERIC_WRITE
}
2024-10-10 11:09:13 +02:00
if flag & O_CREAT != 0 {
2010-04-13 22:30:41 -07:00
access |= GENERIC_WRITE
}
2024-10-10 11:09:13 +02:00
if flag & O_APPEND != 0 {
2010-09-22 13:12:25 +10:00
access &^= GENERIC_WRITE
access |= FILE_APPEND_DATA
}
2010-04-13 22:30:41 -07:00
sharemode := uint32 ( FILE_SHARE_READ | FILE_SHARE_WRITE )
2011-02-03 12:50:41 +11:00
var sa * SecurityAttributes
2024-10-10 11:09:13 +02:00
if flag & O_CLOEXEC == 0 {
2011-02-03 12:50:41 +11:00
sa = makeInheritSa ( )
}
2024-10-09 10:48:07 +02:00
// We don't use CREATE_ALWAYS, because when opening a file with
// FILE_ATTRIBUTE_READONLY these will replace an existing file
// with a new, read-only one. See https://go.dev/issue/38225.
//
// Instead, we ftruncate the file after opening when O_TRUNC is set.
2010-04-02 01:11:17 -07:00
var createmode uint32
switch {
2024-10-10 11:09:13 +02:00
case flag & ( O_CREAT | O_EXCL ) == ( O_CREAT | O_EXCL ) :
2011-05-27 17:02:24 +10:00
createmode = CREATE_NEW
2024-10-10 11:09:13 +02:00
case flag & O_CREAT == O_CREAT :
2011-05-27 17:02:24 +10:00
createmode = OPEN_ALWAYS
2010-04-02 01:11:17 -07:00
default :
createmode = OPEN_EXISTING
}
2019-10-21 16:12:22 +02:00
var attrs uint32 = FILE_ATTRIBUTE_NORMAL
if perm & S_IWRITE == 0 {
attrs = FILE_ATTRIBUTE_READONLY
}
2022-05-10 09:52:20 +02:00
if createmode == OPEN_EXISTING && access == GENERIC_READ {
// Necessary for opening directory handles.
attrs |= FILE_FLAG_BACKUP_SEMANTICS
}
2024-10-10 11:09:13 +02:00
if flag & O_SYNC != 0 {
2023-11-15 13:08:23 +00:00
const _FILE_FLAG_WRITE_THROUGH = 0x80000000
attrs |= _FILE_FLAG_WRITE_THROUGH
}
2024-10-10 11:09:13 +02:00
h , err := CreateFile ( namep , access , sharemode , sa , createmode , attrs , 0 )
2024-10-09 10:48:07 +02:00
if err != nil {
2024-10-10 11:09:13 +02:00
if err == ERROR_ACCESS_DENIED && ( flag & O_WRONLY != 0 || flag & O_RDWR != 0 ) {
2024-10-10 11:01:16 +02:00
// We should return EISDIR when we are trying to open a directory with write access.
2024-10-10 11:09:13 +02:00
fa , e1 := GetFileAttributes ( namep )
2024-10-10 11:01:16 +02:00
if e1 == nil && fa & FILE_ATTRIBUTE_DIRECTORY != 0 {
err = EISDIR
}
}
2024-10-09 10:48:07 +02:00
return InvalidHandle , err
}
2024-10-10 11:09:13 +02:00
if flag & O_TRUNC == O_TRUNC {
2024-10-09 10:48:07 +02:00
err = Ftruncate ( h , 0 )
if err != nil {
CloseHandle ( h )
return InvalidHandle , err
}
}
return h , nil
2010-04-02 01:11:17 -07:00
}
2011-11-13 22:44:52 -05:00
func Read ( fd Handle , p [ ] byte ) ( n int , err error ) {
2010-04-02 01:11:17 -07:00
var done uint32
2011-07-01 10:18:07 -04:00
e := ReadFile ( fd , p , & done , nil )
2011-11-13 22:44:52 -05:00
if e != nil {
2010-04-30 12:46:46 -07:00
if e == ERROR_BROKEN_PIPE {
2010-08-25 01:26:35 -04:00
// NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin
2011-11-13 22:44:52 -05:00
return 0 , nil
2010-04-30 12:46:46 -07:00
}
2010-04-02 01:11:17 -07:00
return 0 , e
}
2022-03-14 17:39:35 -07:00
return int ( done ) , nil
}
func Write ( fd Handle , p [ ] byte ) ( n int , err error ) {
var done uint32
e := WriteFile ( fd , p , & done , nil )
if e != nil {
return 0 , e
}
return int ( done ) , nil
}
func ReadFile ( fd Handle , p [ ] byte , done * uint32 , overlapped * Overlapped ) error {
err := readFile ( fd , p , done , overlapped )
2015-09-23 10:03:54 +02:00
if race . Enabled {
2022-03-14 17:39:35 -07:00
if * done > 0 {
race . WriteRange ( unsafe . Pointer ( & p [ 0 ] ) , int ( * done ) )
2013-06-10 22:40:35 +04:00
}
2015-09-23 10:03:54 +02:00
race . Acquire ( unsafe . Pointer ( & ioSync ) )
2012-10-09 20:51:58 +04:00
}
2024-02-25 21:21:31 +00:00
if msan . Enabled && * done > 0 {
msan . Write ( unsafe . Pointer ( & p [ 0 ] ) , uintptr ( * done ) )
2015-10-21 11:04:42 -07:00
}
2024-02-25 21:21:31 +00:00
if asan . Enabled && * done > 0 {
2024-03-19 11:23:59 +01:00
asan . Write ( unsafe . Pointer ( & p [ 0 ] ) , uintptr ( * done ) )
2021-01-05 17:52:43 +08:00
}
2022-03-14 17:39:35 -07:00
return err
2010-04-02 01:11:17 -07:00
}
2022-03-14 17:39:35 -07:00
func WriteFile ( fd Handle , p [ ] byte , done * uint32 , overlapped * Overlapped ) error {
2015-09-23 10:03:54 +02:00
if race . Enabled {
race . ReleaseMerge ( unsafe . Pointer ( & ioSync ) )
2012-10-09 20:51:58 +04:00
}
2022-03-14 17:39:35 -07:00
err := writeFile ( fd , p , done , overlapped )
if race . Enabled && * done > 0 {
race . ReadRange ( unsafe . Pointer ( & p [ 0 ] ) , int ( * done ) )
2013-06-10 22:40:35 +04:00
}
2024-02-25 21:21:31 +00:00
if msan . Enabled && * done > 0 {
msan . Read ( unsafe . Pointer ( & p [ 0 ] ) , uintptr ( * done ) )
2015-10-21 11:04:42 -07:00
}
2024-02-25 21:21:31 +00:00
if asan . Enabled && * done > 0 {
2024-03-19 11:23:59 +01:00
asan . Read ( unsafe . Pointer ( & p [ 0 ] ) , uintptr ( * done ) )
2021-01-05 17:52:43 +08:00
}
2022-03-14 17:39:35 -07:00
return err
2010-04-02 01:11:17 -07:00
}
2012-10-09 20:51:58 +04:00
var ioSync int64
2017-12-06 18:20:26 +00:00
var procSetFilePointerEx = modkernel32 . NewProc ( "SetFilePointerEx" )
const ptrSize = unsafe . Sizeof ( uintptr ( 0 ) )
// setFilePointerEx calls SetFilePointerEx.
2023-09-12 14:48:12 +02:00
// See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointerex
2017-12-06 18:20:26 +00:00
func setFilePointerEx ( handle Handle , distToMove int64 , newFilePointer * int64 , whence uint32 ) error {
var e1 Errno
2021-01-27 11:39:48 -05:00
if unsafe . Sizeof ( uintptr ( 0 ) ) == 8 {
2017-12-06 18:20:26 +00:00
_ , _ , e1 = Syscall6 ( procSetFilePointerEx . Addr ( ) , 4 , uintptr ( handle ) , uintptr ( distToMove ) , uintptr ( unsafe . Pointer ( newFilePointer ) ) , uintptr ( whence ) , 0 , 0 )
2021-01-27 11:39:48 -05:00
} else {
// Different 32-bit systems disgaree about whether distToMove starts 8-byte aligned.
switch runtime . GOARCH {
default :
panic ( "unsupported 32-bit architecture" )
case "386" :
2022-05-09 15:33:22 -07:00
// distToMove is a LARGE_INTEGER, which is 64 bits.
2021-01-27 11:39:48 -05:00
_ , _ , e1 = Syscall6 ( procSetFilePointerEx . Addr ( ) , 5 , uintptr ( handle ) , uintptr ( distToMove ) , uintptr ( distToMove >> 32 ) , uintptr ( unsafe . Pointer ( newFilePointer ) ) , uintptr ( whence ) , 0 )
case "arm" :
// distToMove must be 8-byte aligned per ARM calling convention
2022-05-09 15:33:22 -07:00
// https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions#stage-c-assignment-of-arguments-to-registers-and-stack
2021-01-27 11:39:48 -05:00
_ , _ , e1 = Syscall6 ( procSetFilePointerEx . Addr ( ) , 6 , uintptr ( handle ) , 0 , uintptr ( distToMove ) , uintptr ( distToMove >> 32 ) , uintptr ( unsafe . Pointer ( newFilePointer ) ) , uintptr ( whence ) )
}
2017-12-06 18:20:26 +00:00
}
if e1 != 0 {
return errnoErr ( e1 )
}
return nil
}
2011-11-13 22:44:52 -05:00
func Seek ( fd Handle , offset int64 , whence int ) ( newoffset int64 , err error ) {
2010-04-02 01:11:17 -07:00
var w uint32
switch whence {
case 0 :
w = FILE_BEGIN
case 1 :
w = FILE_CURRENT
case 2 :
w = FILE_END
}
2017-12-06 18:20:26 +00:00
err = setFilePointerEx ( fd , offset , & newoffset , w )
return
2010-04-02 01:11:17 -07:00
}
2011-11-13 22:44:52 -05:00
func Close ( fd Handle ) ( err error ) {
2011-07-01 10:18:07 -04:00
return CloseHandle ( fd )
2010-04-02 01:11:17 -07:00
}
var (
Stdin = getStdHandle ( STD_INPUT_HANDLE )
Stdout = getStdHandle ( STD_OUTPUT_HANDLE )
Stderr = getStdHandle ( STD_ERROR_HANDLE )
)
2011-07-01 10:18:07 -04:00
func getStdHandle ( h int ) ( fd Handle ) {
2010-04-02 01:11:17 -07:00
r , _ := GetStdHandle ( h )
2011-07-01 10:18:07 -04:00
return r
2010-04-02 01:11:17 -07:00
}
2010-04-26 23:17:14 -07:00
const ImplementsGetwd = true
2011-11-13 22:44:52 -05:00
func Getwd ( ) ( wd string , err error ) {
2010-04-26 23:17:14 -07:00
b := make ( [ ] uint16 , 300 )
2023-06-11 23:29:26 +01:00
// The path of the current directory may not fit in the initial 300-word
// buffer when long path support is enabled. The current directory may also
// change between subsequent calls of GetCurrentDirectory. As a result, we
// need to retry the call in a loop until the current directory fits, each
// time with a bigger buffer.
for {
n , e := GetCurrentDirectory ( uint32 ( len ( b ) ) , & b [ 0 ] )
if e != nil {
return "" , e
}
if int ( n ) <= len ( b ) {
return UTF16ToString ( b [ : n ] ) , nil
}
b = make ( [ ] uint16 , n )
2010-04-26 23:17:14 -07:00
}
}
2011-11-13 22:44:52 -05:00
func Chdir ( path string ) ( err error ) {
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
pathp , err := UTF16PtrFromString ( path )
if err != nil {
return err
}
return SetCurrentDirectory ( pathp )
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Mkdir ( path string , mode uint32 ) ( err error ) {
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
pathp , err := UTF16PtrFromString ( path )
if err != nil {
return err
}
return CreateDirectory ( pathp , nil )
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Rmdir ( path string ) ( err error ) {
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
pathp , err := UTF16PtrFromString ( path )
if err != nil {
return err
}
return RemoveDirectory ( pathp )
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Unlink ( path string ) ( err error ) {
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
pathp , err := UTF16PtrFromString ( path )
if err != nil {
return err
}
return DeleteFile ( pathp )
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Rename ( oldpath , newpath string ) ( err error ) {
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
from , err := UTF16PtrFromString ( oldpath )
if err != nil {
return err
}
to , err := UTF16PtrFromString ( newpath )
if err != nil {
return err
}
2011-02-11 10:15:51 +11:00
return MoveFile ( from , to )
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func ComputerName ( ) ( name string , err error ) {
2023-05-29 11:45:14 +02:00
var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
b := make ( [ ] uint16 , n )
2011-02-11 10:15:51 +11:00
e := GetComputerName ( & b [ 0 ] , & n )
2011-11-13 22:44:52 -05:00
if e != nil {
2010-04-26 23:17:14 -07:00
return "" , e
}
2023-05-05 18:17:18 +02:00
return UTF16ToString ( b [ : n ] ) , nil
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Ftruncate ( fd Handle , length int64 ) ( err error ) {
2024-10-09 10:12:57 +02:00
type _FILE_END_OF_FILE_INFO struct {
EndOfFile int64
2010-04-26 23:17:14 -07:00
}
2024-10-09 10:12:57 +02:00
const FileEndOfFileInfo = 6
var info _FILE_END_OF_FILE_INFO
info . EndOfFile = length
return setFileInformationByHandle ( fd , FileEndOfFileInfo , unsafe . Pointer ( & info ) , uint32 ( unsafe . Sizeof ( info ) ) )
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Gettimeofday ( tv * Timeval ) ( err error ) {
2010-04-26 23:17:14 -07:00
var ft Filetime
GetSystemTimeAsFileTime ( & ft )
2010-09-23 12:36:52 +10:00
* tv = NsecToTimeval ( ft . Nanoseconds ( ) )
2011-11-13 22:44:52 -05:00
return nil
2010-04-26 23:17:14 -07:00
}
2011-11-13 22:44:52 -05:00
func Pipe ( p [ ] Handle ) ( err error ) {
2010-07-26 15:55:01 +10:00
if len ( p ) != 2 {
return EINVAL
}
2011-07-01 10:18:07 -04:00
var r , w Handle
2011-02-11 10:15:51 +11:00
e := CreatePipe ( & r , & w , makeInheritSa ( ) , 0 )
2011-11-13 22:44:52 -05:00
if e != nil {
2011-02-11 10:15:51 +11:00
return e
2010-07-26 15:55:01 +10:00
}
2011-07-01 10:18:07 -04:00
p [ 0 ] = r
p [ 1 ] = w
2011-11-13 22:44:52 -05:00
return nil
2010-07-26 15:55:01 +10:00
}
2011-11-13 22:44:52 -05:00
func Utimes ( path string , tv [ ] Timeval ) ( err error ) {
2010-09-23 12:36:52 +10:00
if len ( tv ) != 2 {
return EINVAL
}
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
pathp , e := UTF16PtrFromString ( path )
if e != nil {
return e
}
h , e := CreateFile ( pathp ,
2010-09-23 12:36:52 +10:00
FILE_WRITE_ATTRIBUTES , FILE_SHARE_WRITE , nil ,
2014-10-06 19:22:48 -04:00
OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 )
2011-11-13 22:44:52 -05:00
if e != nil {
2010-09-23 12:36:52 +10:00
return e
}
2011-07-01 10:18:07 -04:00
defer Close ( h )
2020-10-19 19:19:17 +02:00
a := Filetime { }
w := Filetime { }
if tv [ 0 ] . Nanoseconds ( ) != 0 {
a = NsecToFiletime ( tv [ 0 ] . Nanoseconds ( ) )
}
if tv [ 0 ] . Nanoseconds ( ) != 0 {
w = NsecToFiletime ( tv [ 1 ] . Nanoseconds ( ) )
}
2011-02-11 10:15:51 +11:00
return SetFileTime ( h , nil , & a , & w )
2010-05-24 11:48:14 -07:00
}
2023-05-15 13:53:21 -07:00
// This matches the value in os/file_windows.go.
const _UTIME_OMIT = - 1
2012-12-13 13:02:39 -08:00
func UtimesNano ( path string , ts [ ] Timespec ) ( err error ) {
if len ( ts ) != 2 {
return EINVAL
}
pathp , e := UTF16PtrFromString ( path )
if e != nil {
return e
}
h , e := CreateFile ( pathp ,
FILE_WRITE_ATTRIBUTES , FILE_SHARE_WRITE , nil ,
2014-10-06 19:22:48 -04:00
OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , 0 )
2012-12-13 13:02:39 -08:00
if e != nil {
return e
}
defer Close ( h )
2020-10-19 19:19:17 +02:00
a := Filetime { }
w := Filetime { }
2023-05-15 13:53:21 -07:00
if ts [ 0 ] . Nsec != _UTIME_OMIT {
2020-10-19 19:19:17 +02:00
a = NsecToFiletime ( TimespecToNsec ( ts [ 0 ] ) )
}
2023-05-15 13:53:21 -07:00
if ts [ 1 ] . Nsec != _UTIME_OMIT {
2020-10-19 19:19:17 +02:00
w = NsecToFiletime ( TimespecToNsec ( ts [ 1 ] ) )
}
2012-12-13 13:02:39 -08:00
return SetFileTime ( h , nil , & a , & w )
}
2011-11-13 22:44:52 -05:00
func Fsync ( fd Handle ) ( err error ) {
2011-07-01 10:18:07 -04:00
return FlushFileBuffers ( fd )
2011-02-09 14:54:54 +11:00
}
2011-11-13 22:44:52 -05:00
func Chmod ( path string , mode uint32 ) ( err error ) {
syscall: return EINVAL when string arguments have NUL characters
Since NUL usually terminates strings in underlying syscalls, allowing
it when converting string arguments is a security risk, especially
when dealing with filenames. For example, a program might reason that
filename like "/root/..\x00/" is a subdirectory or "/root/" and allow
access to it, while underlying syscall will treat "\x00" as an end of
that string and the actual filename will be "/root/..", which might
be unexpected. Returning EINVAL when string arguments have NUL in
them makes sure this attack vector is unusable.
R=golang-dev, r, bradfitz, fullung, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6458050
2012-08-05 17:24:32 -04:00
p , e := UTF16PtrFromString ( path )
if e != nil {
return e
}
2011-02-17 12:09:12 +11:00
attrs , e := GetFileAttributes ( p )
2011-11-13 22:44:52 -05:00
if e != nil {
2011-02-17 12:09:12 +11:00
return e
}
if mode & S_IWRITE != 0 {
attrs &^= FILE_ATTRIBUTE_READONLY
} else {
attrs |= FILE_ATTRIBUTE_READONLY
}
return SetFileAttributes ( p , attrs )
}
net: fix connection resets when closed on windows
It is common to close network connection while another goroutine is
blocked reading on another goroutine. This sequence corresponds to
windows calls to WSARecv to start io, followed by GetQueuedCompletionStatus
that blocks until io completes, and, finally, closesocket called from
another thread. We were expecting that closesocket would unblock
GetQueuedCompletionStatus, and it does, but not always
(http://code.google.com/p/go/issues/detail?id=4170#c5). Also that sequence
results in connection is being reset.
This CL inserts CancelIo between GetQueuedCompletionStatus and closesocket,
and waits for both WSARecv and GetQueuedCompletionStatus to complete before
proceeding to closesocket. This seems to fix both connection resets and
issue 4170. It also makes windows code behave similar to unix version.
Unfortunately, CancelIo needs to be called on the same thread as WSARecv.
So we have to employ strategy we use for connections with deadlines to
every connection now. It means, there are 2 unavoidable thread switches
for every io. Some newer versions of windows have new CancelIoEx api that
doesn't have these drawbacks, and this CL uses this capability when available.
As time goes by, we should have less of CancelIo and more of CancelIoEx
systems. Computers with CancelIoEx are also not affected by issue 4195 anymore.
Fixes #3710
Fixes #3746
Fixes #4170
Partial fix for issue 4195
R=golang-dev, mikioh.mikioh, bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6604072
2012-10-31 10:24:37 +11:00
func LoadCancelIoEx ( ) error {
return procCancelIoEx . Find ( )
}
2013-08-08 17:36:43 +04:00
func LoadSetFileCompletionNotificationModes ( ) error {
return procSetFileCompletionNotificationModes . Find ( )
}
2010-06-29 20:23:39 -07:00
// net api calls
2012-09-25 17:06:39 +10:00
const socket_error = uintptr ( ^ uint32 ( 0 ) )
2011-12-08 12:07:21 +11:00
//sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup
2012-09-25 17:06:39 +10:00
//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup
//sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl
2011-11-13 22:44:52 -05:00
//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
2012-09-25 17:06:39 +10:00
//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt
//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt
2014-04-06 12:18:01 +10:00
//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind
//sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect
2012-09-25 17:06:39 +10:00
//sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname
//sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername
//sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen
//sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown
//sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket
2011-11-13 22:44:52 -05:00
//sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx
2011-09-08 16:32:40 +10:00
//sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs
2012-09-25 17:06:39 +10:00
//sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv
//sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend
//sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom
//sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo
2011-11-13 22:44:52 -05:00
//sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname
//sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname
2010-07-29 14:58:28 +10:00
//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
2011-11-13 22:44:52 -05:00
//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
2011-12-08 12:07:21 +11:00
//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
2010-07-29 14:58:28 +10:00
//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
2014-08-15 16:37:19 +10:00
//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W
2012-11-07 16:58:20 +11:00
//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW
//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW
2011-12-08 12:07:21 +11:00
//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
2013-08-08 17:36:43 +04:00
//sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes
//sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW
2010-07-29 14:58:28 +10:00
2010-09-12 12:02:29 +10:00
// For testing: clients can set this flag to force
2023-11-04 15:21:26 +08:00
// creation of IPv6 sockets to return [EAFNOSUPPORT].
2010-09-12 12:02:29 +10:00
var SocketDisableIPv6 bool
2010-06-29 20:23:39 -07:00
type RawSockaddrInet4 struct {
Family uint16
Port uint16
Addr [ 4 ] byte /* in_addr */
Zero [ 8 ] uint8
}
2012-11-07 16:58:20 +11:00
type RawSockaddrInet6 struct {
Family uint16
Port uint16
Flowinfo uint32
Addr [ 16 ] byte /* in6_addr */
Scope_id uint32
}
2010-06-29 20:23:39 -07:00
type RawSockaddr struct {
Family uint16
Data [ 14 ] int8
}
type RawSockaddrAny struct {
Addr RawSockaddr
2018-07-23 01:47:11 +09:00
Pad [ 100 ] int8
2010-06-29 20:23:39 -07:00
}
type Sockaddr interface {
2014-04-06 12:18:01 +10:00
sockaddr ( ) ( ptr unsafe . Pointer , len int32 , err error ) // lowercase; only we can define Sockaddrs
2010-06-29 20:23:39 -07:00
}
type SockaddrInet4 struct {
Port int
Addr [ 4 ] byte
raw RawSockaddrInet4
}
2014-04-06 12:18:01 +10:00
func ( sa * SockaddrInet4 ) sockaddr ( ) ( unsafe . Pointer , int32 , error ) {
2010-06-29 20:23:39 -07:00
if sa . Port < 0 || sa . Port > 0xFFFF {
2014-04-06 12:18:01 +10:00
return nil , 0 , EINVAL
2010-06-29 20:23:39 -07:00
}
sa . raw . Family = AF_INET
p := ( * [ 2 ] byte ) ( unsafe . Pointer ( & sa . raw . Port ) )
p [ 0 ] = byte ( sa . Port >> 8 )
p [ 1 ] = byte ( sa . Port )
2021-11-01 17:28:19 -07:00
sa . raw . Addr = sa . Addr
2014-04-06 12:18:01 +10:00
return unsafe . Pointer ( & sa . raw ) , int32 ( unsafe . Sizeof ( sa . raw ) ) , nil
2010-06-29 20:23:39 -07:00
}
type SockaddrInet6 struct {
2011-05-22 10:09:07 -07:00
Port int
ZoneId uint32
Addr [ 16 ] byte
2012-11-07 16:58:20 +11:00
raw RawSockaddrInet6
2010-06-29 20:23:39 -07:00
}
2014-04-06 12:18:01 +10:00
func ( sa * SockaddrInet6 ) sockaddr ( ) ( unsafe . Pointer , int32 , error ) {
2012-11-07 16:58:20 +11:00
if sa . Port < 0 || sa . Port > 0xFFFF {
2014-04-06 12:18:01 +10:00
return nil , 0 , EINVAL
2012-11-07 16:58:20 +11:00
}
sa . raw . Family = AF_INET6
p := ( * [ 2 ] byte ) ( unsafe . Pointer ( & sa . raw . Port ) )
p [ 0 ] = byte ( sa . Port >> 8 )
p [ 1 ] = byte ( sa . Port )
sa . raw . Scope_id = sa . ZoneId
2021-11-01 17:28:19 -07:00
sa . raw . Addr = sa . Addr
2014-04-06 12:18:01 +10:00
return unsafe . Pointer ( & sa . raw ) , int32 ( unsafe . Sizeof ( sa . raw ) ) , nil
2010-06-29 20:23:39 -07:00
}
2018-07-23 01:47:11 +09:00
type RawSockaddrUnix struct {
Family uint16
Path [ UNIX_PATH_MAX ] int8
}
2010-06-29 20:23:39 -07:00
type SockaddrUnix struct {
Name string
2018-07-23 01:47:11 +09:00
raw RawSockaddrUnix
2010-06-29 20:23:39 -07:00
}
2014-04-06 12:18:01 +10:00
func ( sa * SockaddrUnix ) sockaddr ( ) ( unsafe . Pointer , int32 , error ) {
2018-07-23 01:47:11 +09:00
name := sa . Name
n := len ( name )
if n > len ( sa . raw . Path ) {
return nil , 0 , EINVAL
}
if n == len ( sa . raw . Path ) && name [ 0 ] != '@' {
return nil , 0 , EINVAL
}
sa . raw . Family = AF_UNIX
for i := 0 ; i < n ; i ++ {
sa . raw . Path [ i ] = int8 ( name [ i ] )
}
// length is family (uint16), name, NUL.
sl := int32 ( 2 )
if n > 0 {
sl += int32 ( n ) + 1
}
2023-10-17 21:59:17 +00:00
if sa . raw . Path [ 0 ] == '@' || ( sa . raw . Path [ 0 ] == 0 && sl > 3 ) {
// Check sl > 3 so we don't change unnamed socket behavior.
2018-07-23 01:47:11 +09:00
sa . raw . Path [ 0 ] = 0
// Don't count trailing NUL for abstract address.
sl --
}
return unsafe . Pointer ( & sa . raw ) , sl , nil
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func ( rsa * RawSockaddrAny ) Sockaddr ( ) ( Sockaddr , error ) {
2010-06-29 20:23:39 -07:00
switch rsa . Addr . Family {
case AF_UNIX :
2018-07-23 01:47:11 +09:00
pp := ( * RawSockaddrUnix ) ( unsafe . Pointer ( rsa ) )
sa := new ( SockaddrUnix )
if pp . Path [ 0 ] == 0 {
// "Abstract" Unix domain socket.
// Rewrite leading NUL as @ for textual display.
// (This is the standard convention.)
// Not friendly to overwrite in place,
// but the callers below don't care.
pp . Path [ 0 ] = '@'
}
// Assume path ends at NUL.
// This is not technically the Linux semantics for
// abstract Unix domain sockets--they are supposed
// to be uninterpreted fixed-size binary blobs--but
// everyone uses this convention.
n := 0
for n < len ( pp . Path ) && pp . Path [ n ] != 0 {
n ++
}
2023-02-28 13:58:42 +01:00
sa . Name = string ( unsafe . Slice ( ( * byte ) ( unsafe . Pointer ( & pp . Path [ 0 ] ) ) , n ) )
2018-07-23 01:47:11 +09:00
return sa , nil
2010-06-29 20:23:39 -07:00
case AF_INET :
pp := ( * RawSockaddrInet4 ) ( unsafe . Pointer ( rsa ) )
sa := new ( SockaddrInet4 )
p := ( * [ 2 ] byte ) ( unsafe . Pointer ( & pp . Port ) )
sa . Port = int ( p [ 0 ] ) << 8 + int ( p [ 1 ] )
2021-11-01 17:28:19 -07:00
sa . Addr = pp . Addr
2011-11-13 22:44:52 -05:00
return sa , nil
2010-06-29 20:23:39 -07:00
case AF_INET6 :
2012-11-07 16:58:20 +11:00
pp := ( * RawSockaddrInet6 ) ( unsafe . Pointer ( rsa ) )
sa := new ( SockaddrInet6 )
p := ( * [ 2 ] byte ) ( unsafe . Pointer ( & pp . Port ) )
sa . Port = int ( p [ 0 ] ) << 8 + int ( p [ 1 ] )
sa . ZoneId = pp . Scope_id
2021-11-01 17:28:19 -07:00
sa . Addr = pp . Addr
2012-11-07 16:58:20 +11:00
return sa , nil
2010-06-29 20:23:39 -07:00
}
return nil , EAFNOSUPPORT
}
2011-11-13 22:44:52 -05:00
func Socket ( domain , typ , proto int ) ( fd Handle , err error ) {
2010-09-12 12:02:29 +10:00
if domain == AF_INET6 && SocketDisableIPv6 {
2011-07-01 10:18:07 -04:00
return InvalidHandle , EAFNOSUPPORT
2010-09-12 12:02:29 +10:00
}
2011-11-13 22:44:52 -05:00
return socket ( int32 ( domain ) , int32 ( typ ) , int32 ( proto ) )
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func SetsockoptInt ( fd Handle , level , opt int , value int ) ( err error ) {
2010-06-29 20:23:39 -07:00
v := int32 ( value )
2011-11-13 22:44:52 -05:00
return Setsockopt ( fd , int32 ( level ) , int32 ( opt ) , ( * byte ) ( unsafe . Pointer ( & v ) ) , int32 ( unsafe . Sizeof ( v ) ) )
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func Bind ( fd Handle , sa Sockaddr ) ( err error ) {
2010-06-29 20:23:39 -07:00
ptr , n , err := sa . sockaddr ( )
2011-11-13 22:44:52 -05:00
if err != nil {
2010-06-29 20:23:39 -07:00
return err
}
2011-07-01 10:18:07 -04:00
return bind ( fd , ptr , n )
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func Connect ( fd Handle , sa Sockaddr ) ( err error ) {
2010-06-29 20:23:39 -07:00
ptr , n , err := sa . sockaddr ( )
2011-11-13 22:44:52 -05:00
if err != nil {
2010-06-29 20:23:39 -07:00
return err
}
2011-07-01 10:18:07 -04:00
return connect ( fd , ptr , n )
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func Getsockname ( fd Handle ) ( sa Sockaddr , err error ) {
2010-06-29 20:23:39 -07:00
var rsa RawSockaddrAny
l := int32 ( unsafe . Sizeof ( rsa ) )
2011-11-13 22:44:52 -05:00
if err = getsockname ( fd , & rsa , & l ) ; err != nil {
2010-06-29 20:23:39 -07:00
return
}
return rsa . Sockaddr ( )
}
2011-11-13 22:44:52 -05:00
func Getpeername ( fd Handle ) ( sa Sockaddr , err error ) {
2010-06-29 20:23:39 -07:00
var rsa RawSockaddrAny
l := int32 ( unsafe . Sizeof ( rsa ) )
2011-11-13 22:44:52 -05:00
if err = getpeername ( fd , & rsa , & l ) ; err != nil {
2010-06-29 20:23:39 -07:00
return
}
return rsa . Sockaddr ( )
}
2011-11-13 22:44:52 -05:00
func Listen ( s Handle , n int ) ( err error ) {
return listen ( s , int32 ( n ) )
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func Shutdown ( fd Handle , how int ) ( err error ) {
return shutdown ( fd , int32 ( how ) )
2010-06-29 20:23:39 -07:00
}
2011-11-13 22:44:52 -05:00
func WSASendto ( s Handle , bufs * WSABuf , bufcnt uint32 , sent * uint32 , flags uint32 , to Sockaddr , overlapped * Overlapped , croutine * byte ) ( err error ) {
2022-09-26 22:49:08 +08:00
var rsa unsafe . Pointer
var len int32
if to != nil {
rsa , len , err = to . sockaddr ( )
if err != nil {
return err
}
2010-11-22 11:01:30 -05:00
}
2020-02-25 18:44:55 +11:00
r1 , _ , e1 := Syscall9 ( procWSASendTo . Addr ( ) , 9 , uintptr ( s ) , uintptr ( unsafe . Pointer ( bufs ) ) , uintptr ( bufcnt ) , uintptr ( unsafe . Pointer ( sent ) ) , uintptr ( flags ) , uintptr ( unsafe . Pointer ( rsa ) ) , uintptr ( len ) , uintptr ( unsafe . Pointer ( overlapped ) ) , uintptr ( unsafe . Pointer ( croutine ) ) )
2021-06-28 15:41:20 -07:00
if r1 == socket_error {
if e1 != 0 {
err = errnoErr ( e1 )
} else {
err = EINVAL
}
}
return err
}
2021-11-03 16:28:47 -07:00
func wsaSendtoInet4 ( s Handle , bufs * WSABuf , bufcnt uint32 , sent * uint32 , flags uint32 , to * SockaddrInet4 , overlapped * Overlapped , croutine * byte ) ( err error ) {
2021-06-28 15:41:20 -07:00
rsa , len , err := to . sockaddr ( )
if err != nil {
return err
}
r1 , _ , e1 := Syscall9 ( procWSASendTo . Addr ( ) , 9 , uintptr ( s ) , uintptr ( unsafe . Pointer ( bufs ) ) , uintptr ( bufcnt ) , uintptr ( unsafe . Pointer ( sent ) ) , uintptr ( flags ) , uintptr ( unsafe . Pointer ( rsa ) ) , uintptr ( len ) , uintptr ( unsafe . Pointer ( overlapped ) ) , uintptr ( unsafe . Pointer ( croutine ) ) )
if r1 == socket_error {
if e1 != 0 {
err = errnoErr ( e1 )
} else {
err = EINVAL
}
}
return err
}
2021-11-03 16:28:47 -07:00
func wsaSendtoInet6 ( s Handle , bufs * WSABuf , bufcnt uint32 , sent * uint32 , flags uint32 , to * SockaddrInet6 , overlapped * Overlapped , croutine * byte ) ( err error ) {
2021-06-28 15:41:20 -07:00
rsa , len , err := to . sockaddr ( )
if err != nil {
return err
}
r1 , _ , e1 := Syscall9 ( procWSASendTo . Addr ( ) , 9 , uintptr ( s ) , uintptr ( unsafe . Pointer ( bufs ) ) , uintptr ( bufcnt ) , uintptr ( unsafe . Pointer ( sent ) ) , uintptr ( flags ) , uintptr ( unsafe . Pointer ( rsa ) ) , uintptr ( len ) , uintptr ( unsafe . Pointer ( overlapped ) ) , uintptr ( unsafe . Pointer ( croutine ) ) )
2020-02-25 18:44:55 +11:00
if r1 == socket_error {
if e1 != 0 {
err = errnoErr ( e1 )
} else {
err = EINVAL
}
}
return err
2010-11-22 11:01:30 -05:00
}
2012-11-07 16:58:20 +11:00
func LoadGetAddrInfo ( ) error {
return procGetAddrInfoW . Find ( )
}
2013-01-11 12:42:09 +11:00
var connectExFunc struct {
once sync . Once
addr uintptr
err error
}
func LoadConnectEx ( ) error {
connectExFunc . once . Do ( func ( ) {
var s Handle
s , connectExFunc . err = Socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP )
if connectExFunc . err != nil {
return
}
defer CloseHandle ( s )
var n uint32
connectExFunc . err = WSAIoctl ( s ,
SIO_GET_EXTENSION_FUNCTION_POINTER ,
( * byte ) ( unsafe . Pointer ( & WSAID_CONNECTEX ) ) ,
uint32 ( unsafe . Sizeof ( WSAID_CONNECTEX ) ) ,
( * byte ) ( unsafe . Pointer ( & connectExFunc . addr ) ) ,
uint32 ( unsafe . Sizeof ( connectExFunc . addr ) ) ,
& n , nil , 0 )
} )
return connectExFunc . err
}
2014-04-06 12:18:01 +10:00
func connectEx ( s Handle , name unsafe . Pointer , namelen int32 , sendBuf * byte , sendDataLen uint32 , bytesSent * uint32 , overlapped * Overlapped ) ( err error ) {
2013-01-11 12:42:09 +11:00
r1 , _ , e1 := Syscall9 ( connectExFunc . addr , 7 , uintptr ( s ) , uintptr ( name ) , uintptr ( namelen ) , uintptr ( unsafe . Pointer ( sendBuf ) ) , uintptr ( sendDataLen ) , uintptr ( unsafe . Pointer ( bytesSent ) ) , uintptr ( unsafe . Pointer ( overlapped ) ) , 0 , 0 )
if r1 == 0 {
if e1 != 0 {
err = error ( e1 )
} else {
err = EINVAL
}
}
return
}
func ConnectEx ( fd Handle , sa Sockaddr , sendBuf * byte , sendDataLen uint32 , bytesSent * uint32 , overlapped * Overlapped ) error {
err := LoadConnectEx ( )
if err != nil {
return errorspkg . New ( "failed to find ConnectEx: " + err . Error ( ) )
}
ptr , n , err := sa . sockaddr ( )
if err != nil {
return err
}
return connectEx ( fd , ptr , n , sendBuf , sendDataLen , bytesSent , overlapped )
}
2011-02-04 14:41:26 +11:00
// Invented structures to support what package os expects.
2012-03-02 14:47:40 +11:00
type Rusage struct {
CreationTime Filetime
ExitTime Filetime
KernelTime Filetime
UserTime Filetime
}
2011-02-04 14:41:26 +11:00
type WaitStatus struct {
ExitCode uint32
}
func ( w WaitStatus ) Exited ( ) bool { return true }
func ( w WaitStatus ) ExitStatus ( ) int { return int ( w . ExitCode ) }
2012-02-14 13:51:38 +11:00
func ( w WaitStatus ) Signal ( ) Signal { return - 1 }
2011-02-04 14:41:26 +11:00
func ( w WaitStatus ) CoreDump ( ) bool { return false }
func ( w WaitStatus ) Stopped ( ) bool { return false }
func ( w WaitStatus ) Continued ( ) bool { return false }
2012-02-14 13:51:38 +11:00
func ( w WaitStatus ) StopSignal ( ) Signal { return - 1 }
2011-02-04 14:41:26 +11:00
2011-04-08 10:27:47 +10:00
func ( w WaitStatus ) Signaled ( ) bool { return false }
2011-02-04 14:41:26 +11:00
func ( w WaitStatus ) TrapCause ( ) int { return - 1 }
2012-01-18 19:05:44 -08:00
// Timespec is an invented structure on Windows, but here for
// consistency with the syscall package for other operating systems.
type Timespec struct {
Sec int64
Nsec int64
}
2012-12-13 13:02:39 -08:00
func TimespecToNsec ( ts Timespec ) int64 { return int64 ( ts . Sec ) * 1e9 + int64 ( ts . Nsec ) }
func NsecToTimespec ( nsec int64 ) ( ts Timespec ) {
ts . Sec = nsec / 1e9
ts . Nsec = nsec % 1e9
return
}
2010-06-29 20:23:39 -07:00
// TODO(brainman): fix all needed for net
2011-11-13 22:44:52 -05:00
func Accept ( fd Handle ) ( nfd Handle , sa Sockaddr , err error ) { return 0 , nil , EWINDOWS }
func Recvfrom ( fd Handle , p [ ] byte , flags int ) ( n int , from Sockaddr , err error ) {
2011-07-01 10:18:07 -04:00
return 0 , nil , EWINDOWS
}
2011-11-13 22:44:52 -05:00
func Sendto ( fd Handle , p [ ] byte , flags int , to Sockaddr ) ( err error ) { return EWINDOWS }
func SetsockoptTimeval ( fd Handle , level , opt int , tv * Timeval ) ( err error ) { return EWINDOWS }
2010-06-29 20:23:39 -07:00
2012-05-23 13:05:05 +10:00
// The Linger struct is wrong but we only noticed after Go 1.
// sysLinger is the real system call structure.
// BUG(brainman): The definition of Linger is not appropriate for direct use
// with Setsockopt and Getsockopt.
// Use SetsockoptLinger instead.
2010-06-29 20:23:39 -07:00
type Linger struct {
Onoff int32
Linger int32
}
2012-05-23 13:05:05 +10:00
type sysLinger struct {
Onoff uint16
Linger uint16
}
2011-06-02 10:10:17 -04:00
type IPMreq struct {
2011-02-17 12:00:02 +11:00
Multiaddr [ 4 ] byte /* in_addr */
Interface [ 4 ] byte /* in_addr */
}
2011-06-02 10:10:17 -04:00
type IPv6Mreq struct {
Multiaddr [ 16 ] byte /* in6_addr */
Interface uint32
}
2024-02-21 02:30:42 +08:00
func GetsockoptInt ( fd Handle , level , opt int ) ( int , error ) {
optval := int32 ( 0 )
optlen := int32 ( unsafe . Sizeof ( optval ) )
err := Getsockopt ( fd , int32 ( level ) , int32 ( opt ) , ( * byte ) ( unsafe . Pointer ( & optval ) ) , & optlen )
return int ( optval ) , err
}
2012-05-23 13:05:05 +10:00
func SetsockoptLinger ( fd Handle , level , opt int , l * Linger ) ( err error ) {
sys := sysLinger { Onoff : uint16 ( l . Onoff ) , Linger : uint16 ( l . Linger ) }
return Setsockopt ( fd , int32 ( level ) , int32 ( opt ) , ( * byte ) ( unsafe . Pointer ( & sys ) ) , int32 ( unsafe . Sizeof ( sys ) ) )
}
2012-02-01 14:14:04 +09:00
func SetsockoptInet4Addr ( fd Handle , level , opt int , value [ 4 ] byte ) ( err error ) {
return Setsockopt ( fd , int32 ( level ) , int32 ( opt ) , ( * byte ) ( unsafe . Pointer ( & value [ 0 ] ) ) , 4 )
}
2011-11-13 22:44:52 -05:00
func SetsockoptIPMreq ( fd Handle , level , opt int , mreq * IPMreq ) ( err error ) {
2011-09-08 16:32:40 +10:00
return Setsockopt ( fd , int32 ( level ) , int32 ( opt ) , ( * byte ) ( unsafe . Pointer ( mreq ) ) , int32 ( unsafe . Sizeof ( * mreq ) ) )
}
2011-11-13 22:44:52 -05:00
func SetsockoptIPv6Mreq ( fd Handle , level , opt int , mreq * IPv6Mreq ) ( err error ) { return EWINDOWS }
2010-06-29 20:23:39 -07:00
2012-06-08 14:28:29 -04:00
func Getpid ( ) ( pid int ) { return int ( getCurrentProcessId ( ) ) }
2010-04-02 01:11:17 -07:00
2012-06-03 19:27:17 +10:00
func FindFirstFile ( name * uint16 , data * Win32finddata ) ( handle Handle , err error ) {
2012-06-08 13:54:48 -04:00
// NOTE(rsc): The Win32finddata struct is wrong for the system call:
// the two paths are each one uint16 short. Use the correct struct,
// a win32finddata1, and then copy the results out.
// There is no loss of expressivity here, because the final
// uint16, if it is used, is supposed to be a NUL, and Go doesn't need that.
// For Go 1.1, we might avoid the allocation of win32finddata1 here
// by adding a final Bug [2]uint16 field to the struct and then
// adjusting the fields in the result directly.
var data1 win32finddata1
handle , err = findFirstFile1 ( name , & data1 )
if err == nil {
copyFindData ( data , & data1 )
}
return
2012-06-03 19:27:17 +10:00
}
func FindNextFile ( handle Handle , data * Win32finddata ) ( err error ) {
2012-06-08 13:54:48 -04:00
var data1 win32finddata1
err = findNextFile1 ( handle , & data1 )
if err == nil {
copyFindData ( data , & data1 )
}
return
2012-06-03 19:27:17 +10:00
}
2014-06-14 15:51:00 +10:00
func getProcessEntry ( pid int ) ( * ProcessEntry32 , error ) {
snapshot , err := CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS , 0 )
if err != nil {
return nil , err
}
defer CloseHandle ( snapshot )
var procEntry ProcessEntry32
procEntry . Size = uint32 ( unsafe . Sizeof ( procEntry ) )
if err = Process32First ( snapshot , & procEntry ) ; err != nil {
return nil , err
}
for {
if procEntry . ProcessID == uint32 ( pid ) {
return & procEntry , nil
}
err = Process32Next ( snapshot , & procEntry )
if err != nil {
return nil , err
}
}
}
func Getppid ( ) ( ppid int ) {
pe , err := getProcessEntry ( Getpid ( ) )
if err != nil {
return - 1
}
return int ( pe . ParentProcessID )
}
2010-04-02 01:11:17 -07:00
2023-03-29 10:28:33 +02:00
func fdpath ( fd Handle , buf [ ] uint16 ) ( [ ] uint16 , error ) {
const (
FILE_NAME_NORMALIZED = 0
VOLUME_NAME_DOS = 0
)
for {
n , err := getFinalPathNameByHandle ( fd , & buf [ 0 ] , uint32 ( len ( buf ) ) , FILE_NAME_NORMALIZED | VOLUME_NAME_DOS )
if err == nil {
buf = buf [ : n ]
break
}
if err != _ERROR_NOT_ENOUGH_MEMORY {
return nil , err
}
buf = append ( buf , make ( [ ] uint16 , n - uint32 ( len ( buf ) ) ) ... )
}
return buf , nil
}
func Fchdir ( fd Handle ) ( err error ) {
var buf [ MAX_PATH + 1 ] uint16
path , err := fdpath ( fd , buf [ : ] )
if err != nil {
return err
}
2024-01-30 15:19:54 +00:00
// When using VOLUME_NAME_DOS, the path is always prefixed by "\\?\".
2023-03-29 10:28:33 +02:00
// That prefix tells the Windows APIs to disable all string parsing and to send
// the string that follows it straight to the file system.
// Although SetCurrentDirectory and GetCurrentDirectory do support the "\\?\" prefix,
// some other Windows APIs don't. If the prefix is not removed here, it will leak
// to Getwd, and we don't want such a general-purpose function to always return a
// path with the "\\?\" prefix after Fchdir is called.
// The downside is that APIs that do support it will parse the path and try to normalize it,
// when it's already normalized.
if len ( path ) >= 4 && path [ 0 ] == '\\' && path [ 1 ] == '\\' && path [ 2 ] == '?' && path [ 3 ] == '\\' {
path = path [ 4 : ]
}
return SetCurrentDirectory ( & path [ 0 ] )
}
2014-06-14 15:51:00 +10:00
// TODO(brainman): fix all needed for os
2014-07-17 17:02:46 +10:00
func Link ( oldpath , newpath string ) ( err error ) { return EWINDOWS }
func Symlink ( path , link string ) ( err error ) { return EWINDOWS }
2011-02-16 16:24:59 +11:00
2011-11-13 22:44:52 -05:00
func Fchmod ( fd Handle , mode uint32 ) ( err error ) { return EWINDOWS }
func Chown ( path string , uid int , gid int ) ( err error ) { return EWINDOWS }
func Lchown ( path string , uid int , gid int ) ( err error ) { return EWINDOWS }
func Fchown ( fd Handle , uid int , gid int ) ( err error ) { return EWINDOWS }
2010-04-02 01:11:17 -07:00
2010-04-26 23:17:14 -07:00
func Getuid ( ) ( uid int ) { return - 1 }
func Geteuid ( ) ( euid int ) { return - 1 }
func Getgid ( ) ( gid int ) { return - 1 }
func Getegid ( ) ( egid int ) { return - 1 }
2011-11-13 22:44:52 -05:00
func Getgroups ( ) ( gids [ ] int , err error ) { return nil , EWINDOWS }
2012-02-14 13:51:38 +11:00
type Signal int
func ( s Signal ) Signal ( ) { }
func ( s Signal ) String ( ) string {
if 0 <= s && int ( s ) < len ( signals ) {
str := signals [ s ]
if str != "" {
return str
}
}
2021-03-13 16:52:16 -08:00
return "signal " + itoa . Itoa ( int ( s ) )
2012-02-14 13:51:38 +11:00
}
2014-07-17 17:02:46 +10:00
func LoadCreateSymbolicLink ( ) error {
return procCreateSymbolicLinkW . Find ( )
}
// Readlink returns the destination of the named symbolic link.
func Readlink ( path string , buf [ ] byte ) ( n int , err error ) {
fd , err := CreateFile ( StringToUTF16Ptr ( path ) , GENERIC_READ , 0 , nil , OPEN_EXISTING ,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS , 0 )
if err != nil {
return - 1 , err
}
defer CloseHandle ( fd )
rdbbuf := make ( [ ] byte , MAXIMUM_REPARSE_DATA_BUFFER_SIZE )
var bytesReturned uint32
err = DeviceIoControl ( fd , FSCTL_GET_REPARSE_POINT , nil , 0 , & rdbbuf [ 0 ] , uint32 ( len ( rdbbuf ) ) , & bytesReturned , nil )
if err != nil {
return - 1 , err
}
rdb := ( * reparseDataBuffer ) ( unsafe . Pointer ( & rdbbuf [ 0 ] ) )
2015-01-06 09:47:37 +09:00
var s string
switch rdb . ReparseTag {
case IO_REPARSE_TAG_SYMLINK :
data := ( * symbolicLinkReparseBuffer ) ( unsafe . Pointer ( & rdb . reparseBuffer ) )
p := ( * [ 0xffff ] uint16 ) ( unsafe . Pointer ( & data . PathBuffer [ 0 ] ) )
2016-10-16 13:25:53 +09:00
s = UTF16ToString ( p [ data . SubstituteNameOffset / 2 : ( data . SubstituteNameOffset + data . SubstituteNameLength ) / 2 ] )
if data . Flags & _SYMLINK_FLAG_RELATIVE == 0 {
if len ( s ) >= 4 && s [ : 4 ] == ` \??\ ` {
s = s [ 4 : ]
switch {
case len ( s ) >= 2 && s [ 1 ] == ':' : // \??\C:\foo\bar
// do nothing
case len ( s ) >= 4 && s [ : 4 ] == ` UNC\ ` : // \??\UNC\foo\bar
s = ` \\ ` + s [ 4 : ]
default :
// unexpected; do nothing
}
} else {
// unexpected; do nothing
}
}
2015-01-06 09:47:37 +09:00
case _IO_REPARSE_TAG_MOUNT_POINT :
data := ( * mountPointReparseBuffer ) ( unsafe . Pointer ( & rdb . reparseBuffer ) )
p := ( * [ 0xffff ] uint16 ) ( unsafe . Pointer ( & data . PathBuffer [ 0 ] ) )
2016-10-16 13:25:53 +09:00
s = UTF16ToString ( p [ data . SubstituteNameOffset / 2 : ( data . SubstituteNameOffset + data . SubstituteNameLength ) / 2 ] )
if len ( s ) >= 4 && s [ : 4 ] == ` \??\ ` { // \??\C:\foo\bar
s = s [ 4 : ]
} else {
// unexpected; do nothing
}
2015-01-06 09:47:37 +09:00
default :
// the path is not a symlink or junction but another type of reparse
// point
2014-07-17 17:02:46 +10:00
return - 1 , ENOENT
}
n = copy ( buf , [ ] byte ( s ) )
2015-01-06 09:47:37 +09:00
2014-07-17 17:02:46 +10:00
return n , nil
}
2021-02-24 22:59:59 +01:00
// Deprecated: CreateIoCompletionPort has the wrong function signature. Use x/sys/windows.CreateIoCompletionPort.
func CreateIoCompletionPort ( filehandle Handle , cphandle Handle , key uint32 , threadcnt uint32 ) ( Handle , error ) {
return createIoCompletionPort ( filehandle , cphandle , uintptr ( key ) , threadcnt )
}
// Deprecated: GetQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.GetQueuedCompletionStatus.
func GetQueuedCompletionStatus ( cphandle Handle , qty * uint32 , key * uint32 , overlapped * * Overlapped , timeout uint32 ) error {
var ukey uintptr
var pukey * uintptr
if key != nil {
ukey = uintptr ( * key )
pukey = & ukey
}
err := getQueuedCompletionStatus ( cphandle , qty , pukey , overlapped , timeout )
if key != nil {
* key = uint32 ( ukey )
2021-02-25 02:58:04 +01:00
if uintptr ( * key ) != ukey && err == nil {
err = errorspkg . New ( "GetQueuedCompletionStatus returned key overflow" )
}
2021-02-24 22:59:59 +01:00
}
return err
}
// Deprecated: PostQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.PostQueuedCompletionStatus.
func PostQueuedCompletionStatus ( cphandle Handle , qty uint32 , key uint32 , overlapped * Overlapped ) error {
return postQueuedCompletionStatus ( cphandle , qty , uintptr ( key ) , overlapped )
}
2021-01-31 17:37:20 +01:00
// newProcThreadAttributeList allocates new PROC_THREAD_ATTRIBUTE_LIST, with
// the requested maximum number of attributes, which must be cleaned up by
// deleteProcThreadAttributeList.
func newProcThreadAttributeList ( maxAttrCount uint32 ) ( * _PROC_THREAD_ATTRIBUTE_LIST , error ) {
var size uintptr
err := initializeProcThreadAttributeList ( nil , maxAttrCount , 0 , & size )
if err != ERROR_INSUFFICIENT_BUFFER {
if err == nil {
return nil , errorspkg . New ( "unable to query buffer size from InitializeProcThreadAttributeList" )
}
return nil , err
}
2021-02-28 12:18:18 +01:00
// size is guaranteed to be ≥1 by initializeProcThreadAttributeList.
2021-03-10 07:21:56 -07:00
al := ( * _PROC_THREAD_ATTRIBUTE_LIST ) ( unsafe . Pointer ( & make ( [ ] byte , size ) [ 0 ] ) )
2021-01-31 17:37:20 +01:00
err = initializeProcThreadAttributeList ( al , maxAttrCount , 0 , & size )
if err != nil {
return nil , err
}
return al , nil
}
2021-11-03 18:18:18 +00:00
// RegEnumKeyEx enumerates the subkeys of an open registry key.
// Each call retrieves information about one subkey. name is
// a buffer that should be large enough to hold the name of the
// subkey plus a null terminating character. nameLen is its
// length. On return, nameLen will contain the actual length of the
// subkey.
//
// Should name not be large enough to hold the subkey, this function
// will return ERROR_MORE_DATA, and must be called again with an
// appropriately sized buffer.
//
// reserved must be nil. class and classLen behave like name and nameLen
// but for the class of the subkey, except that they are optional.
// lastWriteTime, if not nil, will be populated with the time the subkey
// was last written.
//
// The caller must enumerate all subkeys in order. That is
// RegEnumKeyEx must be called with index starting at 0, incrementing
// the index until the function returns ERROR_NO_MORE_ITEMS, or with
// the index of the last subkey (obtainable from RegQueryInfoKey),
// decrementing until index 0 is enumerated.
//
// Successive calls to this API must happen on the same OS thread,
2023-11-04 15:21:26 +08:00
// so call [runtime.LockOSThread] before calling this function.
2021-11-03 18:18:18 +00:00
func RegEnumKeyEx ( key Handle , index uint32 , name * uint16 , nameLen * uint32 , reserved * uint32 , class * uint16 , classLen * uint32 , lastWriteTime * Filetime ) ( regerrno error ) {
return regEnumKeyEx ( key , index , name , nameLen , reserved , class , classLen , lastWriteTime )
}
2023-08-17 00:03:13 +02:00
func GetStartupInfo ( startupInfo * StartupInfo ) error {
getStartupInfo ( startupInfo )
return nil
}