github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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 "sync" 12 "unicode/utf16" 13 "unsafe" 14 ) 15 16 type Handle uintptr 17 18 const InvalidHandle = ^Handle(0) 19 20 // StringToUTF16 is deprecated. Use UTF16FromString instead. 21 // If s contains a NUL byte this function panics instead of 22 // returning an error. 23 func StringToUTF16(s string) []uint16 { 24 a, err := UTF16FromString(s) 25 if err != nil { 26 panic("syscall: string with NUL passed to StringToUTF16") 27 } 28 return a 29 } 30 31 // UTF16FromString returns the UTF-16 encoding of the UTF-8 string 32 // s, with a terminating NUL added. If s contains a NUL byte at any 33 // location, it returns (nil, EINVAL). 34 func UTF16FromString(s string) ([]uint16, error) { 35 for i := 0; i < len(s); i++ { 36 if s[i] == 0 { 37 return nil, EINVAL 38 } 39 } 40 return utf16.Encode([]rune(s + "\x00")), nil 41 } 42 43 // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, 44 // with a terminating NUL removed. 45 func UTF16ToString(s []uint16) string { 46 for i, v := range s { 47 if v == 0 { 48 s = s[0:i] 49 break 50 } 51 } 52 return string(utf16.Decode(s)) 53 } 54 55 // StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead. 56 // If s contains a NUL byte this function panics instead of 57 // returning an error. 58 func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } 59 60 // UTF16PtrFromString returns pointer to the UTF-16 encoding of 61 // the UTF-8 string s, with a terminating NUL added. If s 62 // contains a NUL byte at any location, it returns (nil, EINVAL). 63 func UTF16PtrFromString(s string) (*uint16, error) { 64 a, err := UTF16FromString(s) 65 if err != nil { 66 return nil, err 67 } 68 return &a[0], nil 69 } 70 71 func Getpagesize() int { return 4096 } 72 73 // Errno is the Windows error number. 74 type Errno uintptr 75 76 func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) } 77 78 func (e Errno) Error() string { 79 // deal with special go errors 80 idx := int(e - APPLICATION_ERROR) 81 if 0 <= idx && idx < len(errors) { 82 return errors[idx] 83 } 84 // ask windows for the remaining errors 85 var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS 86 b := make([]uint16, 300) 87 n, err := FormatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil) 88 if err != nil { 89 n, err = FormatMessage(flags, 0, uint32(e), 0, b, nil) 90 if err != nil { 91 return "winapi error #" + itoa(int(e)) 92 } 93 } 94 // trim terminating \r and \n 95 for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { 96 } 97 return string(utf16.Decode(b[:n])) 98 } 99 100 func (e Errno) Temporary() bool { 101 return e == EINTR || e == EMFILE || e.Timeout() 102 } 103 104 func (e Errno) Timeout() bool { 105 return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT 106 } 107 108 // Converts a Go function to a function pointer conforming 109 // to the stdcall calling convention. This is useful when 110 // interoperating with Windows code requiring callbacks. 111 // Implemented in ../runtime/syscall_windows.goc 112 func NewCallback(fn interface{}) uintptr 113 114 // windows api calls 115 116 //sys GetLastError() (lasterr error) 117 //sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW 118 //sys FreeLibrary(handle Handle) (err error) 119 //sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) 120 //sys GetVersion() (ver uint32, err error) 121 //sys FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW 122 //sys ExitProcess(exitcode uint32) 123 //sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW 124 //sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) 125 //sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) 126 //sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff] 127 //sys CloseHandle(handle Handle) (err error) 128 //sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle] 129 //sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW 130 //sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW 131 //sys FindClose(handle Handle) (err error) 132 //sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) 133 //sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW 134 //sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW 135 //sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW 136 //sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW 137 //sys DeleteFile(path *uint16) (err error) = DeleteFileW 138 //sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW 139 //sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW 140 //sys SetEndOfFile(handle Handle) (err error) 141 //sys GetSystemTimeAsFileTime(time *Filetime) 142 //sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] 143 //sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) 144 //sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) 145 //sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) 146 //sys CancelIo(s Handle) (err error) 147 //sys CancelIoEx(s Handle, o *Overlapped) (err error) 148 //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 149 //sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) 150 //sys TerminateProcess(handle Handle, exitcode uint32) (err error) 151 //sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) 152 //sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW 153 //sys GetCurrentProcess() (pseudoHandle Handle, err error) 154 //sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) 155 //sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) 156 //sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] 157 //sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW 158 //sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) 159 //sys GetFileType(filehandle Handle) (n uint32, err error) 160 //sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW 161 //sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext 162 //sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom 163 //sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW 164 //sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW 165 //sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW 166 //sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW 167 //sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) 168 //sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW 169 //sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW 170 //sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW 171 //sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW 172 //sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW 173 //sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0] 174 //sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) 175 //sys FlushFileBuffers(handle Handle) (err error) 176 //sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW 177 //sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW 178 //sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW 179 //sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW 180 //sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) 181 //sys UnmapViewOfFile(addr uintptr) (err error) 182 //sys FlushViewOfFile(addr uintptr, length uintptr) (err error) 183 //sys VirtualLock(addr uintptr, length uintptr) (err error) 184 //sys VirtualUnlock(addr uintptr, length uintptr) (err error) 185 //sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile 186 //sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW 187 //sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW 188 //sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore 189 //sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore 190 //sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore 191 //sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore 192 //sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain 193 //sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain 194 //sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext 195 //sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext 196 //sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy 197 //sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW 198 //sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey 199 //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 200 //sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW 201 //sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW 202 //sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId 203 //sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode 204 //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW 205 //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW 206 207 // syscall interface implementation for other packages 208 209 func Exit(code int) { ExitProcess(uint32(code)) } 210 211 func makeInheritSa() *SecurityAttributes { 212 var sa SecurityAttributes 213 sa.Length = uint32(unsafe.Sizeof(sa)) 214 sa.InheritHandle = 1 215 return &sa 216 } 217 218 func Open(path string, mode int, perm uint32) (fd Handle, err error) { 219 if len(path) == 0 { 220 return InvalidHandle, ERROR_FILE_NOT_FOUND 221 } 222 pathp, err := UTF16PtrFromString(path) 223 if err != nil { 224 return InvalidHandle, err 225 } 226 var access uint32 227 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) { 228 case O_RDONLY: 229 access = GENERIC_READ 230 case O_WRONLY: 231 access = GENERIC_WRITE 232 case O_RDWR: 233 access = GENERIC_READ | GENERIC_WRITE 234 } 235 if mode&O_CREAT != 0 { 236 access |= GENERIC_WRITE 237 } 238 if mode&O_APPEND != 0 { 239 access &^= GENERIC_WRITE 240 access |= FILE_APPEND_DATA 241 } 242 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE) 243 var sa *SecurityAttributes 244 if mode&O_CLOEXEC == 0 { 245 sa = makeInheritSa() 246 } 247 var createmode uint32 248 switch { 249 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): 250 createmode = CREATE_NEW 251 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): 252 createmode = CREATE_ALWAYS 253 case mode&O_CREAT == O_CREAT: 254 createmode = OPEN_ALWAYS 255 case mode&O_TRUNC == O_TRUNC: 256 createmode = TRUNCATE_EXISTING 257 default: 258 createmode = OPEN_EXISTING 259 } 260 h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0) 261 return h, e 262 } 263 264 func Read(fd Handle, p []byte) (n int, err error) { 265 var done uint32 266 e := ReadFile(fd, p, &done, nil) 267 if e != nil { 268 if e == ERROR_BROKEN_PIPE { 269 // NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin 270 return 0, nil 271 } 272 return 0, e 273 } 274 if raceenabled { 275 if done > 0 { 276 raceWriteRange(unsafe.Pointer(&p[0]), int(done)) 277 } 278 raceAcquire(unsafe.Pointer(&ioSync)) 279 } 280 return int(done), nil 281 } 282 283 func Write(fd Handle, p []byte) (n int, err error) { 284 if raceenabled { 285 raceReleaseMerge(unsafe.Pointer(&ioSync)) 286 } 287 var done uint32 288 e := WriteFile(fd, p, &done, nil) 289 if e != nil { 290 return 0, e 291 } 292 if raceenabled && done > 0 { 293 raceReadRange(unsafe.Pointer(&p[0]), int(done)) 294 } 295 return int(done), nil 296 } 297 298 var ioSync int64 299 300 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) { 301 var w uint32 302 switch whence { 303 case 0: 304 w = FILE_BEGIN 305 case 1: 306 w = FILE_CURRENT 307 case 2: 308 w = FILE_END 309 } 310 hi := int32(offset >> 32) 311 lo := int32(offset) 312 // use GetFileType to check pipe, pipe can't do seek 313 ft, _ := GetFileType(fd) 314 if ft == FILE_TYPE_PIPE { 315 return 0, EPIPE 316 } 317 rlo, e := SetFilePointer(fd, lo, &hi, w) 318 if e != nil { 319 return 0, e 320 } 321 return int64(hi)<<32 + int64(rlo), nil 322 } 323 324 func Close(fd Handle) (err error) { 325 return CloseHandle(fd) 326 } 327 328 var ( 329 Stdin = getStdHandle(STD_INPUT_HANDLE) 330 Stdout = getStdHandle(STD_OUTPUT_HANDLE) 331 Stderr = getStdHandle(STD_ERROR_HANDLE) 332 ) 333 334 func getStdHandle(h int) (fd Handle) { 335 r, _ := GetStdHandle(h) 336 CloseOnExec(r) 337 return r 338 } 339 340 const ImplementsGetwd = true 341 342 func Getwd() (wd string, err error) { 343 b := make([]uint16, 300) 344 n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) 345 if e != nil { 346 return "", e 347 } 348 return string(utf16.Decode(b[0:n])), nil 349 } 350 351 func Chdir(path string) (err error) { 352 pathp, err := UTF16PtrFromString(path) 353 if err != nil { 354 return err 355 } 356 return SetCurrentDirectory(pathp) 357 } 358 359 func Mkdir(path string, mode uint32) (err error) { 360 pathp, err := UTF16PtrFromString(path) 361 if err != nil { 362 return err 363 } 364 return CreateDirectory(pathp, nil) 365 } 366 367 func Rmdir(path string) (err error) { 368 pathp, err := UTF16PtrFromString(path) 369 if err != nil { 370 return err 371 } 372 return RemoveDirectory(pathp) 373 } 374 375 func Unlink(path string) (err error) { 376 pathp, err := UTF16PtrFromString(path) 377 if err != nil { 378 return err 379 } 380 return DeleteFile(pathp) 381 } 382 383 func Rename(oldpath, newpath string) (err error) { 384 from, err := UTF16PtrFromString(oldpath) 385 if err != nil { 386 return err 387 } 388 to, err := UTF16PtrFromString(newpath) 389 if err != nil { 390 return err 391 } 392 return MoveFile(from, to) 393 } 394 395 func ComputerName() (name string, err error) { 396 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1 397 b := make([]uint16, n) 398 e := GetComputerName(&b[0], &n) 399 if e != nil { 400 return "", e 401 } 402 return string(utf16.Decode(b[0:n])), nil 403 } 404 405 func Ftruncate(fd Handle, length int64) (err error) { 406 curoffset, e := Seek(fd, 0, 1) 407 if e != nil { 408 return e 409 } 410 defer Seek(fd, curoffset, 0) 411 _, e = Seek(fd, length, 0) 412 if e != nil { 413 return e 414 } 415 e = SetEndOfFile(fd) 416 if e != nil { 417 return e 418 } 419 return nil 420 } 421 422 func Gettimeofday(tv *Timeval) (err error) { 423 var ft Filetime 424 GetSystemTimeAsFileTime(&ft) 425 *tv = NsecToTimeval(ft.Nanoseconds()) 426 return nil 427 } 428 429 func Pipe(p []Handle) (err error) { 430 if len(p) != 2 { 431 return EINVAL 432 } 433 var r, w Handle 434 e := CreatePipe(&r, &w, makeInheritSa(), 0) 435 if e != nil { 436 return e 437 } 438 p[0] = r 439 p[1] = w 440 return nil 441 } 442 443 func Utimes(path string, tv []Timeval) (err error) { 444 if len(tv) != 2 { 445 return EINVAL 446 } 447 pathp, e := UTF16PtrFromString(path) 448 if e != nil { 449 return e 450 } 451 h, e := CreateFile(pathp, 452 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 453 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) 454 if e != nil { 455 return e 456 } 457 defer Close(h) 458 a := NsecToFiletime(tv[0].Nanoseconds()) 459 w := NsecToFiletime(tv[1].Nanoseconds()) 460 return SetFileTime(h, nil, &a, &w) 461 } 462 463 func UtimesNano(path string, ts []Timespec) (err error) { 464 if len(ts) != 2 { 465 return EINVAL 466 } 467 pathp, e := UTF16PtrFromString(path) 468 if e != nil { 469 return e 470 } 471 h, e := CreateFile(pathp, 472 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 473 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) 474 if e != nil { 475 return e 476 } 477 defer Close(h) 478 a := NsecToFiletime(TimespecToNsec(ts[0])) 479 w := NsecToFiletime(TimespecToNsec(ts[1])) 480 return SetFileTime(h, nil, &a, &w) 481 } 482 483 func Fsync(fd Handle) (err error) { 484 return FlushFileBuffers(fd) 485 } 486 487 func Chmod(path string, mode uint32) (err error) { 488 if mode == 0 { 489 return EINVAL 490 } 491 p, e := UTF16PtrFromString(path) 492 if e != nil { 493 return e 494 } 495 attrs, e := GetFileAttributes(p) 496 if e != nil { 497 return e 498 } 499 if mode&S_IWRITE != 0 { 500 attrs &^= FILE_ATTRIBUTE_READONLY 501 } else { 502 attrs |= FILE_ATTRIBUTE_READONLY 503 } 504 return SetFileAttributes(p, attrs) 505 } 506 507 func LoadCancelIoEx() error { 508 return procCancelIoEx.Find() 509 } 510 511 func LoadSetFileCompletionNotificationModes() error { 512 return procSetFileCompletionNotificationModes.Find() 513 } 514 515 // net api calls 516 517 const socket_error = uintptr(^uint32(0)) 518 519 //sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup 520 //sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup 521 //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 522 //sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket 523 //sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt 524 //sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt 525 //sys bind(s Handle, name uintptr, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind 526 //sys connect(s Handle, name uintptr, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect 527 //sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname 528 //sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername 529 //sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen 530 //sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown 531 //sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket 532 //sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx 533 //sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs 534 //sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv 535 //sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend 536 //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 537 //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 538 //sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname 539 //sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname 540 //sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs 541 //sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname 542 //sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W 543 //sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree 544 //sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW 545 //sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW 546 //sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry 547 //sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo 548 //sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes 549 //sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW 550 551 // For testing: clients can set this flag to force 552 // creation of IPv6 sockets to return EAFNOSUPPORT. 553 var SocketDisableIPv6 bool 554 555 type RawSockaddrInet4 struct { 556 Family uint16 557 Port uint16 558 Addr [4]byte /* in_addr */ 559 Zero [8]uint8 560 } 561 562 type RawSockaddrInet6 struct { 563 Family uint16 564 Port uint16 565 Flowinfo uint32 566 Addr [16]byte /* in6_addr */ 567 Scope_id uint32 568 } 569 570 type RawSockaddr struct { 571 Family uint16 572 Data [14]int8 573 } 574 575 type RawSockaddrAny struct { 576 Addr RawSockaddr 577 Pad [96]int8 578 } 579 580 type Sockaddr interface { 581 sockaddr() (ptr uintptr, len int32, err error) // lowercase; only we can define Sockaddrs 582 } 583 584 type SockaddrInet4 struct { 585 Port int 586 Addr [4]byte 587 raw RawSockaddrInet4 588 } 589 590 func (sa *SockaddrInet4) sockaddr() (uintptr, int32, error) { 591 if sa.Port < 0 || sa.Port > 0xFFFF { 592 return 0, 0, EINVAL 593 } 594 sa.raw.Family = AF_INET 595 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 596 p[0] = byte(sa.Port >> 8) 597 p[1] = byte(sa.Port) 598 for i := 0; i < len(sa.Addr); i++ { 599 sa.raw.Addr[i] = sa.Addr[i] 600 } 601 return uintptr(unsafe.Pointer(&sa.raw)), int32(unsafe.Sizeof(sa.raw)), nil 602 } 603 604 type SockaddrInet6 struct { 605 Port int 606 ZoneId uint32 607 Addr [16]byte 608 raw RawSockaddrInet6 609 } 610 611 func (sa *SockaddrInet6) sockaddr() (uintptr, int32, error) { 612 if sa.Port < 0 || sa.Port > 0xFFFF { 613 return 0, 0, EINVAL 614 } 615 sa.raw.Family = AF_INET6 616 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 617 p[0] = byte(sa.Port >> 8) 618 p[1] = byte(sa.Port) 619 sa.raw.Scope_id = sa.ZoneId 620 for i := 0; i < len(sa.Addr); i++ { 621 sa.raw.Addr[i] = sa.Addr[i] 622 } 623 return uintptr(unsafe.Pointer(&sa.raw)), int32(unsafe.Sizeof(sa.raw)), nil 624 } 625 626 type SockaddrUnix struct { 627 Name string 628 } 629 630 func (sa *SockaddrUnix) sockaddr() (uintptr, int32, error) { 631 // TODO(brainman): implement SockaddrUnix.sockaddr() 632 return 0, 0, EWINDOWS 633 } 634 635 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { 636 switch rsa.Addr.Family { 637 case AF_UNIX: 638 return nil, EWINDOWS 639 640 case AF_INET: 641 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 642 sa := new(SockaddrInet4) 643 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 644 sa.Port = int(p[0])<<8 + int(p[1]) 645 for i := 0; i < len(sa.Addr); i++ { 646 sa.Addr[i] = pp.Addr[i] 647 } 648 return sa, nil 649 650 case AF_INET6: 651 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 652 sa := new(SockaddrInet6) 653 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 654 sa.Port = int(p[0])<<8 + int(p[1]) 655 sa.ZoneId = pp.Scope_id 656 for i := 0; i < len(sa.Addr); i++ { 657 sa.Addr[i] = pp.Addr[i] 658 } 659 return sa, nil 660 } 661 return nil, EAFNOSUPPORT 662 } 663 664 func Socket(domain, typ, proto int) (fd Handle, err error) { 665 if domain == AF_INET6 && SocketDisableIPv6 { 666 return InvalidHandle, EAFNOSUPPORT 667 } 668 return socket(int32(domain), int32(typ), int32(proto)) 669 } 670 671 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) { 672 v := int32(value) 673 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v))) 674 } 675 676 func Bind(fd Handle, sa Sockaddr) (err error) { 677 ptr, n, err := sa.sockaddr() 678 if err != nil { 679 return err 680 } 681 return bind(fd, ptr, n) 682 } 683 684 func Connect(fd Handle, sa Sockaddr) (err error) { 685 ptr, n, err := sa.sockaddr() 686 if err != nil { 687 return err 688 } 689 return connect(fd, ptr, n) 690 } 691 692 func Getsockname(fd Handle) (sa Sockaddr, err error) { 693 var rsa RawSockaddrAny 694 l := int32(unsafe.Sizeof(rsa)) 695 if err = getsockname(fd, &rsa, &l); err != nil { 696 return 697 } 698 return rsa.Sockaddr() 699 } 700 701 func Getpeername(fd Handle) (sa Sockaddr, err error) { 702 var rsa RawSockaddrAny 703 l := int32(unsafe.Sizeof(rsa)) 704 if err = getpeername(fd, &rsa, &l); err != nil { 705 return 706 } 707 return rsa.Sockaddr() 708 } 709 710 func Listen(s Handle, n int) (err error) { 711 return listen(s, int32(n)) 712 } 713 714 func Shutdown(fd Handle, how int) (err error) { 715 return shutdown(fd, int32(how)) 716 } 717 718 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) { 719 rsa, l, err := to.sockaddr() 720 if err != nil { 721 return err 722 } 723 return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine) 724 } 725 726 func LoadGetAddrInfo() error { 727 return procGetAddrInfoW.Find() 728 } 729 730 var connectExFunc struct { 731 once sync.Once 732 addr uintptr 733 err error 734 } 735 736 func LoadConnectEx() error { 737 connectExFunc.once.Do(func() { 738 var s Handle 739 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 740 if connectExFunc.err != nil { 741 return 742 } 743 defer CloseHandle(s) 744 var n uint32 745 connectExFunc.err = WSAIoctl(s, 746 SIO_GET_EXTENSION_FUNCTION_POINTER, 747 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)), 748 uint32(unsafe.Sizeof(WSAID_CONNECTEX)), 749 (*byte)(unsafe.Pointer(&connectExFunc.addr)), 750 uint32(unsafe.Sizeof(connectExFunc.addr)), 751 &n, nil, 0) 752 }) 753 return connectExFunc.err 754 } 755 756 func connectEx(s Handle, name uintptr, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) { 757 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) 758 if r1 == 0 { 759 if e1 != 0 { 760 err = error(e1) 761 } else { 762 err = EINVAL 763 } 764 } 765 return 766 } 767 768 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error { 769 err := LoadConnectEx() 770 if err != nil { 771 return errorspkg.New("failed to find ConnectEx: " + err.Error()) 772 } 773 ptr, n, err := sa.sockaddr() 774 if err != nil { 775 return err 776 } 777 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) 778 } 779 780 // Invented structures to support what package os expects. 781 type Rusage struct { 782 CreationTime Filetime 783 ExitTime Filetime 784 KernelTime Filetime 785 UserTime Filetime 786 } 787 788 type WaitStatus struct { 789 ExitCode uint32 790 } 791 792 func (w WaitStatus) Exited() bool { return true } 793 794 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) } 795 796 func (w WaitStatus) Signal() Signal { return -1 } 797 798 func (w WaitStatus) CoreDump() bool { return false } 799 800 func (w WaitStatus) Stopped() bool { return false } 801 802 func (w WaitStatus) Continued() bool { return false } 803 804 func (w WaitStatus) StopSignal() Signal { return -1 } 805 806 func (w WaitStatus) Signaled() bool { return false } 807 808 func (w WaitStatus) TrapCause() int { return -1 } 809 810 // Timespec is an invented structure on Windows, but here for 811 // consistency with the syscall package for other operating systems. 812 type Timespec struct { 813 Sec int64 814 Nsec int64 815 } 816 817 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } 818 819 func NsecToTimespec(nsec int64) (ts Timespec) { 820 ts.Sec = nsec / 1e9 821 ts.Nsec = nsec % 1e9 822 return 823 } 824 825 // TODO(brainman): fix all needed for net 826 827 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS } 828 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) { 829 return 0, nil, EWINDOWS 830 } 831 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS } 832 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS } 833 834 // The Linger struct is wrong but we only noticed after Go 1. 835 // sysLinger is the real system call structure. 836 837 // BUG(brainman): The definition of Linger is not appropriate for direct use 838 // with Setsockopt and Getsockopt. 839 // Use SetsockoptLinger instead. 840 841 type Linger struct { 842 Onoff int32 843 Linger int32 844 } 845 846 type sysLinger struct { 847 Onoff uint16 848 Linger uint16 849 } 850 851 type IPMreq struct { 852 Multiaddr [4]byte /* in_addr */ 853 Interface [4]byte /* in_addr */ 854 } 855 856 type IPv6Mreq struct { 857 Multiaddr [16]byte /* in6_addr */ 858 Interface uint32 859 } 860 861 func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, EWINDOWS } 862 863 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { 864 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)} 865 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys))) 866 } 867 868 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { 869 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) 870 } 871 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { 872 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) 873 } 874 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS } 875 876 func Getpid() (pid int) { return int(getCurrentProcessId()) } 877 878 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) { 879 // NOTE(rsc): The Win32finddata struct is wrong for the system call: 880 // the two paths are each one uint16 short. Use the correct struct, 881 // a win32finddata1, and then copy the results out. 882 // There is no loss of expressivity here, because the final 883 // uint16, if it is used, is supposed to be a NUL, and Go doesn't need that. 884 // For Go 1.1, we might avoid the allocation of win32finddata1 here 885 // by adding a final Bug [2]uint16 field to the struct and then 886 // adjusting the fields in the result directly. 887 var data1 win32finddata1 888 handle, err = findFirstFile1(name, &data1) 889 if err == nil { 890 copyFindData(data, &data1) 891 } 892 return 893 } 894 895 func FindNextFile(handle Handle, data *Win32finddata) (err error) { 896 var data1 win32finddata1 897 err = findNextFile1(handle, &data1) 898 if err == nil { 899 copyFindData(data, &data1) 900 } 901 return 902 } 903 904 // TODO(brainman): fix all needed for os 905 func Getppid() (ppid int) { return -1 } 906 907 func Fchdir(fd Handle) (err error) { return EWINDOWS } 908 func Link(oldpath, newpath string) (err error) { return EWINDOWS } 909 func Symlink(path, link string) (err error) { return EWINDOWS } 910 func Readlink(path string, buf []byte) (n int, err error) { return 0, EWINDOWS } 911 912 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS } 913 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS } 914 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS } 915 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS } 916 917 func Getuid() (uid int) { return -1 } 918 func Geteuid() (euid int) { return -1 } 919 func Getgid() (gid int) { return -1 } 920 func Getegid() (egid int) { return -1 } 921 func Getgroups() (gids []int, err error) { return nil, EWINDOWS } 922 923 type Signal int 924 925 func (s Signal) Signal() {} 926 927 func (s Signal) String() string { 928 if 0 <= s && int(s) < len(signals) { 929 str := signals[s] 930 if str != "" { 931 return str 932 } 933 } 934 return "signal " + itoa(int(s)) 935 }