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