1// Copyright 2014 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
5package windows
6
7import (
8	"sync"
9	"syscall"
10	"unsafe"
11)
12
13// CanUseLongPaths is true when the OS supports opting into
14// proper long path handling without the need for fixups.
15//
16//go:linkname CanUseLongPaths
17var CanUseLongPaths bool
18
19// UTF16PtrToString is like UTF16ToString, but takes *uint16
20// as a parameter instead of []uint16.
21func UTF16PtrToString(p *uint16) string {
22	if p == nil {
23		return ""
24	}
25	end := unsafe.Pointer(p)
26	n := 0
27	for *(*uint16)(end) != 0 {
28		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
29		n++
30	}
31	return syscall.UTF16ToString(unsafe.Slice(p, n))
32}
33
34const (
35	ERROR_BAD_LENGTH             syscall.Errno = 24
36	ERROR_SHARING_VIOLATION      syscall.Errno = 32
37	ERROR_LOCK_VIOLATION         syscall.Errno = 33
38	ERROR_NOT_SUPPORTED          syscall.Errno = 50
39	ERROR_CALL_NOT_IMPLEMENTED   syscall.Errno = 120
40	ERROR_INVALID_NAME           syscall.Errno = 123
41	ERROR_LOCK_FAILED            syscall.Errno = 167
42	ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113
43)
44
45const (
46	GAA_FLAG_INCLUDE_PREFIX   = 0x00000010
47	GAA_FLAG_INCLUDE_GATEWAYS = 0x0080
48)
49
50const (
51	IF_TYPE_OTHER              = 1
52	IF_TYPE_ETHERNET_CSMACD    = 6
53	IF_TYPE_ISO88025_TOKENRING = 9
54	IF_TYPE_PPP                = 23
55	IF_TYPE_SOFTWARE_LOOPBACK  = 24
56	IF_TYPE_ATM                = 37
57	IF_TYPE_IEEE80211          = 71
58	IF_TYPE_TUNNEL             = 131
59	IF_TYPE_IEEE1394           = 144
60)
61
62type SocketAddress struct {
63	Sockaddr       *syscall.RawSockaddrAny
64	SockaddrLength int32
65}
66
67type IpAdapterUnicastAddress struct {
68	Length             uint32
69	Flags              uint32
70	Next               *IpAdapterUnicastAddress
71	Address            SocketAddress
72	PrefixOrigin       int32
73	SuffixOrigin       int32
74	DadState           int32
75	ValidLifetime      uint32
76	PreferredLifetime  uint32
77	LeaseLifetime      uint32
78	OnLinkPrefixLength uint8
79}
80
81type IpAdapterAnycastAddress struct {
82	Length  uint32
83	Flags   uint32
84	Next    *IpAdapterAnycastAddress
85	Address SocketAddress
86}
87
88type IpAdapterMulticastAddress struct {
89	Length  uint32
90	Flags   uint32
91	Next    *IpAdapterMulticastAddress
92	Address SocketAddress
93}
94
95type IpAdapterDnsServerAdapter struct {
96	Length   uint32
97	Reserved uint32
98	Next     *IpAdapterDnsServerAdapter
99	Address  SocketAddress
100}
101
102type IpAdapterPrefix struct {
103	Length       uint32
104	Flags        uint32
105	Next         *IpAdapterPrefix
106	Address      SocketAddress
107	PrefixLength uint32
108}
109
110type IpAdapterWinsServerAddress struct {
111	Length   uint32
112	Reserved uint32
113	Next     *IpAdapterWinsServerAddress
114	Address  SocketAddress
115}
116
117type IpAdapterGatewayAddress struct {
118	Length   uint32
119	Reserved uint32
120	Next     *IpAdapterGatewayAddress
121	Address  SocketAddress
122}
123
124type IpAdapterAddresses struct {
125	Length                 uint32
126	IfIndex                uint32
127	Next                   *IpAdapterAddresses
128	AdapterName            *byte
129	FirstUnicastAddress    *IpAdapterUnicastAddress
130	FirstAnycastAddress    *IpAdapterAnycastAddress
131	FirstMulticastAddress  *IpAdapterMulticastAddress
132	FirstDnsServerAddress  *IpAdapterDnsServerAdapter
133	DnsSuffix              *uint16
134	Description            *uint16
135	FriendlyName           *uint16
136	PhysicalAddress        [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
137	PhysicalAddressLength  uint32
138	Flags                  uint32
139	Mtu                    uint32
140	IfType                 uint32
141	OperStatus             uint32
142	Ipv6IfIndex            uint32
143	ZoneIndices            [16]uint32
144	FirstPrefix            *IpAdapterPrefix
145	TransmitLinkSpeed      uint64
146	ReceiveLinkSpeed       uint64
147	FirstWinsServerAddress *IpAdapterWinsServerAddress
148	FirstGatewayAddress    *IpAdapterGatewayAddress
149	/* more fields might be present here. */
150}
151
152type SecurityAttributes struct {
153	Length             uint16
154	SecurityDescriptor uintptr
155	InheritHandle      bool
156}
157
158type FILE_BASIC_INFO struct {
159	CreationTime   int64
160	LastAccessTime int64
161	LastWriteTime  int64
162	ChangedTime    int64
163	FileAttributes uint32
164
165	// Pad out to 8-byte alignment.
166	//
167	// Without this padding, TestChmod fails due to an argument validation error
168	// in SetFileInformationByHandle on windows/386.
169	//
170	// https://learn.microsoft.com/en-us/cpp/build/reference/zp-struct-member-alignment?view=msvc-170
171	// says that “The C/C++ headers in the Windows SDK assume the platform's
172	// default alignment is used.” What we see here is padding rather than
173	// alignment, but maybe it is related.
174	_ uint32
175}
176
177const (
178	IfOperStatusUp             = 1
179	IfOperStatusDown           = 2
180	IfOperStatusTesting        = 3
181	IfOperStatusUnknown        = 4
182	IfOperStatusDormant        = 5
183	IfOperStatusNotPresent     = 6
184	IfOperStatusLowerLayerDown = 7
185)
186
187//sys	GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
188//sys	GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
189//sys	MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
190//sys	GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
191//sys	SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
192//sys	VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery
193//sys	GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W
194
195const (
196	// flags for CreateToolhelp32Snapshot
197	TH32CS_SNAPMODULE   = 0x08
198	TH32CS_SNAPMODULE32 = 0x10
199)
200
201const MAX_MODULE_NAME32 = 255
202
203type ModuleEntry32 struct {
204	Size         uint32
205	ModuleID     uint32
206	ProcessID    uint32
207	GlblcntUsage uint32
208	ProccntUsage uint32
209	ModBaseAddr  uintptr
210	ModBaseSize  uint32
211	ModuleHandle syscall.Handle
212	Module       [MAX_MODULE_NAME32 + 1]uint16
213	ExePath      [syscall.MAX_PATH]uint16
214}
215
216const SizeofModuleEntry32 = unsafe.Sizeof(ModuleEntry32{})
217
218//sys	Module32First(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
219//sys	Module32Next(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32NextW
220
221const (
222	WSA_FLAG_OVERLAPPED        = 0x01
223	WSA_FLAG_NO_HANDLE_INHERIT = 0x80
224
225	WSAEINVAL       syscall.Errno = 10022
226	WSAEMSGSIZE     syscall.Errno = 10040
227	WSAEAFNOSUPPORT syscall.Errno = 10047
228
229	MSG_PEEK   = 0x2
230	MSG_TRUNC  = 0x0100
231	MSG_CTRUNC = 0x0200
232
233	socket_error = uintptr(^uint32(0))
234)
235
236var WSAID_WSASENDMSG = syscall.GUID{
237	Data1: 0xa441e712,
238	Data2: 0x754f,
239	Data3: 0x43ca,
240	Data4: [8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
241}
242
243var WSAID_WSARECVMSG = syscall.GUID{
244	Data1: 0xf689d7c8,
245	Data2: 0x6f1f,
246	Data3: 0x436b,
247	Data4: [8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
248}
249
250var sendRecvMsgFunc struct {
251	once     sync.Once
252	sendAddr uintptr
253	recvAddr uintptr
254	err      error
255}
256
257type WSAMsg struct {
258	Name        syscall.Pointer
259	Namelen     int32
260	Buffers     *syscall.WSABuf
261	BufferCount uint32
262	Control     syscall.WSABuf
263	Flags       uint32
264}
265
266//sys	WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = ws2_32.WSASocketW
267//sys	WSAGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
268
269func loadWSASendRecvMsg() error {
270	sendRecvMsgFunc.once.Do(func() {
271		var s syscall.Handle
272		s, sendRecvMsgFunc.err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
273		if sendRecvMsgFunc.err != nil {
274			return
275		}
276		defer syscall.CloseHandle(s)
277		var n uint32
278		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
279			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
280			(*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)),
281			uint32(unsafe.Sizeof(WSAID_WSARECVMSG)),
282			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)),
283			uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)),
284			&n, nil, 0)
285		if sendRecvMsgFunc.err != nil {
286			return
287		}
288		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
289			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
290			(*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)),
291			uint32(unsafe.Sizeof(WSAID_WSASENDMSG)),
292			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)),
293			uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)),
294			&n, nil, 0)
295	})
296	return sendRecvMsgFunc.err
297}
298
299func WSASendMsg(fd syscall.Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
300	err := loadWSASendRecvMsg()
301	if err != nil {
302		return err
303	}
304	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)))
305	if r1 == socket_error {
306		if e1 != 0 {
307			err = errnoErr(e1)
308		} else {
309			err = syscall.EINVAL
310		}
311	}
312	return err
313}
314
315func WSARecvMsg(fd syscall.Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
316	err := loadWSASendRecvMsg()
317	if err != nil {
318		return err
319	}
320	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)
321	if r1 == socket_error {
322		if e1 != 0 {
323			err = errnoErr(e1)
324		} else {
325			err = syscall.EINVAL
326		}
327	}
328	return err
329}
330
331const (
332	ComputerNameNetBIOS                   = 0
333	ComputerNameDnsHostname               = 1
334	ComputerNameDnsDomain                 = 2
335	ComputerNameDnsFullyQualified         = 3
336	ComputerNamePhysicalNetBIOS           = 4
337	ComputerNamePhysicalDnsHostname       = 5
338	ComputerNamePhysicalDnsDomain         = 6
339	ComputerNamePhysicalDnsFullyQualified = 7
340	ComputerNameMax                       = 8
341
342	MOVEFILE_REPLACE_EXISTING      = 0x1
343	MOVEFILE_COPY_ALLOWED          = 0x2
344	MOVEFILE_DELAY_UNTIL_REBOOT    = 0x4
345	MOVEFILE_WRITE_THROUGH         = 0x8
346	MOVEFILE_CREATE_HARDLINK       = 0x10
347	MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20
348)
349
350func Rename(oldpath, newpath string) error {
351	from, err := syscall.UTF16PtrFromString(oldpath)
352	if err != nil {
353		return err
354	}
355	to, err := syscall.UTF16PtrFromString(newpath)
356	if err != nil {
357		return err
358	}
359	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
360}
361
362//sys LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.LockFileEx
363//sys UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.UnlockFileEx
364
365const (
366	LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
367	LOCKFILE_EXCLUSIVE_LOCK   = 0x00000002
368)
369
370const MB_ERR_INVALID_CHARS = 8
371
372//sys	GetACP() (acp uint32) = kernel32.GetACP
373//sys	GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
374//sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
375//sys	GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread
376
377// Constants from lmshare.h
378const (
379	STYPE_DISKTREE  = 0x00
380	STYPE_TEMPORARY = 0x40000000
381)
382
383type SHARE_INFO_2 struct {
384	Netname     *uint16
385	Type        uint32
386	Remark      *uint16
387	Permissions uint32
388	MaxUses     uint32
389	CurrentUses uint32
390	Path        *uint16
391	Passwd      *uint16
392}
393
394//sys  NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd
395//sys  NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel
396
397const (
398	FILE_NAME_NORMALIZED = 0x0
399	FILE_NAME_OPENED     = 0x8
400
401	VOLUME_NAME_DOS  = 0x0
402	VOLUME_NAME_GUID = 0x1
403	VOLUME_NAME_NONE = 0x4
404	VOLUME_NAME_NT   = 0x2
405)
406
407//sys	GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
408
409func ErrorLoadingGetTempPath2() error {
410	return procGetTempPath2W.Find()
411}
412
413//sys	CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
414//sys	DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
415//sys	CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
416
417//sys	ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng
418
419type FILE_ID_BOTH_DIR_INFO struct {
420	NextEntryOffset uint32
421	FileIndex       uint32
422	CreationTime    syscall.Filetime
423	LastAccessTime  syscall.Filetime
424	LastWriteTime   syscall.Filetime
425	ChangeTime      syscall.Filetime
426	EndOfFile       uint64
427	AllocationSize  uint64
428	FileAttributes  uint32
429	FileNameLength  uint32
430	EaSize          uint32
431	ShortNameLength uint32
432	ShortName       [12]uint16
433	FileID          uint64
434	FileName        [1]uint16
435}
436
437type FILE_FULL_DIR_INFO struct {
438	NextEntryOffset uint32
439	FileIndex       uint32
440	CreationTime    syscall.Filetime
441	LastAccessTime  syscall.Filetime
442	LastWriteTime   syscall.Filetime
443	ChangeTime      syscall.Filetime
444	EndOfFile       uint64
445	AllocationSize  uint64
446	FileAttributes  uint32
447	FileNameLength  uint32
448	EaSize          uint32
449	FileName        [1]uint16
450}
451
452//sys	GetVolumeInformationByHandle(file syscall.Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) = GetVolumeInformationByHandleW
453//sys	GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) = GetVolumeNameForVolumeMountPointW
454
455//sys	RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry
456//sys	RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind
457
458type SERVICE_STATUS struct {
459	ServiceType             uint32
460	CurrentState            uint32
461	ControlsAccepted        uint32
462	Win32ExitCode           uint32
463	ServiceSpecificExitCode uint32
464	CheckPoint              uint32
465	WaitHint                uint32
466}
467
468const (
469	SERVICE_RUNNING      = 4
470	SERVICE_QUERY_STATUS = 4
471)
472
473//sys    OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) = advapi32.OpenServiceW
474//sys	QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error)  = advapi32.QueryServiceStatus
475//sys    OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error)  [failretval==0] = advapi32.OpenSCManagerW
476
477func FinalPath(h syscall.Handle, flags uint32) (string, error) {
478	buf := make([]uint16, 100)
479	for {
480		n, err := GetFinalPathNameByHandle(h, &buf[0], uint32(len(buf)), flags)
481		if err != nil {
482			return "", err
483		}
484		if n < uint32(len(buf)) {
485			break
486		}
487		buf = make([]uint16, n)
488	}
489	return syscall.UTF16ToString(buf), nil
490}
491
492// QueryPerformanceCounter retrieves the current value of performance counter.
493//
494//go:linkname QueryPerformanceCounter
495func QueryPerformanceCounter() int64 // Implemented in runtime package.
496
497// QueryPerformanceFrequency retrieves the frequency of the performance counter.
498// The returned value is represented as counts per second.
499//
500//go:linkname QueryPerformanceFrequency
501func QueryPerformanceFrequency() int64 // Implemented in runtime package.
502