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