1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Windows system calls. 6 7package syscall 8 9import ( 10 errorspkg "errors" 11 "internal/asan" 12 "internal/bytealg" 13 "internal/itoa" 14 "internal/msan" 15 "internal/oserror" 16 "internal/race" 17 "runtime" 18 "sync" 19 "unsafe" 20) 21 22type Handle uintptr 23 24const InvalidHandle = ^Handle(0) 25 26// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s, 27// with a terminating NUL added. If s contains a NUL byte this 28// function panics instead of returning an error. 29// 30// Deprecated: Use [UTF16FromString] instead. 31func StringToUTF16(s string) []uint16 { 32 a, err := UTF16FromString(s) 33 if err != nil { 34 panic("syscall: string with NUL passed to StringToUTF16") 35 } 36 return a 37} 38 39// UTF16FromString returns the UTF-16 encoding of the UTF-8 string 40// s, with a terminating NUL added. If s contains a NUL byte at any 41// location, it returns (nil, [EINVAL]). Unpaired surrogates 42// are encoded using WTF-8. 43func UTF16FromString(s string) ([]uint16, error) { 44 if bytealg.IndexByteString(s, 0) != -1 { 45 return nil, EINVAL 46 } 47 // Valid UTF-8 characters between 1 and 3 bytes require one uint16. 48 // Valid UTF-8 characters of 4 bytes require two uint16. 49 // Bytes with invalid UTF-8 encoding require maximum one uint16 per byte. 50 // So the number of UTF-8 code units (len(s)) is always greater or 51 // equal than the number of UTF-16 code units. 52 // Also account for the terminating NUL character. 53 buf := make([]uint16, 0, len(s)+1) 54 buf = encodeWTF16(s, buf) 55 return append(buf, 0), nil 56} 57 58// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, 59// with a terminating NUL removed. Unpaired surrogates are decoded 60// using WTF-8 instead of UTF-8 encoding. 61func UTF16ToString(s []uint16) string { 62 maxLen := 0 63 for i, v := range s { 64 if v == 0 { 65 s = s[0:i] 66 break 67 } 68 switch { 69 case v <= rune1Max: 70 maxLen += 1 71 case v <= rune2Max: 72 maxLen += 2 73 default: 74 // r is a non-surrogate that decodes to 3 bytes, 75 // or is an unpaired surrogate (also 3 bytes in WTF-8), 76 // or is one half of a valid surrogate pair. 77 // If it is half of a pair, we will add 3 for the second surrogate 78 // (total of 6) and overestimate by 2 bytes for the pair, 79 // since the resulting rune only requires 4 bytes. 80 maxLen += 3 81 } 82 } 83 buf := decodeWTF16(s, make([]byte, 0, maxLen)) 84 return unsafe.String(unsafe.SliceData(buf), len(buf)) 85} 86 87// utf16PtrToString is like UTF16ToString, but takes *uint16 88// as a parameter instead of []uint16. 89func utf16PtrToString(p *uint16) string { 90 if p == nil { 91 return "" 92 } 93 end := unsafe.Pointer(p) 94 n := 0 95 for *(*uint16)(end) != 0 { 96 end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) 97 n++ 98 } 99 return UTF16ToString(unsafe.Slice(p, n)) 100} 101 102// StringToUTF16Ptr returns pointer to the UTF-16 encoding of 103// the UTF-8 string s, with a terminating NUL added. If s 104// contains a NUL byte this function panics instead of 105// returning an error. 106// 107// Deprecated: Use [UTF16PtrFromString] instead. 108func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } 109 110// UTF16PtrFromString returns pointer to the UTF-16 encoding of 111// the UTF-8 string s, with a terminating NUL added. If s 112// contains a NUL byte at any location, it returns (nil, EINVAL). 113// Unpaired surrogates are encoded using WTF-8. 114func UTF16PtrFromString(s string) (*uint16, error) { 115 a, err := UTF16FromString(s) 116 if err != nil { 117 return nil, err 118 } 119 return &a[0], nil 120} 121 122// Errno is the Windows error number. 123// 124// Errno values can be tested against error values using [errors.Is]. 125// For example: 126// 127// _, _, err := syscall.Syscall(...) 128// if errors.Is(err, fs.ErrNotExist) ... 129type Errno uintptr 130 131func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) } 132 133// FormatMessage is deprecated (msgsrc should be uintptr, not uint32, but can 134// not be changed due to the Go 1 compatibility guarantee). 135// 136// Deprecated: Use FormatMessage from golang.org/x/sys/windows instead. 137func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { 138 return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args) 139} 140 141func (e Errno) Error() string { 142 // deal with special go errors 143 idx := int(e - APPLICATION_ERROR) 144 if 0 <= idx && idx < len(errors) { 145 return errors[idx] 146 } 147 // ask windows for the remaining errors 148 var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS 149 b := make([]uint16, 300) 150 n, err := formatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil) 151 if err != nil { 152 n, err = formatMessage(flags, 0, uint32(e), 0, b, nil) 153 if err != nil { 154 return "winapi error #" + itoa.Itoa(int(e)) 155 } 156 } 157 // trim terminating \r and \n 158 for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { 159 } 160 return UTF16ToString(b[:n]) 161} 162 163const ( 164 _ERROR_NOT_ENOUGH_MEMORY = Errno(8) 165 _ERROR_NOT_SUPPORTED = Errno(50) 166 _ERROR_BAD_NETPATH = Errno(53) 167 _ERROR_CALL_NOT_IMPLEMENTED = Errno(120) 168) 169 170func (e Errno) Is(target error) bool { 171 switch target { 172 case oserror.ErrPermission: 173 return e == ERROR_ACCESS_DENIED || 174 e == EACCES || 175 e == EPERM 176 case oserror.ErrExist: 177 return e == ERROR_ALREADY_EXISTS || 178 e == ERROR_DIR_NOT_EMPTY || 179 e == ERROR_FILE_EXISTS || 180 e == EEXIST || 181 e == ENOTEMPTY 182 case oserror.ErrNotExist: 183 return e == ERROR_FILE_NOT_FOUND || 184 e == _ERROR_BAD_NETPATH || 185 e == ERROR_PATH_NOT_FOUND || 186 e == ENOENT 187 case errorspkg.ErrUnsupported: 188 return e == _ERROR_NOT_SUPPORTED || 189 e == _ERROR_CALL_NOT_IMPLEMENTED || 190 e == ENOSYS || 191 e == ENOTSUP || 192 e == EOPNOTSUPP || 193 e == EWINDOWS 194 } 195 return false 196} 197 198func (e Errno) Temporary() bool { 199 return e == EINTR || e == EMFILE || e.Timeout() 200} 201 202func (e Errno) Timeout() bool { 203 return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT 204} 205 206// Implemented in runtime/syscall_windows.go. 207func compileCallback(fn any, cleanstack bool) uintptr 208 209// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. 210// This is useful when interoperating with Windows code requiring callbacks. 211// 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. 212// Only a limited number of callbacks may be created in a single Go process, and any memory allocated 213// for these callbacks is never released. 214// Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created. 215func NewCallback(fn any) uintptr { 216 return compileCallback(fn, true) 217} 218 219// NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention. 220// This is useful when interoperating with Windows code requiring callbacks. 221// 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. 222// Only a limited number of callbacks may be created in a single Go process, and any memory allocated 223// for these callbacks is never released. 224// Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created. 225func NewCallbackCDecl(fn any) uintptr { 226 return compileCallback(fn, false) 227} 228 229// windows api calls 230 231//sys GetLastError() (lasterr error) 232//sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW 233//sys FreeLibrary(handle Handle) (err error) 234//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) 235//sys GetVersion() (ver uint32, err error) 236//sys formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW 237//sys ExitProcess(exitcode uint32) 238//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW 239//sys readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = ReadFile 240//sys writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = WriteFile 241//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff] 242//sys CloseHandle(handle Handle) (err error) 243//sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle] 244//sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW 245//sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW 246//sys FindClose(handle Handle) (err error) 247//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) 248//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW 249//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW 250//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW 251//sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW 252//sys DeleteFile(path *uint16) (err error) = DeleteFileW 253//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW 254//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW 255//sys SetEndOfFile(handle Handle) (err error) 256//sys GetSystemTimeAsFileTime(time *Filetime) 257//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] 258//sys createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) = CreateIoCompletionPort 259//sys getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) = GetQueuedCompletionStatus 260//sys postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) = PostQueuedCompletionStatus 261//sys CancelIo(s Handle) (err error) 262//sys CancelIoEx(s Handle, o *Overlapped) (err error) 263//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 264//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 265//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) 266//sys TerminateProcess(handle Handle, exitcode uint32) (err error) 267//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) 268//sys getStartupInfo(startupInfo *StartupInfo) = GetStartupInfoW 269//sys GetCurrentProcess() (pseudoHandle Handle, err error) 270//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) 271//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) 272//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] 273//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW 274//sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) 275//sys GetFileType(filehandle Handle) (n uint32, err error) 276//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW 277//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext 278//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom 279//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW 280//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW 281//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW 282//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW 283//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) 284//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW 285//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW 286//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW 287//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW 288//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW 289//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0] 290//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) 291//sys FlushFileBuffers(handle Handle) (err error) 292//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW 293//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW 294//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW 295//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW 296//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) 297//sys UnmapViewOfFile(addr uintptr) (err error) 298//sys FlushViewOfFile(addr uintptr, length uintptr) (err error) 299//sys VirtualLock(addr uintptr, length uintptr) (err error) 300//sys VirtualUnlock(addr uintptr, length uintptr) (err error) 301//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile 302//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW 303//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW 304//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore 305//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore 306//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore 307//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore 308//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain 309//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain 310//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext 311//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext 312//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy 313//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW 314//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey 315//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 316//sys regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW 317//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW 318//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId 319//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode 320//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW 321//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW 322//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot 323//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW 324//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW 325//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) 326// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. 327//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW 328//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW 329//sys initializeProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList 330//sys deleteProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST) = DeleteProcThreadAttributeList 331//sys updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute 332//sys getFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) [n == 0 || n >= filePathSize] = kernel32.GetFinalPathNameByHandleW 333 334// syscall interface implementation for other packages 335 336func makeInheritSa() *SecurityAttributes { 337 var sa SecurityAttributes 338 sa.Length = uint32(unsafe.Sizeof(sa)) 339 sa.InheritHandle = 1 340 return &sa 341} 342 343func Open(path string, mode int, perm uint32) (fd Handle, err error) { 344 if len(path) == 0 { 345 return InvalidHandle, ERROR_FILE_NOT_FOUND 346 } 347 pathp, err := UTF16PtrFromString(path) 348 if err != nil { 349 return InvalidHandle, err 350 } 351 var access uint32 352 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) { 353 case O_RDONLY: 354 access = GENERIC_READ 355 case O_WRONLY: 356 access = GENERIC_WRITE 357 case O_RDWR: 358 access = GENERIC_READ | GENERIC_WRITE 359 } 360 if mode&O_CREAT != 0 { 361 access |= GENERIC_WRITE 362 } 363 if mode&O_APPEND != 0 { 364 access &^= GENERIC_WRITE 365 access |= FILE_APPEND_DATA 366 } 367 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE) 368 var sa *SecurityAttributes 369 if mode&O_CLOEXEC == 0 { 370 sa = makeInheritSa() 371 } 372 var createmode uint32 373 switch { 374 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): 375 createmode = CREATE_NEW 376 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): 377 createmode = CREATE_ALWAYS 378 case mode&O_CREAT == O_CREAT: 379 createmode = OPEN_ALWAYS 380 case mode&O_TRUNC == O_TRUNC: 381 createmode = TRUNCATE_EXISTING 382 default: 383 createmode = OPEN_EXISTING 384 } 385 var attrs uint32 = FILE_ATTRIBUTE_NORMAL 386 if perm&S_IWRITE == 0 { 387 attrs = FILE_ATTRIBUTE_READONLY 388 if createmode == CREATE_ALWAYS { 389 // We have been asked to create a read-only file. 390 // If the file already exists, the semantics of 391 // the Unix open system call is to preserve the 392 // existing permissions. If we pass CREATE_ALWAYS 393 // and FILE_ATTRIBUTE_READONLY to CreateFile, 394 // and the file already exists, CreateFile will 395 // change the file permissions. 396 // Avoid that to preserve the Unix semantics. 397 h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) 398 switch e { 399 case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND: 400 // File does not exist. These are the same 401 // errors as Errno.Is checks for ErrNotExist. 402 // Carry on to create the file. 403 default: 404 // Success or some different error. 405 return h, e 406 } 407 } 408 } 409 if createmode == OPEN_EXISTING && access == GENERIC_READ { 410 // Necessary for opening directory handles. 411 attrs |= FILE_FLAG_BACKUP_SEMANTICS 412 } 413 if mode&O_SYNC != 0 { 414 const _FILE_FLAG_WRITE_THROUGH = 0x80000000 415 attrs |= _FILE_FLAG_WRITE_THROUGH 416 } 417 return CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) 418} 419 420func Read(fd Handle, p []byte) (n int, err error) { 421 var done uint32 422 e := ReadFile(fd, p, &done, nil) 423 if e != nil { 424 if e == ERROR_BROKEN_PIPE { 425 // NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin 426 return 0, nil 427 } 428 return 0, e 429 } 430 return int(done), nil 431} 432 433func Write(fd Handle, p []byte) (n int, err error) { 434 var done uint32 435 e := WriteFile(fd, p, &done, nil) 436 if e != nil { 437 return 0, e 438 } 439 return int(done), nil 440} 441 442func ReadFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error { 443 err := readFile(fd, p, done, overlapped) 444 if race.Enabled { 445 if *done > 0 { 446 race.WriteRange(unsafe.Pointer(&p[0]), int(*done)) 447 } 448 race.Acquire(unsafe.Pointer(&ioSync)) 449 } 450 if msan.Enabled && *done > 0 { 451 msan.Write(unsafe.Pointer(&p[0]), uintptr(*done)) 452 } 453 if asan.Enabled && *done > 0 { 454 asan.Write(unsafe.Pointer(&p[0]), uintptr(*done)) 455 } 456 return err 457} 458 459func WriteFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error { 460 if race.Enabled { 461 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 462 } 463 err := writeFile(fd, p, done, overlapped) 464 if race.Enabled && *done > 0 { 465 race.ReadRange(unsafe.Pointer(&p[0]), int(*done)) 466 } 467 if msan.Enabled && *done > 0 { 468 msan.Read(unsafe.Pointer(&p[0]), uintptr(*done)) 469 } 470 if asan.Enabled && *done > 0 { 471 asan.Read(unsafe.Pointer(&p[0]), uintptr(*done)) 472 } 473 return err 474} 475 476var ioSync int64 477 478var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx") 479 480const ptrSize = unsafe.Sizeof(uintptr(0)) 481 482// setFilePointerEx calls SetFilePointerEx. 483// See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointerex 484func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error { 485 var e1 Errno 486 if unsafe.Sizeof(uintptr(0)) == 8 { 487 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0) 488 } else { 489 // Different 32-bit systems disgaree about whether distToMove starts 8-byte aligned. 490 switch runtime.GOARCH { 491 default: 492 panic("unsupported 32-bit architecture") 493 case "386": 494 // distToMove is a LARGE_INTEGER, which is 64 bits. 495 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0) 496 case "arm": 497 // distToMove must be 8-byte aligned per ARM calling convention 498 // https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions#stage-c-assignment-of-arguments-to-registers-and-stack 499 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence)) 500 } 501 } 502 if e1 != 0 { 503 return errnoErr(e1) 504 } 505 return nil 506} 507 508func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) { 509 var w uint32 510 switch whence { 511 case 0: 512 w = FILE_BEGIN 513 case 1: 514 w = FILE_CURRENT 515 case 2: 516 w = FILE_END 517 } 518 err = setFilePointerEx(fd, offset, &newoffset, w) 519 return 520} 521 522func Close(fd Handle) (err error) { 523 return CloseHandle(fd) 524} 525 526var ( 527 Stdin = getStdHandle(STD_INPUT_HANDLE) 528 Stdout = getStdHandle(STD_OUTPUT_HANDLE) 529 Stderr = getStdHandle(STD_ERROR_HANDLE) 530) 531 532func getStdHandle(h int) (fd Handle) { 533 r, _ := GetStdHandle(h) 534 return r 535} 536 537const ImplementsGetwd = true 538 539func Getwd() (wd string, err error) { 540 b := make([]uint16, 300) 541 // The path of the current directory may not fit in the initial 300-word 542 // buffer when long path support is enabled. The current directory may also 543 // change between subsequent calls of GetCurrentDirectory. As a result, we 544 // need to retry the call in a loop until the current directory fits, each 545 // time with a bigger buffer. 546 for { 547 n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) 548 if e != nil { 549 return "", e 550 } 551 if int(n) <= len(b) { 552 return UTF16ToString(b[:n]), nil 553 } 554 b = make([]uint16, n) 555 } 556} 557 558func Chdir(path string) (err error) { 559 pathp, err := UTF16PtrFromString(path) 560 if err != nil { 561 return err 562 } 563 return SetCurrentDirectory(pathp) 564} 565 566func Mkdir(path string, mode uint32) (err error) { 567 pathp, err := UTF16PtrFromString(path) 568 if err != nil { 569 return err 570 } 571 return CreateDirectory(pathp, nil) 572} 573 574func Rmdir(path string) (err error) { 575 pathp, err := UTF16PtrFromString(path) 576 if err != nil { 577 return err 578 } 579 return RemoveDirectory(pathp) 580} 581 582func Unlink(path string) (err error) { 583 pathp, err := UTF16PtrFromString(path) 584 if err != nil { 585 return err 586 } 587 return DeleteFile(pathp) 588} 589 590func Rename(oldpath, newpath string) (err error) { 591 from, err := UTF16PtrFromString(oldpath) 592 if err != nil { 593 return err 594 } 595 to, err := UTF16PtrFromString(newpath) 596 if err != nil { 597 return err 598 } 599 return MoveFile(from, to) 600} 601 602func ComputerName() (name string, err error) { 603 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1 604 b := make([]uint16, n) 605 e := GetComputerName(&b[0], &n) 606 if e != nil { 607 return "", e 608 } 609 return UTF16ToString(b[:n]), nil 610} 611 612func Ftruncate(fd Handle, length int64) (err error) { 613 curoffset, e := Seek(fd, 0, 1) 614 if e != nil { 615 return e 616 } 617 defer Seek(fd, curoffset, 0) 618 _, e = Seek(fd, length, 0) 619 if e != nil { 620 return e 621 } 622 e = SetEndOfFile(fd) 623 if e != nil { 624 return e 625 } 626 return nil 627} 628 629func Gettimeofday(tv *Timeval) (err error) { 630 var ft Filetime 631 GetSystemTimeAsFileTime(&ft) 632 *tv = NsecToTimeval(ft.Nanoseconds()) 633 return nil 634} 635 636func Pipe(p []Handle) (err error) { 637 if len(p) != 2 { 638 return EINVAL 639 } 640 var r, w Handle 641 e := CreatePipe(&r, &w, makeInheritSa(), 0) 642 if e != nil { 643 return e 644 } 645 p[0] = r 646 p[1] = w 647 return nil 648} 649 650func Utimes(path string, tv []Timeval) (err error) { 651 if len(tv) != 2 { 652 return EINVAL 653 } 654 pathp, e := UTF16PtrFromString(path) 655 if e != nil { 656 return e 657 } 658 h, e := CreateFile(pathp, 659 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 660 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) 661 if e != nil { 662 return e 663 } 664 defer Close(h) 665 a := Filetime{} 666 w := Filetime{} 667 if tv[0].Nanoseconds() != 0 { 668 a = NsecToFiletime(tv[0].Nanoseconds()) 669 } 670 if tv[0].Nanoseconds() != 0 { 671 w = NsecToFiletime(tv[1].Nanoseconds()) 672 } 673 return SetFileTime(h, nil, &a, &w) 674} 675 676// This matches the value in os/file_windows.go. 677const _UTIME_OMIT = -1 678 679func UtimesNano(path string, ts []Timespec) (err error) { 680 if len(ts) != 2 { 681 return EINVAL 682 } 683 pathp, e := UTF16PtrFromString(path) 684 if e != nil { 685 return e 686 } 687 h, e := CreateFile(pathp, 688 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 689 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) 690 if e != nil { 691 return e 692 } 693 defer Close(h) 694 a := Filetime{} 695 w := Filetime{} 696 if ts[0].Nsec != _UTIME_OMIT { 697 a = NsecToFiletime(TimespecToNsec(ts[0])) 698 } 699 if ts[1].Nsec != _UTIME_OMIT { 700 w = NsecToFiletime(TimespecToNsec(ts[1])) 701 } 702 return SetFileTime(h, nil, &a, &w) 703} 704 705func Fsync(fd Handle) (err error) { 706 return FlushFileBuffers(fd) 707} 708 709func Chmod(path string, mode uint32) (err error) { 710 p, e := UTF16PtrFromString(path) 711 if e != nil { 712 return e 713 } 714 attrs, e := GetFileAttributes(p) 715 if e != nil { 716 return e 717 } 718 if mode&S_IWRITE != 0 { 719 attrs &^= FILE_ATTRIBUTE_READONLY 720 } else { 721 attrs |= FILE_ATTRIBUTE_READONLY 722 } 723 return SetFileAttributes(p, attrs) 724} 725 726func LoadCancelIoEx() error { 727 return procCancelIoEx.Find() 728} 729 730func LoadSetFileCompletionNotificationModes() error { 731 return procSetFileCompletionNotificationModes.Find() 732} 733 734// net api calls 735 736const socket_error = uintptr(^uint32(0)) 737 738//sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup 739//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup 740//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 741//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket 742//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt 743//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt 744//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind 745//sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect 746//sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname 747//sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername 748//sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen 749//sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown 750//sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket 751//sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx 752//sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs 753//sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv 754//sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend 755//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 756//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 757//sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname 758//sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname 759//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs 760//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname 761//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W 762//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree 763//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W 764//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW 765//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW 766//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry 767//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo 768//sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes 769//sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW 770 771// For testing: clients can set this flag to force 772// creation of IPv6 sockets to return [EAFNOSUPPORT]. 773var SocketDisableIPv6 bool 774 775type RawSockaddrInet4 struct { 776 Family uint16 777 Port uint16 778 Addr [4]byte /* in_addr */ 779 Zero [8]uint8 780} 781 782type RawSockaddrInet6 struct { 783 Family uint16 784 Port uint16 785 Flowinfo uint32 786 Addr [16]byte /* in6_addr */ 787 Scope_id uint32 788} 789 790type RawSockaddr struct { 791 Family uint16 792 Data [14]int8 793} 794 795type RawSockaddrAny struct { 796 Addr RawSockaddr 797 Pad [100]int8 798} 799 800type Sockaddr interface { 801 sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs 802} 803 804type SockaddrInet4 struct { 805 Port int 806 Addr [4]byte 807 raw RawSockaddrInet4 808} 809 810func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { 811 if sa.Port < 0 || sa.Port > 0xFFFF { 812 return nil, 0, EINVAL 813 } 814 sa.raw.Family = AF_INET 815 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 816 p[0] = byte(sa.Port >> 8) 817 p[1] = byte(sa.Port) 818 sa.raw.Addr = sa.Addr 819 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil 820} 821 822type SockaddrInet6 struct { 823 Port int 824 ZoneId uint32 825 Addr [16]byte 826 raw RawSockaddrInet6 827} 828 829func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { 830 if sa.Port < 0 || sa.Port > 0xFFFF { 831 return nil, 0, EINVAL 832 } 833 sa.raw.Family = AF_INET6 834 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 835 p[0] = byte(sa.Port >> 8) 836 p[1] = byte(sa.Port) 837 sa.raw.Scope_id = sa.ZoneId 838 sa.raw.Addr = sa.Addr 839 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil 840} 841 842type RawSockaddrUnix struct { 843 Family uint16 844 Path [UNIX_PATH_MAX]int8 845} 846 847type SockaddrUnix struct { 848 Name string 849 raw RawSockaddrUnix 850} 851 852func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { 853 name := sa.Name 854 n := len(name) 855 if n > len(sa.raw.Path) { 856 return nil, 0, EINVAL 857 } 858 if n == len(sa.raw.Path) && name[0] != '@' { 859 return nil, 0, EINVAL 860 } 861 sa.raw.Family = AF_UNIX 862 for i := 0; i < n; i++ { 863 sa.raw.Path[i] = int8(name[i]) 864 } 865 // length is family (uint16), name, NUL. 866 sl := int32(2) 867 if n > 0 { 868 sl += int32(n) + 1 869 } 870 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { 871 // Check sl > 3 so we don't change unnamed socket behavior. 872 sa.raw.Path[0] = 0 873 // Don't count trailing NUL for abstract address. 874 sl-- 875 } 876 877 return unsafe.Pointer(&sa.raw), sl, nil 878} 879 880func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { 881 switch rsa.Addr.Family { 882 case AF_UNIX: 883 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 884 sa := new(SockaddrUnix) 885 if pp.Path[0] == 0 { 886 // "Abstract" Unix domain socket. 887 // Rewrite leading NUL as @ for textual display. 888 // (This is the standard convention.) 889 // Not friendly to overwrite in place, 890 // but the callers below don't care. 891 pp.Path[0] = '@' 892 } 893 894 // Assume path ends at NUL. 895 // This is not technically the Linux semantics for 896 // abstract Unix domain sockets--they are supposed 897 // to be uninterpreted fixed-size binary blobs--but 898 // everyone uses this convention. 899 n := 0 900 for n < len(pp.Path) && pp.Path[n] != 0 { 901 n++ 902 } 903 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 904 return sa, nil 905 906 case AF_INET: 907 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 908 sa := new(SockaddrInet4) 909 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 910 sa.Port = int(p[0])<<8 + int(p[1]) 911 sa.Addr = pp.Addr 912 return sa, nil 913 914 case AF_INET6: 915 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 916 sa := new(SockaddrInet6) 917 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 918 sa.Port = int(p[0])<<8 + int(p[1]) 919 sa.ZoneId = pp.Scope_id 920 sa.Addr = pp.Addr 921 return sa, nil 922 } 923 return nil, EAFNOSUPPORT 924} 925 926func Socket(domain, typ, proto int) (fd Handle, err error) { 927 if domain == AF_INET6 && SocketDisableIPv6 { 928 return InvalidHandle, EAFNOSUPPORT 929 } 930 return socket(int32(domain), int32(typ), int32(proto)) 931} 932 933func SetsockoptInt(fd Handle, level, opt int, value int) (err error) { 934 v := int32(value) 935 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v))) 936} 937 938func Bind(fd Handle, sa Sockaddr) (err error) { 939 ptr, n, err := sa.sockaddr() 940 if err != nil { 941 return err 942 } 943 return bind(fd, ptr, n) 944} 945 946func Connect(fd Handle, sa Sockaddr) (err error) { 947 ptr, n, err := sa.sockaddr() 948 if err != nil { 949 return err 950 } 951 return connect(fd, ptr, n) 952} 953 954func Getsockname(fd Handle) (sa Sockaddr, err error) { 955 var rsa RawSockaddrAny 956 l := int32(unsafe.Sizeof(rsa)) 957 if err = getsockname(fd, &rsa, &l); err != nil { 958 return 959 } 960 return rsa.Sockaddr() 961} 962 963func Getpeername(fd Handle) (sa Sockaddr, err error) { 964 var rsa RawSockaddrAny 965 l := int32(unsafe.Sizeof(rsa)) 966 if err = getpeername(fd, &rsa, &l); err != nil { 967 return 968 } 969 return rsa.Sockaddr() 970} 971 972func Listen(s Handle, n int) (err error) { 973 return listen(s, int32(n)) 974} 975 976func Shutdown(fd Handle, how int) (err error) { 977 return shutdown(fd, int32(how)) 978} 979 980func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) { 981 var rsa unsafe.Pointer 982 var len int32 983 if to != nil { 984 rsa, len, err = to.sockaddr() 985 if err != nil { 986 return err 987 } 988 } 989 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))) 990 if r1 == socket_error { 991 if e1 != 0 { 992 err = errnoErr(e1) 993 } else { 994 err = EINVAL 995 } 996 } 997 return err 998} 999 1000func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { 1001 rsa, len, err := to.sockaddr() 1002 if err != nil { 1003 return err 1004 } 1005 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))) 1006 if r1 == socket_error { 1007 if e1 != 0 { 1008 err = errnoErr(e1) 1009 } else { 1010 err = EINVAL 1011 } 1012 } 1013 return err 1014} 1015 1016func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { 1017 rsa, len, err := to.sockaddr() 1018 if err != nil { 1019 return err 1020 } 1021 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))) 1022 if r1 == socket_error { 1023 if e1 != 0 { 1024 err = errnoErr(e1) 1025 } else { 1026 err = EINVAL 1027 } 1028 } 1029 return err 1030} 1031 1032func LoadGetAddrInfo() error { 1033 return procGetAddrInfoW.Find() 1034} 1035 1036var connectExFunc struct { 1037 once sync.Once 1038 addr uintptr 1039 err error 1040} 1041 1042func LoadConnectEx() error { 1043 connectExFunc.once.Do(func() { 1044 var s Handle 1045 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 1046 if connectExFunc.err != nil { 1047 return 1048 } 1049 defer CloseHandle(s) 1050 var n uint32 1051 connectExFunc.err = WSAIoctl(s, 1052 SIO_GET_EXTENSION_FUNCTION_POINTER, 1053 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)), 1054 uint32(unsafe.Sizeof(WSAID_CONNECTEX)), 1055 (*byte)(unsafe.Pointer(&connectExFunc.addr)), 1056 uint32(unsafe.Sizeof(connectExFunc.addr)), 1057 &n, nil, 0) 1058 }) 1059 return connectExFunc.err 1060} 1061 1062func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) { 1063 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) 1064 if r1 == 0 { 1065 if e1 != 0 { 1066 err = error(e1) 1067 } else { 1068 err = EINVAL 1069 } 1070 } 1071 return 1072} 1073 1074func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error { 1075 err := LoadConnectEx() 1076 if err != nil { 1077 return errorspkg.New("failed to find ConnectEx: " + err.Error()) 1078 } 1079 ptr, n, err := sa.sockaddr() 1080 if err != nil { 1081 return err 1082 } 1083 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) 1084} 1085 1086// Invented structures to support what package os expects. 1087type Rusage struct { 1088 CreationTime Filetime 1089 ExitTime Filetime 1090 KernelTime Filetime 1091 UserTime Filetime 1092} 1093 1094type WaitStatus struct { 1095 ExitCode uint32 1096} 1097 1098func (w WaitStatus) Exited() bool { return true } 1099 1100func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) } 1101 1102func (w WaitStatus) Signal() Signal { return -1 } 1103 1104func (w WaitStatus) CoreDump() bool { return false } 1105 1106func (w WaitStatus) Stopped() bool { return false } 1107 1108func (w WaitStatus) Continued() bool { return false } 1109 1110func (w WaitStatus) StopSignal() Signal { return -1 } 1111 1112func (w WaitStatus) Signaled() bool { return false } 1113 1114func (w WaitStatus) TrapCause() int { return -1 } 1115 1116// Timespec is an invented structure on Windows, but here for 1117// consistency with the syscall package for other operating systems. 1118type Timespec struct { 1119 Sec int64 1120 Nsec int64 1121} 1122 1123func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } 1124 1125func NsecToTimespec(nsec int64) (ts Timespec) { 1126 ts.Sec = nsec / 1e9 1127 ts.Nsec = nsec % 1e9 1128 return 1129} 1130 1131// TODO(brainman): fix all needed for net 1132 1133func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS } 1134func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) { 1135 return 0, nil, EWINDOWS 1136} 1137func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS } 1138func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS } 1139 1140// The Linger struct is wrong but we only noticed after Go 1. 1141// sysLinger is the real system call structure. 1142 1143// BUG(brainman): The definition of Linger is not appropriate for direct use 1144// with Setsockopt and Getsockopt. 1145// Use SetsockoptLinger instead. 1146 1147type Linger struct { 1148 Onoff int32 1149 Linger int32 1150} 1151 1152type sysLinger struct { 1153 Onoff uint16 1154 Linger uint16 1155} 1156 1157type IPMreq struct { 1158 Multiaddr [4]byte /* in_addr */ 1159 Interface [4]byte /* in_addr */ 1160} 1161 1162type IPv6Mreq struct { 1163 Multiaddr [16]byte /* in6_addr */ 1164 Interface uint32 1165} 1166 1167func GetsockoptInt(fd Handle, level, opt int) (int, error) { 1168 optval := int32(0) 1169 optlen := int32(unsafe.Sizeof(optval)) 1170 err := Getsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&optval)), &optlen) 1171 return int(optval), err 1172} 1173 1174func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { 1175 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)} 1176 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys))) 1177} 1178 1179func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { 1180 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) 1181} 1182func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { 1183 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) 1184} 1185func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS } 1186 1187func Getpid() (pid int) { return int(getCurrentProcessId()) } 1188 1189func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) { 1190 // NOTE(rsc): The Win32finddata struct is wrong for the system call: 1191 // the two paths are each one uint16 short. Use the correct struct, 1192 // a win32finddata1, and then copy the results out. 1193 // There is no loss of expressivity here, because the final 1194 // uint16, if it is used, is supposed to be a NUL, and Go doesn't need that. 1195 // For Go 1.1, we might avoid the allocation of win32finddata1 here 1196 // by adding a final Bug [2]uint16 field to the struct and then 1197 // adjusting the fields in the result directly. 1198 var data1 win32finddata1 1199 handle, err = findFirstFile1(name, &data1) 1200 if err == nil { 1201 copyFindData(data, &data1) 1202 } 1203 return 1204} 1205 1206func FindNextFile(handle Handle, data *Win32finddata) (err error) { 1207 var data1 win32finddata1 1208 err = findNextFile1(handle, &data1) 1209 if err == nil { 1210 copyFindData(data, &data1) 1211 } 1212 return 1213} 1214 1215func getProcessEntry(pid int) (*ProcessEntry32, error) { 1216 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 1217 if err != nil { 1218 return nil, err 1219 } 1220 defer CloseHandle(snapshot) 1221 var procEntry ProcessEntry32 1222 procEntry.Size = uint32(unsafe.Sizeof(procEntry)) 1223 if err = Process32First(snapshot, &procEntry); err != nil { 1224 return nil, err 1225 } 1226 for { 1227 if procEntry.ProcessID == uint32(pid) { 1228 return &procEntry, nil 1229 } 1230 err = Process32Next(snapshot, &procEntry) 1231 if err != nil { 1232 return nil, err 1233 } 1234 } 1235} 1236 1237func Getppid() (ppid int) { 1238 pe, err := getProcessEntry(Getpid()) 1239 if err != nil { 1240 return -1 1241 } 1242 return int(pe.ParentProcessID) 1243} 1244 1245func fdpath(fd Handle, buf []uint16) ([]uint16, error) { 1246 const ( 1247 FILE_NAME_NORMALIZED = 0 1248 VOLUME_NAME_DOS = 0 1249 ) 1250 for { 1251 n, err := getFinalPathNameByHandle(fd, &buf[0], uint32(len(buf)), FILE_NAME_NORMALIZED|VOLUME_NAME_DOS) 1252 if err == nil { 1253 buf = buf[:n] 1254 break 1255 } 1256 if err != _ERROR_NOT_ENOUGH_MEMORY { 1257 return nil, err 1258 } 1259 buf = append(buf, make([]uint16, n-uint32(len(buf)))...) 1260 } 1261 return buf, nil 1262} 1263 1264func Fchdir(fd Handle) (err error) { 1265 var buf [MAX_PATH + 1]uint16 1266 path, err := fdpath(fd, buf[:]) 1267 if err != nil { 1268 return err 1269 } 1270 // When using VOLUME_NAME_DOS, the path is always prefixed by "\\?\". 1271 // That prefix tells the Windows APIs to disable all string parsing and to send 1272 // the string that follows it straight to the file system. 1273 // Although SetCurrentDirectory and GetCurrentDirectory do support the "\\?\" prefix, 1274 // some other Windows APIs don't. If the prefix is not removed here, it will leak 1275 // to Getwd, and we don't want such a general-purpose function to always return a 1276 // path with the "\\?\" prefix after Fchdir is called. 1277 // The downside is that APIs that do support it will parse the path and try to normalize it, 1278 // when it's already normalized. 1279 if len(path) >= 4 && path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\' { 1280 path = path[4:] 1281 } 1282 return SetCurrentDirectory(&path[0]) 1283} 1284 1285// TODO(brainman): fix all needed for os 1286func Link(oldpath, newpath string) (err error) { return EWINDOWS } 1287func Symlink(path, link string) (err error) { return EWINDOWS } 1288 1289func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS } 1290func Chown(path string, uid int, gid int) (err error) { return EWINDOWS } 1291func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS } 1292func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS } 1293 1294func Getuid() (uid int) { return -1 } 1295func Geteuid() (euid int) { return -1 } 1296func Getgid() (gid int) { return -1 } 1297func Getegid() (egid int) { return -1 } 1298func Getgroups() (gids []int, err error) { return nil, EWINDOWS } 1299 1300type Signal int 1301 1302func (s Signal) Signal() {} 1303 1304func (s Signal) String() string { 1305 if 0 <= s && int(s) < len(signals) { 1306 str := signals[s] 1307 if str != "" { 1308 return str 1309 } 1310 } 1311 return "signal " + itoa.Itoa(int(s)) 1312} 1313 1314func LoadCreateSymbolicLink() error { 1315 return procCreateSymbolicLinkW.Find() 1316} 1317 1318// Readlink returns the destination of the named symbolic link. 1319func Readlink(path string, buf []byte) (n int, err error) { 1320 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING, 1321 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0) 1322 if err != nil { 1323 return -1, err 1324 } 1325 defer CloseHandle(fd) 1326 1327 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE) 1328 var bytesReturned uint32 1329 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil) 1330 if err != nil { 1331 return -1, err 1332 } 1333 1334 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0])) 1335 var s string 1336 switch rdb.ReparseTag { 1337 case IO_REPARSE_TAG_SYMLINK: 1338 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) 1339 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) 1340 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2]) 1341 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 { 1342 if len(s) >= 4 && s[:4] == `\??\` { 1343 s = s[4:] 1344 switch { 1345 case len(s) >= 2 && s[1] == ':': // \??\C:\foo\bar 1346 // do nothing 1347 case len(s) >= 4 && s[:4] == `UNC\`: // \??\UNC\foo\bar 1348 s = `\\` + s[4:] 1349 default: 1350 // unexpected; do nothing 1351 } 1352 } else { 1353 // unexpected; do nothing 1354 } 1355 } 1356 case _IO_REPARSE_TAG_MOUNT_POINT: 1357 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) 1358 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) 1359 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2]) 1360 if len(s) >= 4 && s[:4] == `\??\` { // \??\C:\foo\bar 1361 s = s[4:] 1362 } else { 1363 // unexpected; do nothing 1364 } 1365 default: 1366 // the path is not a symlink or junction but another type of reparse 1367 // point 1368 return -1, ENOENT 1369 } 1370 n = copy(buf, []byte(s)) 1371 1372 return n, nil 1373} 1374 1375// Deprecated: CreateIoCompletionPort has the wrong function signature. Use x/sys/windows.CreateIoCompletionPort. 1376func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) { 1377 return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt) 1378} 1379 1380// Deprecated: GetQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.GetQueuedCompletionStatus. 1381func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error { 1382 var ukey uintptr 1383 var pukey *uintptr 1384 if key != nil { 1385 ukey = uintptr(*key) 1386 pukey = &ukey 1387 } 1388 err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout) 1389 if key != nil { 1390 *key = uint32(ukey) 1391 if uintptr(*key) != ukey && err == nil { 1392 err = errorspkg.New("GetQueuedCompletionStatus returned key overflow") 1393 } 1394 } 1395 return err 1396} 1397 1398// Deprecated: PostQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.PostQueuedCompletionStatus. 1399func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error { 1400 return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped) 1401} 1402 1403// newProcThreadAttributeList allocates new PROC_THREAD_ATTRIBUTE_LIST, with 1404// the requested maximum number of attributes, which must be cleaned up by 1405// deleteProcThreadAttributeList. 1406func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LIST, error) { 1407 var size uintptr 1408 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size) 1409 if err != ERROR_INSUFFICIENT_BUFFER { 1410 if err == nil { 1411 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList") 1412 } 1413 return nil, err 1414 } 1415 // size is guaranteed to be ≥1 by initializeProcThreadAttributeList. 1416 al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0])) 1417 err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size) 1418 if err != nil { 1419 return nil, err 1420 } 1421 return al, nil 1422} 1423 1424// RegEnumKeyEx enumerates the subkeys of an open registry key. 1425// Each call retrieves information about one subkey. name is 1426// a buffer that should be large enough to hold the name of the 1427// subkey plus a null terminating character. nameLen is its 1428// length. On return, nameLen will contain the actual length of the 1429// subkey. 1430// 1431// Should name not be large enough to hold the subkey, this function 1432// will return ERROR_MORE_DATA, and must be called again with an 1433// appropriately sized buffer. 1434// 1435// reserved must be nil. class and classLen behave like name and nameLen 1436// but for the class of the subkey, except that they are optional. 1437// lastWriteTime, if not nil, will be populated with the time the subkey 1438// was last written. 1439// 1440// The caller must enumerate all subkeys in order. That is 1441// RegEnumKeyEx must be called with index starting at 0, incrementing 1442// the index until the function returns ERROR_NO_MORE_ITEMS, or with 1443// the index of the last subkey (obtainable from RegQueryInfoKey), 1444// decrementing until index 0 is enumerated. 1445// 1446// Successive calls to this API must happen on the same OS thread, 1447// so call [runtime.LockOSThread] before calling this function. 1448func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { 1449 return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime) 1450} 1451 1452func GetStartupInfo(startupInfo *StartupInfo) error { 1453 getStartupInfo(startupInfo) 1454 return nil 1455} 1456