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