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