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 syscall
8
9import (
10	errorspkg "errors"
11	"internal/asan"
12	"internal/bytealg"
13	"internal/itoa"
14	"internal/msan"
15	"internal/oserror"
16	"internal/race"
17	"runtime"
18	"sync"
19	"unsafe"
20)
21
22type Handle uintptr
23
24const InvalidHandle = ^Handle(0)
25
26// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s,
27// with a terminating NUL added. If s contains a NUL byte this
28// function panics instead of returning an error.
29//
30// Deprecated: Use [UTF16FromString] instead.
31func StringToUTF16(s string) []uint16 {
32	a, err := UTF16FromString(s)
33	if err != nil {
34		panic("syscall: string with NUL passed to StringToUTF16")
35	}
36	return a
37}
38
39// UTF16FromString returns the UTF-16 encoding of the UTF-8 string
40// s, with a terminating NUL added. If s contains a NUL byte at any
41// location, it returns (nil, [EINVAL]). Unpaired surrogates
42// are encoded using WTF-8.
43func UTF16FromString(s string) ([]uint16, error) {
44	if bytealg.IndexByteString(s, 0) != -1 {
45		return nil, EINVAL
46	}
47	// Valid UTF-8 characters between 1 and 3 bytes require one uint16.
48	// Valid UTF-8 characters of 4 bytes require two uint16.
49	// Bytes with invalid UTF-8 encoding require maximum one uint16 per byte.
50	// So the number of UTF-8 code units (len(s)) is always greater or
51	// equal than the number of UTF-16 code units.
52	// Also account for the terminating NUL character.
53	buf := make([]uint16, 0, len(s)+1)
54	buf = encodeWTF16(s, buf)
55	return append(buf, 0), nil
56}
57
58// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
59// with a terminating NUL removed. Unpaired surrogates are decoded
60// using WTF-8 instead of UTF-8 encoding.
61func UTF16ToString(s []uint16) string {
62	maxLen := 0
63	for i, v := range s {
64		if v == 0 {
65			s = s[0:i]
66			break
67		}
68		switch {
69		case v <= rune1Max:
70			maxLen += 1
71		case v <= rune2Max:
72			maxLen += 2
73		default:
74			// r is a non-surrogate that decodes to 3 bytes,
75			// or is an unpaired surrogate (also 3 bytes in WTF-8),
76			// or is one half of a valid surrogate pair.
77			// If it is half of a pair, we will add 3 for the second surrogate
78			// (total of 6) and overestimate by 2 bytes for the pair,
79			// since the resulting rune only requires 4 bytes.
80			maxLen += 3
81		}
82	}
83	buf := decodeWTF16(s, make([]byte, 0, maxLen))
84	return unsafe.String(unsafe.SliceData(buf), len(buf))
85}
86
87// utf16PtrToString is like UTF16ToString, but takes *uint16
88// as a parameter instead of []uint16.
89func utf16PtrToString(p *uint16) string {
90	if p == nil {
91		return ""
92	}
93	end := unsafe.Pointer(p)
94	n := 0
95	for *(*uint16)(end) != 0 {
96		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
97		n++
98	}
99	return UTF16ToString(unsafe.Slice(p, n))
100}
101
102// StringToUTF16Ptr returns pointer to the UTF-16 encoding of
103// the UTF-8 string s, with a terminating NUL added. If s
104// contains a NUL byte this function panics instead of
105// returning an error.
106//
107// Deprecated: Use [UTF16PtrFromString] instead.
108func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
109
110// UTF16PtrFromString returns pointer to the UTF-16 encoding of
111// the UTF-8 string s, with a terminating NUL added. If s
112// contains a NUL byte at any location, it returns (nil, EINVAL).
113// Unpaired surrogates are encoded using WTF-8.
114func UTF16PtrFromString(s string) (*uint16, error) {
115	a, err := UTF16FromString(s)
116	if err != nil {
117		return nil, err
118	}
119	return &a[0], nil
120}
121
122// Errno is the Windows error number.
123//
124// Errno values can be tested against error values using [errors.Is].
125// For example:
126//
127//	_, _, err := syscall.Syscall(...)
128//	if errors.Is(err, fs.ErrNotExist) ...
129type Errno uintptr
130
131func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) }
132
133// FormatMessage is deprecated (msgsrc should be uintptr, not uint32, but can
134// not be changed due to the Go 1 compatibility guarantee).
135//
136// Deprecated: Use FormatMessage from golang.org/x/sys/windows instead.
137func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
138	return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args)
139}
140
141func (e Errno) Error() string {
142	// deal with special go errors
143	idx := int(e - APPLICATION_ERROR)
144	if 0 <= idx && idx < len(errors) {
145		return errors[idx]
146	}
147	// ask windows for the remaining errors
148	var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
149	b := make([]uint16, 300)
150	n, err := formatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil)
151	if err != nil {
152		n, err = formatMessage(flags, 0, uint32(e), 0, b, nil)
153		if err != nil {
154			return "winapi error #" + itoa.Itoa(int(e))
155		}
156	}
157	// trim terminating \r and \n
158	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
159	}
160	return UTF16ToString(b[:n])
161}
162
163const (
164	_ERROR_NOT_ENOUGH_MEMORY    = Errno(8)
165	_ERROR_NOT_SUPPORTED        = Errno(50)
166	_ERROR_BAD_NETPATH          = Errno(53)
167	_ERROR_CALL_NOT_IMPLEMENTED = Errno(120)
168)
169
170func (e Errno) Is(target error) bool {
171	switch target {
172	case oserror.ErrPermission:
173		return e == ERROR_ACCESS_DENIED ||
174			e == EACCES ||
175			e == EPERM
176	case oserror.ErrExist:
177		return e == ERROR_ALREADY_EXISTS ||
178			e == ERROR_DIR_NOT_EMPTY ||
179			e == ERROR_FILE_EXISTS ||
180			e == EEXIST ||
181			e == ENOTEMPTY
182	case oserror.ErrNotExist:
183		return e == ERROR_FILE_NOT_FOUND ||
184			e == _ERROR_BAD_NETPATH ||
185			e == ERROR_PATH_NOT_FOUND ||
186			e == ENOENT
187	case errorspkg.ErrUnsupported:
188		return e == _ERROR_NOT_SUPPORTED ||
189			e == _ERROR_CALL_NOT_IMPLEMENTED ||
190			e == ENOSYS ||
191			e == ENOTSUP ||
192			e == EOPNOTSUPP ||
193			e == EWINDOWS
194	}
195	return false
196}
197
198func (e Errno) Temporary() bool {
199	return e == EINTR || e == EMFILE || e.Timeout()
200}
201
202func (e Errno) Timeout() bool {
203	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
204}
205
206// Implemented in runtime/syscall_windows.go.
207func compileCallback(fn any, cleanstack bool) uintptr
208
209// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
210// This is useful when interoperating with Windows code requiring callbacks.
211// The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
212// Only a limited number of callbacks may be created in a single Go process, and any memory allocated
213// for these callbacks is never released.
214// Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created.
215func NewCallback(fn any) uintptr {
216	return compileCallback(fn, true)
217}
218
219// NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention.
220// This is useful when interoperating with Windows code requiring callbacks.
221// The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
222// Only a limited number of callbacks may be created in a single Go process, and any memory allocated
223// for these callbacks is never released.
224// Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created.
225func NewCallbackCDecl(fn any) uintptr {
226	return compileCallback(fn, false)
227}
228
229// windows api calls
230
231//sys	GetLastError() (lasterr error)
232//sys	LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW
233//sys	FreeLibrary(handle Handle) (err error)
234//sys	GetProcAddress(module Handle, procname string) (proc uintptr, err error)
235//sys	GetVersion() (ver uint32, err error)
236//sys	formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
237//sys	ExitProcess(exitcode uint32)
238//sys	CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
239//sys	readFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = ReadFile
240//sys	writeFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) = WriteFile
241//sys	SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
242//sys	CloseHandle(handle Handle) (err error)
243//sys	GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle]
244//sys	findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW
245//sys	findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW
246//sys	FindClose(handle Handle) (err error)
247//sys	GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error)
248//sys	GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW
249//sys	SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW
250//sys	CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW
251//sys	RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW
252//sys	DeleteFile(path *uint16) (err error) = DeleteFileW
253//sys	MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
254//sys	GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
255//sys	SetEndOfFile(handle Handle) (err error)
256//sys	GetSystemTimeAsFileTime(time *Filetime)
257//sys	GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
258//sys	createIoCompletionPort(filehandle Handle, cphandle Handle, key uintptr, threadcnt uint32) (handle Handle, err error) = CreateIoCompletionPort
259//sys	getQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uintptr, overlapped **Overlapped, timeout uint32) (err error) = GetQueuedCompletionStatus
260//sys	postQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) = PostQueuedCompletionStatus
261//sys	CancelIo(s Handle) (err error)
262//sys	CancelIoEx(s Handle, o *Overlapped) (err error)
263//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
264//sys	CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = advapi32.CreateProcessAsUserW
265//sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
266//sys	TerminateProcess(handle Handle, exitcode uint32) (err error)
267//sys	GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
268//sys	getStartupInfo(startupInfo *StartupInfo) = GetStartupInfoW
269//sys	GetCurrentProcess() (pseudoHandle Handle, err error)
270//sys	GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
271//sys	DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
272//sys	WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
273//sys	GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW
274//sys	CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error)
275//sys	GetFileType(filehandle Handle) (n uint32, err error)
276//sys	CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW
277//sys	CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext
278//sys	CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom
279//sys	GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW
280//sys	FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW
281//sys	GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW
282//sys	SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW
283//sys	SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
284//sys	GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
285//sys	SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
286//sys	GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
287//sys	GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
288//sys	CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
289//sys	LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
290//sys	SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
291//sys	FlushFileBuffers(handle Handle) (err error)
292//sys	GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW
293//sys	GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW
294//sys	GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW
295//sys	CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW
296//sys	MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error)
297//sys	UnmapViewOfFile(addr uintptr) (err error)
298//sys	FlushViewOfFile(addr uintptr, length uintptr) (err error)
299//sys	VirtualLock(addr uintptr, length uintptr) (err error)
300//sys	VirtualUnlock(addr uintptr, length uintptr) (err error)
301//sys	TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
302//sys	ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
303//sys	CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
304//sys   CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) = crypt32.CertOpenStore
305//sys	CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
306//sys   CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
307//sys	CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
308//sys   CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain
309//sys   CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain
310//sys   CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext
311//sys   CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext
312//sys   CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy
313//sys	RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
314//sys	RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
315//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
316//sys	regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
317//sys	RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
318//sys	getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
319//sys	GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
320//sys	WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
321//sys	ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
322//sys	CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
323//sys	Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
324//sys	Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
325//sys	DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error)
326// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
327//sys	CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW
328//sys	CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW
329//sys	initializeProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList
330//sys	deleteProcThreadAttributeList(attrlist *_PROC_THREAD_ATTRIBUTE_LIST) = DeleteProcThreadAttributeList
331//sys	updateProcThreadAttribute(attrlist *_PROC_THREAD_ATTRIBUTE_LIST, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute
332//sys	getFinalPathNameByHandle(file Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) [n == 0 || n >= filePathSize] = kernel32.GetFinalPathNameByHandleW
333
334// syscall interface implementation for other packages
335
336func makeInheritSa() *SecurityAttributes {
337	var sa SecurityAttributes
338	sa.Length = uint32(unsafe.Sizeof(sa))
339	sa.InheritHandle = 1
340	return &sa
341}
342
343func Open(path string, mode int, perm uint32) (fd Handle, err error) {
344	if len(path) == 0 {
345		return InvalidHandle, ERROR_FILE_NOT_FOUND
346	}
347	pathp, err := UTF16PtrFromString(path)
348	if err != nil {
349		return InvalidHandle, err
350	}
351	var access uint32
352	switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
353	case O_RDONLY:
354		access = GENERIC_READ
355	case O_WRONLY:
356		access = GENERIC_WRITE
357	case O_RDWR:
358		access = GENERIC_READ | GENERIC_WRITE
359	}
360	if mode&O_CREAT != 0 {
361		access |= GENERIC_WRITE
362	}
363	if mode&O_APPEND != 0 {
364		access &^= GENERIC_WRITE
365		access |= FILE_APPEND_DATA
366	}
367	sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
368	var sa *SecurityAttributes
369	if mode&O_CLOEXEC == 0 {
370		sa = makeInheritSa()
371	}
372	var createmode uint32
373	switch {
374	case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
375		createmode = CREATE_NEW
376	case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
377		createmode = CREATE_ALWAYS
378	case mode&O_CREAT == O_CREAT:
379		createmode = OPEN_ALWAYS
380	case mode&O_TRUNC == O_TRUNC:
381		createmode = TRUNCATE_EXISTING
382	default:
383		createmode = OPEN_EXISTING
384	}
385	var attrs uint32 = FILE_ATTRIBUTE_NORMAL
386	if perm&S_IWRITE == 0 {
387		attrs = FILE_ATTRIBUTE_READONLY
388		if createmode == CREATE_ALWAYS {
389			// We have been asked to create a read-only file.
390			// If the file already exists, the semantics of
391			// the Unix open system call is to preserve the
392			// existing permissions. If we pass CREATE_ALWAYS
393			// and FILE_ATTRIBUTE_READONLY to CreateFile,
394			// and the file already exists, CreateFile will
395			// change the file permissions.
396			// Avoid that to preserve the Unix semantics.
397			h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
398			switch e {
399			case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND:
400				// File does not exist. These are the same
401				// errors as Errno.Is checks for ErrNotExist.
402				// Carry on to create the file.
403			default:
404				// Success or some different error.
405				return h, e
406			}
407		}
408	}
409	if createmode == OPEN_EXISTING && access == GENERIC_READ {
410		// Necessary for opening directory handles.
411		attrs |= FILE_FLAG_BACKUP_SEMANTICS
412	}
413	if mode&O_SYNC != 0 {
414		const _FILE_FLAG_WRITE_THROUGH = 0x80000000
415		attrs |= _FILE_FLAG_WRITE_THROUGH
416	}
417	return CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
418}
419
420func Read(fd Handle, p []byte) (n int, err error) {
421	var done uint32
422	e := ReadFile(fd, p, &done, nil)
423	if e != nil {
424		if e == ERROR_BROKEN_PIPE {
425			// NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin
426			return 0, nil
427		}
428		return 0, e
429	}
430	return int(done), nil
431}
432
433func Write(fd Handle, p []byte) (n int, err error) {
434	var done uint32
435	e := WriteFile(fd, p, &done, nil)
436	if e != nil {
437		return 0, e
438	}
439	return int(done), nil
440}
441
442func ReadFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
443	err := readFile(fd, p, done, overlapped)
444	if race.Enabled {
445		if *done > 0 {
446			race.WriteRange(unsafe.Pointer(&p[0]), int(*done))
447		}
448		race.Acquire(unsafe.Pointer(&ioSync))
449	}
450	if msan.Enabled && *done > 0 {
451		msan.Write(unsafe.Pointer(&p[0]), uintptr(*done))
452	}
453	if asan.Enabled && *done > 0 {
454		asan.Write(unsafe.Pointer(&p[0]), uintptr(*done))
455	}
456	return err
457}
458
459func WriteFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
460	if race.Enabled {
461		race.ReleaseMerge(unsafe.Pointer(&ioSync))
462	}
463	err := writeFile(fd, p, done, overlapped)
464	if race.Enabled && *done > 0 {
465		race.ReadRange(unsafe.Pointer(&p[0]), int(*done))
466	}
467	if msan.Enabled && *done > 0 {
468		msan.Read(unsafe.Pointer(&p[0]), uintptr(*done))
469	}
470	if asan.Enabled && *done > 0 {
471		asan.Read(unsafe.Pointer(&p[0]), uintptr(*done))
472	}
473	return err
474}
475
476var ioSync int64
477
478var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
479
480const ptrSize = unsafe.Sizeof(uintptr(0))
481
482// setFilePointerEx calls SetFilePointerEx.
483// See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointerex
484func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error {
485	var e1 Errno
486	if unsafe.Sizeof(uintptr(0)) == 8 {
487		_, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0)
488	} else {
489		// Different 32-bit systems disgaree about whether distToMove starts 8-byte aligned.
490		switch runtime.GOARCH {
491		default:
492			panic("unsupported 32-bit architecture")
493		case "386":
494			// distToMove is a LARGE_INTEGER, which is 64 bits.
495			_, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0)
496		case "arm":
497			// distToMove must be 8-byte aligned per ARM calling convention
498			// https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions#stage-c-assignment-of-arguments-to-registers-and-stack
499			_, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence))
500		}
501	}
502	if e1 != 0 {
503		return errnoErr(e1)
504	}
505	return nil
506}
507
508func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
509	var w uint32
510	switch whence {
511	case 0:
512		w = FILE_BEGIN
513	case 1:
514		w = FILE_CURRENT
515	case 2:
516		w = FILE_END
517	}
518	err = setFilePointerEx(fd, offset, &newoffset, w)
519	return
520}
521
522func Close(fd Handle) (err error) {
523	return CloseHandle(fd)
524}
525
526var (
527	Stdin  = getStdHandle(STD_INPUT_HANDLE)
528	Stdout = getStdHandle(STD_OUTPUT_HANDLE)
529	Stderr = getStdHandle(STD_ERROR_HANDLE)
530)
531
532func getStdHandle(h int) (fd Handle) {
533	r, _ := GetStdHandle(h)
534	return r
535}
536
537const ImplementsGetwd = true
538
539func Getwd() (wd string, err error) {
540	b := make([]uint16, 300)
541	// The path of the current directory may not fit in the initial 300-word
542	// buffer when long path support is enabled. The current directory may also
543	// change between subsequent calls of GetCurrentDirectory. As a result, we
544	// need to retry the call in a loop until the current directory fits, each
545	// time with a bigger buffer.
546	for {
547		n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
548		if e != nil {
549			return "", e
550		}
551		if int(n) <= len(b) {
552			return UTF16ToString(b[:n]), nil
553		}
554		b = make([]uint16, n)
555	}
556}
557
558func Chdir(path string) (err error) {
559	pathp, err := UTF16PtrFromString(path)
560	if err != nil {
561		return err
562	}
563	return SetCurrentDirectory(pathp)
564}
565
566func Mkdir(path string, mode uint32) (err error) {
567	pathp, err := UTF16PtrFromString(path)
568	if err != nil {
569		return err
570	}
571	return CreateDirectory(pathp, nil)
572}
573
574func Rmdir(path string) (err error) {
575	pathp, err := UTF16PtrFromString(path)
576	if err != nil {
577		return err
578	}
579	return RemoveDirectory(pathp)
580}
581
582func Unlink(path string) (err error) {
583	pathp, err := UTF16PtrFromString(path)
584	if err != nil {
585		return err
586	}
587	return DeleteFile(pathp)
588}
589
590func Rename(oldpath, newpath string) (err error) {
591	from, err := UTF16PtrFromString(oldpath)
592	if err != nil {
593		return err
594	}
595	to, err := UTF16PtrFromString(newpath)
596	if err != nil {
597		return err
598	}
599	return MoveFile(from, to)
600}
601
602func ComputerName() (name string, err error) {
603	var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
604	b := make([]uint16, n)
605	e := GetComputerName(&b[0], &n)
606	if e != nil {
607		return "", e
608	}
609	return UTF16ToString(b[:n]), nil
610}
611
612func Ftruncate(fd Handle, length int64) (err error) {
613	curoffset, e := Seek(fd, 0, 1)
614	if e != nil {
615		return e
616	}
617	defer Seek(fd, curoffset, 0)
618	_, e = Seek(fd, length, 0)
619	if e != nil {
620		return e
621	}
622	e = SetEndOfFile(fd)
623	if e != nil {
624		return e
625	}
626	return nil
627}
628
629func Gettimeofday(tv *Timeval) (err error) {
630	var ft Filetime
631	GetSystemTimeAsFileTime(&ft)
632	*tv = NsecToTimeval(ft.Nanoseconds())
633	return nil
634}
635
636func Pipe(p []Handle) (err error) {
637	if len(p) != 2 {
638		return EINVAL
639	}
640	var r, w Handle
641	e := CreatePipe(&r, &w, makeInheritSa(), 0)
642	if e != nil {
643		return e
644	}
645	p[0] = r
646	p[1] = w
647	return nil
648}
649
650func Utimes(path string, tv []Timeval) (err error) {
651	if len(tv) != 2 {
652		return EINVAL
653	}
654	pathp, e := UTF16PtrFromString(path)
655	if e != nil {
656		return e
657	}
658	h, e := CreateFile(pathp,
659		FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
660		OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
661	if e != nil {
662		return e
663	}
664	defer Close(h)
665	a := Filetime{}
666	w := Filetime{}
667	if tv[0].Nanoseconds() != 0 {
668		a = NsecToFiletime(tv[0].Nanoseconds())
669	}
670	if tv[0].Nanoseconds() != 0 {
671		w = NsecToFiletime(tv[1].Nanoseconds())
672	}
673	return SetFileTime(h, nil, &a, &w)
674}
675
676// This matches the value in os/file_windows.go.
677const _UTIME_OMIT = -1
678
679func UtimesNano(path string, ts []Timespec) (err error) {
680	if len(ts) != 2 {
681		return EINVAL
682	}
683	pathp, e := UTF16PtrFromString(path)
684	if e != nil {
685		return e
686	}
687	h, e := CreateFile(pathp,
688		FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
689		OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
690	if e != nil {
691		return e
692	}
693	defer Close(h)
694	a := Filetime{}
695	w := Filetime{}
696	if ts[0].Nsec != _UTIME_OMIT {
697		a = NsecToFiletime(TimespecToNsec(ts[0]))
698	}
699	if ts[1].Nsec != _UTIME_OMIT {
700		w = NsecToFiletime(TimespecToNsec(ts[1]))
701	}
702	return SetFileTime(h, nil, &a, &w)
703}
704
705func Fsync(fd Handle) (err error) {
706	return FlushFileBuffers(fd)
707}
708
709func Chmod(path string, mode uint32) (err error) {
710	p, e := UTF16PtrFromString(path)
711	if e != nil {
712		return e
713	}
714	attrs, e := GetFileAttributes(p)
715	if e != nil {
716		return e
717	}
718	if mode&S_IWRITE != 0 {
719		attrs &^= FILE_ATTRIBUTE_READONLY
720	} else {
721		attrs |= FILE_ATTRIBUTE_READONLY
722	}
723	return SetFileAttributes(p, attrs)
724}
725
726func LoadCancelIoEx() error {
727	return procCancelIoEx.Find()
728}
729
730func LoadSetFileCompletionNotificationModes() error {
731	return procSetFileCompletionNotificationModes.Find()
732}
733
734// net api calls
735
736const socket_error = uintptr(^uint32(0))
737
738//sys	WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup
739//sys	WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup
740//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
741//sys	socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
742//sys	Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt
743//sys	Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt
744//sys	bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind
745//sys	connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect
746//sys	getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname
747//sys	getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername
748//sys	listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen
749//sys	shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown
750//sys	Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket
751//sys	AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx
752//sys	GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs
753//sys	WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv
754//sys	WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend
755//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
756//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
757//sys	GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname
758//sys	GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname
759//sys	Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
760//sys	GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
761//sys	DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
762//sys	DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
763//sys	DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W
764//sys	GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW
765//sys	FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW
766//sys	GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
767//sys	GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
768//sys	SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes
769//sys	WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW
770
771// For testing: clients can set this flag to force
772// creation of IPv6 sockets to return [EAFNOSUPPORT].
773var SocketDisableIPv6 bool
774
775type RawSockaddrInet4 struct {
776	Family uint16
777	Port   uint16
778	Addr   [4]byte /* in_addr */
779	Zero   [8]uint8
780}
781
782type RawSockaddrInet6 struct {
783	Family   uint16
784	Port     uint16
785	Flowinfo uint32
786	Addr     [16]byte /* in6_addr */
787	Scope_id uint32
788}
789
790type RawSockaddr struct {
791	Family uint16
792	Data   [14]int8
793}
794
795type RawSockaddrAny struct {
796	Addr RawSockaddr
797	Pad  [100]int8
798}
799
800type Sockaddr interface {
801	sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs
802}
803
804type SockaddrInet4 struct {
805	Port int
806	Addr [4]byte
807	raw  RawSockaddrInet4
808}
809
810func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
811	if sa.Port < 0 || sa.Port > 0xFFFF {
812		return nil, 0, EINVAL
813	}
814	sa.raw.Family = AF_INET
815	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
816	p[0] = byte(sa.Port >> 8)
817	p[1] = byte(sa.Port)
818	sa.raw.Addr = sa.Addr
819	return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
820}
821
822type SockaddrInet6 struct {
823	Port   int
824	ZoneId uint32
825	Addr   [16]byte
826	raw    RawSockaddrInet6
827}
828
829func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
830	if sa.Port < 0 || sa.Port > 0xFFFF {
831		return nil, 0, EINVAL
832	}
833	sa.raw.Family = AF_INET6
834	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
835	p[0] = byte(sa.Port >> 8)
836	p[1] = byte(sa.Port)
837	sa.raw.Scope_id = sa.ZoneId
838	sa.raw.Addr = sa.Addr
839	return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
840}
841
842type RawSockaddrUnix struct {
843	Family uint16
844	Path   [UNIX_PATH_MAX]int8
845}
846
847type SockaddrUnix struct {
848	Name string
849	raw  RawSockaddrUnix
850}
851
852func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
853	name := sa.Name
854	n := len(name)
855	if n > len(sa.raw.Path) {
856		return nil, 0, EINVAL
857	}
858	if n == len(sa.raw.Path) && name[0] != '@' {
859		return nil, 0, EINVAL
860	}
861	sa.raw.Family = AF_UNIX
862	for i := 0; i < n; i++ {
863		sa.raw.Path[i] = int8(name[i])
864	}
865	// length is family (uint16), name, NUL.
866	sl := int32(2)
867	if n > 0 {
868		sl += int32(n) + 1
869	}
870	if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
871		// Check sl > 3 so we don't change unnamed socket behavior.
872		sa.raw.Path[0] = 0
873		// Don't count trailing NUL for abstract address.
874		sl--
875	}
876
877	return unsafe.Pointer(&sa.raw), sl, nil
878}
879
880func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
881	switch rsa.Addr.Family {
882	case AF_UNIX:
883		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
884		sa := new(SockaddrUnix)
885		if pp.Path[0] == 0 {
886			// "Abstract" Unix domain socket.
887			// Rewrite leading NUL as @ for textual display.
888			// (This is the standard convention.)
889			// Not friendly to overwrite in place,
890			// but the callers below don't care.
891			pp.Path[0] = '@'
892		}
893
894		// Assume path ends at NUL.
895		// This is not technically the Linux semantics for
896		// abstract Unix domain sockets--they are supposed
897		// to be uninterpreted fixed-size binary blobs--but
898		// everyone uses this convention.
899		n := 0
900		for n < len(pp.Path) && pp.Path[n] != 0 {
901			n++
902		}
903		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
904		return sa, nil
905
906	case AF_INET:
907		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
908		sa := new(SockaddrInet4)
909		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
910		sa.Port = int(p[0])<<8 + int(p[1])
911		sa.Addr = pp.Addr
912		return sa, nil
913
914	case AF_INET6:
915		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
916		sa := new(SockaddrInet6)
917		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
918		sa.Port = int(p[0])<<8 + int(p[1])
919		sa.ZoneId = pp.Scope_id
920		sa.Addr = pp.Addr
921		return sa, nil
922	}
923	return nil, EAFNOSUPPORT
924}
925
926func Socket(domain, typ, proto int) (fd Handle, err error) {
927	if domain == AF_INET6 && SocketDisableIPv6 {
928		return InvalidHandle, EAFNOSUPPORT
929	}
930	return socket(int32(domain), int32(typ), int32(proto))
931}
932
933func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
934	v := int32(value)
935	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
936}
937
938func Bind(fd Handle, sa Sockaddr) (err error) {
939	ptr, n, err := sa.sockaddr()
940	if err != nil {
941		return err
942	}
943	return bind(fd, ptr, n)
944}
945
946func Connect(fd Handle, sa Sockaddr) (err error) {
947	ptr, n, err := sa.sockaddr()
948	if err != nil {
949		return err
950	}
951	return connect(fd, ptr, n)
952}
953
954func Getsockname(fd Handle) (sa Sockaddr, err error) {
955	var rsa RawSockaddrAny
956	l := int32(unsafe.Sizeof(rsa))
957	if err = getsockname(fd, &rsa, &l); err != nil {
958		return
959	}
960	return rsa.Sockaddr()
961}
962
963func Getpeername(fd Handle) (sa Sockaddr, err error) {
964	var rsa RawSockaddrAny
965	l := int32(unsafe.Sizeof(rsa))
966	if err = getpeername(fd, &rsa, &l); err != nil {
967		return
968	}
969	return rsa.Sockaddr()
970}
971
972func Listen(s Handle, n int) (err error) {
973	return listen(s, int32(n))
974}
975
976func Shutdown(fd Handle, how int) (err error) {
977	return shutdown(fd, int32(how))
978}
979
980func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
981	var rsa unsafe.Pointer
982	var len int32
983	if to != nil {
984		rsa, len, err = to.sockaddr()
985		if err != nil {
986			return err
987		}
988	}
989	r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
990	if r1 == socket_error {
991		if e1 != 0 {
992			err = errnoErr(e1)
993		} else {
994			err = EINVAL
995		}
996	}
997	return err
998}
999
1000func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) {
1001	rsa, len, err := to.sockaddr()
1002	if err != nil {
1003		return err
1004	}
1005	r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
1006	if r1 == socket_error {
1007		if e1 != 0 {
1008			err = errnoErr(e1)
1009		} else {
1010			err = EINVAL
1011		}
1012	}
1013	return err
1014}
1015
1016func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) {
1017	rsa, len, err := to.sockaddr()
1018	if err != nil {
1019		return err
1020	}
1021	r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
1022	if r1 == socket_error {
1023		if e1 != 0 {
1024			err = errnoErr(e1)
1025		} else {
1026			err = EINVAL
1027		}
1028	}
1029	return err
1030}
1031
1032func LoadGetAddrInfo() error {
1033	return procGetAddrInfoW.Find()
1034}
1035
1036var connectExFunc struct {
1037	once sync.Once
1038	addr uintptr
1039	err  error
1040}
1041
1042func LoadConnectEx() error {
1043	connectExFunc.once.Do(func() {
1044		var s Handle
1045		s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
1046		if connectExFunc.err != nil {
1047			return
1048		}
1049		defer CloseHandle(s)
1050		var n uint32
1051		connectExFunc.err = WSAIoctl(s,
1052			SIO_GET_EXTENSION_FUNCTION_POINTER,
1053			(*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
1054			uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
1055			(*byte)(unsafe.Pointer(&connectExFunc.addr)),
1056			uint32(unsafe.Sizeof(connectExFunc.addr)),
1057			&n, nil, 0)
1058	})
1059	return connectExFunc.err
1060}
1061
1062func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
1063	r1, _, e1 := Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0)
1064	if r1 == 0 {
1065		if e1 != 0 {
1066			err = error(e1)
1067		} else {
1068			err = EINVAL
1069		}
1070	}
1071	return
1072}
1073
1074func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
1075	err := LoadConnectEx()
1076	if err != nil {
1077		return errorspkg.New("failed to find ConnectEx: " + err.Error())
1078	}
1079	ptr, n, err := sa.sockaddr()
1080	if err != nil {
1081		return err
1082	}
1083	return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
1084}
1085
1086// Invented structures to support what package os expects.
1087type Rusage struct {
1088	CreationTime Filetime
1089	ExitTime     Filetime
1090	KernelTime   Filetime
1091	UserTime     Filetime
1092}
1093
1094type WaitStatus struct {
1095	ExitCode uint32
1096}
1097
1098func (w WaitStatus) Exited() bool { return true }
1099
1100func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
1101
1102func (w WaitStatus) Signal() Signal { return -1 }
1103
1104func (w WaitStatus) CoreDump() bool { return false }
1105
1106func (w WaitStatus) Stopped() bool { return false }
1107
1108func (w WaitStatus) Continued() bool { return false }
1109
1110func (w WaitStatus) StopSignal() Signal { return -1 }
1111
1112func (w WaitStatus) Signaled() bool { return false }
1113
1114func (w WaitStatus) TrapCause() int { return -1 }
1115
1116// Timespec is an invented structure on Windows, but here for
1117// consistency with the syscall package for other operating systems.
1118type Timespec struct {
1119	Sec  int64
1120	Nsec int64
1121}
1122
1123func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
1124
1125func NsecToTimespec(nsec int64) (ts Timespec) {
1126	ts.Sec = nsec / 1e9
1127	ts.Nsec = nsec % 1e9
1128	return
1129}
1130
1131// TODO(brainman): fix all needed for net
1132
1133func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
1134func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
1135	return 0, nil, EWINDOWS
1136}
1137func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error)       { return EWINDOWS }
1138func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
1139
1140// The Linger struct is wrong but we only noticed after Go 1.
1141// sysLinger is the real system call structure.
1142
1143// BUG(brainman): The definition of Linger is not appropriate for direct use
1144// with Setsockopt and Getsockopt.
1145// Use SetsockoptLinger instead.
1146
1147type Linger struct {
1148	Onoff  int32
1149	Linger int32
1150}
1151
1152type sysLinger struct {
1153	Onoff  uint16
1154	Linger uint16
1155}
1156
1157type IPMreq struct {
1158	Multiaddr [4]byte /* in_addr */
1159	Interface [4]byte /* in_addr */
1160}
1161
1162type IPv6Mreq struct {
1163	Multiaddr [16]byte /* in6_addr */
1164	Interface uint32
1165}
1166
1167func GetsockoptInt(fd Handle, level, opt int) (int, error) {
1168	optval := int32(0)
1169	optlen := int32(unsafe.Sizeof(optval))
1170	err := Getsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&optval)), &optlen)
1171	return int(optval), err
1172}
1173
1174func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
1175	sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
1176	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
1177}
1178
1179func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
1180	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
1181}
1182func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
1183	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1184}
1185func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }
1186
1187func Getpid() (pid int) { return int(getCurrentProcessId()) }
1188
1189func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
1190	// NOTE(rsc): The Win32finddata struct is wrong for the system call:
1191	// the two paths are each one uint16 short. Use the correct struct,
1192	// a win32finddata1, and then copy the results out.
1193	// There is no loss of expressivity here, because the final
1194	// uint16, if it is used, is supposed to be a NUL, and Go doesn't need that.
1195	// For Go 1.1, we might avoid the allocation of win32finddata1 here
1196	// by adding a final Bug [2]uint16 field to the struct and then
1197	// adjusting the fields in the result directly.
1198	var data1 win32finddata1
1199	handle, err = findFirstFile1(name, &data1)
1200	if err == nil {
1201		copyFindData(data, &data1)
1202	}
1203	return
1204}
1205
1206func FindNextFile(handle Handle, data *Win32finddata) (err error) {
1207	var data1 win32finddata1
1208	err = findNextFile1(handle, &data1)
1209	if err == nil {
1210		copyFindData(data, &data1)
1211	}
1212	return
1213}
1214
1215func getProcessEntry(pid int) (*ProcessEntry32, error) {
1216	snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
1217	if err != nil {
1218		return nil, err
1219	}
1220	defer CloseHandle(snapshot)
1221	var procEntry ProcessEntry32
1222	procEntry.Size = uint32(unsafe.Sizeof(procEntry))
1223	if err = Process32First(snapshot, &procEntry); err != nil {
1224		return nil, err
1225	}
1226	for {
1227		if procEntry.ProcessID == uint32(pid) {
1228			return &procEntry, nil
1229		}
1230		err = Process32Next(snapshot, &procEntry)
1231		if err != nil {
1232			return nil, err
1233		}
1234	}
1235}
1236
1237func Getppid() (ppid int) {
1238	pe, err := getProcessEntry(Getpid())
1239	if err != nil {
1240		return -1
1241	}
1242	return int(pe.ParentProcessID)
1243}
1244
1245func fdpath(fd Handle, buf []uint16) ([]uint16, error) {
1246	const (
1247		FILE_NAME_NORMALIZED = 0
1248		VOLUME_NAME_DOS      = 0
1249	)
1250	for {
1251		n, err := getFinalPathNameByHandle(fd, &buf[0], uint32(len(buf)), FILE_NAME_NORMALIZED|VOLUME_NAME_DOS)
1252		if err == nil {
1253			buf = buf[:n]
1254			break
1255		}
1256		if err != _ERROR_NOT_ENOUGH_MEMORY {
1257			return nil, err
1258		}
1259		buf = append(buf, make([]uint16, n-uint32(len(buf)))...)
1260	}
1261	return buf, nil
1262}
1263
1264func Fchdir(fd Handle) (err error) {
1265	var buf [MAX_PATH + 1]uint16
1266	path, err := fdpath(fd, buf[:])
1267	if err != nil {
1268		return err
1269	}
1270	// When using VOLUME_NAME_DOS, the path is always prefixed by "\\?\".
1271	// That prefix tells the Windows APIs to disable all string parsing and to send
1272	// the string that follows it straight to the file system.
1273	// Although SetCurrentDirectory and GetCurrentDirectory do support the "\\?\" prefix,
1274	// some other Windows APIs don't. If the prefix is not removed here, it will leak
1275	// to Getwd, and we don't want such a general-purpose function to always return a
1276	// path with the "\\?\" prefix after Fchdir is called.
1277	// The downside is that APIs that do support it will parse the path and try to normalize it,
1278	// when it's already normalized.
1279	if len(path) >= 4 && path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\' {
1280		path = path[4:]
1281	}
1282	return SetCurrentDirectory(&path[0])
1283}
1284
1285// TODO(brainman): fix all needed for os
1286func Link(oldpath, newpath string) (err error) { return EWINDOWS }
1287func Symlink(path, link string) (err error)    { return EWINDOWS }
1288
1289func Fchmod(fd Handle, mode uint32) (err error)        { return EWINDOWS }
1290func Chown(path string, uid int, gid int) (err error)  { return EWINDOWS }
1291func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
1292func Fchown(fd Handle, uid int, gid int) (err error)   { return EWINDOWS }
1293
1294func Getuid() (uid int)                  { return -1 }
1295func Geteuid() (euid int)                { return -1 }
1296func Getgid() (gid int)                  { return -1 }
1297func Getegid() (egid int)                { return -1 }
1298func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
1299
1300type Signal int
1301
1302func (s Signal) Signal() {}
1303
1304func (s Signal) String() string {
1305	if 0 <= s && int(s) < len(signals) {
1306		str := signals[s]
1307		if str != "" {
1308			return str
1309		}
1310	}
1311	return "signal " + itoa.Itoa(int(s))
1312}
1313
1314func LoadCreateSymbolicLink() error {
1315	return procCreateSymbolicLinkW.Find()
1316}
1317
1318// Readlink returns the destination of the named symbolic link.
1319func Readlink(path string, buf []byte) (n int, err error) {
1320	fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
1321		FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
1322	if err != nil {
1323		return -1, err
1324	}
1325	defer CloseHandle(fd)
1326
1327	rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
1328	var bytesReturned uint32
1329	err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
1330	if err != nil {
1331		return -1, err
1332	}
1333
1334	rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
1335	var s string
1336	switch rdb.ReparseTag {
1337	case IO_REPARSE_TAG_SYMLINK:
1338		data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1339		p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1340		s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1341		if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
1342			if len(s) >= 4 && s[:4] == `\??\` {
1343				s = s[4:]
1344				switch {
1345				case len(s) >= 2 && s[1] == ':': // \??\C:\foo\bar
1346					// do nothing
1347				case len(s) >= 4 && s[:4] == `UNC\`: // \??\UNC\foo\bar
1348					s = `\\` + s[4:]
1349				default:
1350					// unexpected; do nothing
1351				}
1352			} else {
1353				// unexpected; do nothing
1354			}
1355		}
1356	case _IO_REPARSE_TAG_MOUNT_POINT:
1357		data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1358		p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1359		s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1360		if len(s) >= 4 && s[:4] == `\??\` { // \??\C:\foo\bar
1361			s = s[4:]
1362		} else {
1363			// unexpected; do nothing
1364		}
1365	default:
1366		// the path is not a symlink or junction but another type of reparse
1367		// point
1368		return -1, ENOENT
1369	}
1370	n = copy(buf, []byte(s))
1371
1372	return n, nil
1373}
1374
1375// Deprecated: CreateIoCompletionPort has the wrong function signature. Use x/sys/windows.CreateIoCompletionPort.
1376func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
1377	return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
1378}
1379
1380// Deprecated: GetQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.GetQueuedCompletionStatus.
1381func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
1382	var ukey uintptr
1383	var pukey *uintptr
1384	if key != nil {
1385		ukey = uintptr(*key)
1386		pukey = &ukey
1387	}
1388	err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
1389	if key != nil {
1390		*key = uint32(ukey)
1391		if uintptr(*key) != ukey && err == nil {
1392			err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
1393		}
1394	}
1395	return err
1396}
1397
1398// Deprecated: PostQueuedCompletionStatus has the wrong function signature. Use x/sys/windows.PostQueuedCompletionStatus.
1399func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
1400	return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
1401}
1402
1403// newProcThreadAttributeList allocates new PROC_THREAD_ATTRIBUTE_LIST, with
1404// the requested maximum number of attributes, which must be cleaned up by
1405// deleteProcThreadAttributeList.
1406func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LIST, error) {
1407	var size uintptr
1408	err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
1409	if err != ERROR_INSUFFICIENT_BUFFER {
1410		if err == nil {
1411			return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
1412		}
1413		return nil, err
1414	}
1415	// size is guaranteed to be ≥1 by initializeProcThreadAttributeList.
1416	al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0]))
1417	err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size)
1418	if err != nil {
1419		return nil, err
1420	}
1421	return al, nil
1422}
1423
1424// RegEnumKeyEx enumerates the subkeys of an open registry key.
1425// Each call retrieves information about one subkey. name is
1426// a buffer that should be large enough to hold the name of the
1427// subkey plus a null terminating character. nameLen is its
1428// length. On return, nameLen will contain the actual length of the
1429// subkey.
1430//
1431// Should name not be large enough to hold the subkey, this function
1432// will return ERROR_MORE_DATA, and must be called again with an
1433// appropriately sized buffer.
1434//
1435// reserved must be nil. class and classLen behave like name and nameLen
1436// but for the class of the subkey, except that they are optional.
1437// lastWriteTime, if not nil, will be populated with the time the subkey
1438// was last written.
1439//
1440// The caller must enumerate all subkeys in order. That is
1441// RegEnumKeyEx must be called with index starting at 0, incrementing
1442// the index until the function returns ERROR_NO_MORE_ITEMS, or with
1443// the index of the last subkey (obtainable from RegQueryInfoKey),
1444// decrementing until index 0 is enumerated.
1445//
1446// Successive calls to this API must happen on the same OS thread,
1447// so call [runtime.LockOSThread] before calling this function.
1448func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
1449	return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime)
1450}
1451
1452func GetStartupInfo(startupInfo *StartupInfo) error {
1453	getStartupInfo(startupInfo)
1454	return nil
1455}
1456