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