blob: 7aff0d02252549beaac0c184324c604c77f22f94 [file] [log] [blame]
sslobodrd046be82019-01-16 10:02:22 -05001// 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)
William Kurkiandaa6bb22019-03-07 12:26:28 -0500140//sys GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error)
sslobodrd046be82019-01-16 10:02:22 -0500141//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]
Stephane Barbarie260a5632019-02-26 16:12:49 -0500176//sys waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] = WaitForMultipleObjects
sslobodrd046be82019-01-16 10:02:22 -0500177//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
Stephane Barbarie260a5632019-02-26 16:12:49 -0500594func 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
sslobodrd046be82019-01-16 10:02:22 -0500606// 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}