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
13const (
14	ERROR_SHARING_VIOLATION      syscall.Errno = 32
15	ERROR_LOCK_VIOLATION         syscall.Errno = 33
16	ERROR_NOT_SUPPORTED          syscall.Errno = 50
17	ERROR_CALL_NOT_IMPLEMENTED   syscall.Errno = 120
18	ERROR_INVALID_NAME           syscall.Errno = 123
19	ERROR_LOCK_FAILED            syscall.Errno = 167
20	ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113
21)
22
23const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
24
25const (
26	IF_TYPE_OTHER              = 1
27	IF_TYPE_ETHERNET_CSMACD    = 6
28	IF_TYPE_ISO88025_TOKENRING = 9
29	IF_TYPE_PPP                = 23
30	IF_TYPE_SOFTWARE_LOOPBACK  = 24
31	IF_TYPE_ATM                = 37
32	IF_TYPE_IEEE80211          = 71
33	IF_TYPE_TUNNEL             = 131
34	IF_TYPE_IEEE1394           = 144
35)
36
37type SocketAddress struct {
38	Sockaddr       *syscall.RawSockaddrAny
39	SockaddrLength int32
40}
41
42type IpAdapterUnicastAddress struct {
43	Length             uint32
44	Flags              uint32
45	Next               *IpAdapterUnicastAddress
46	Address            SocketAddress
47	PrefixOrigin       int32
48	SuffixOrigin       int32
49	DadState           int32
50	ValidLifetime      uint32
51	PreferredLifetime  uint32
52	LeaseLifetime      uint32
53	OnLinkPrefixLength uint8
54}
55
56type IpAdapterAnycastAddress struct {
57	Length  uint32
58	Flags   uint32
59	Next    *IpAdapterAnycastAddress
60	Address SocketAddress
61}
62
63type IpAdapterMulticastAddress struct {
64	Length  uint32
65	Flags   uint32
66	Next    *IpAdapterMulticastAddress
67	Address SocketAddress
68}
69
70type IpAdapterDnsServerAdapter struct {
71	Length   uint32
72	Reserved uint32
73	Next     *IpAdapterDnsServerAdapter
74	Address  SocketAddress
75}
76
77type IpAdapterPrefix struct {
78	Length       uint32
79	Flags        uint32
80	Next         *IpAdapterPrefix
81	Address      SocketAddress
82	PrefixLength uint32
83}
84
85type IpAdapterAddresses struct {
86	Length                uint32
87	IfIndex               uint32
88	Next                  *IpAdapterAddresses
89	AdapterName           *byte
90	FirstUnicastAddress   *IpAdapterUnicastAddress
91	FirstAnycastAddress   *IpAdapterAnycastAddress
92	FirstMulticastAddress *IpAdapterMulticastAddress
93	FirstDnsServerAddress *IpAdapterDnsServerAdapter
94	DnsSuffix             *uint16
95	Description           *uint16
96	FriendlyName          *uint16
97	PhysicalAddress       [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
98	PhysicalAddressLength uint32
99	Flags                 uint32
100	Mtu                   uint32
101	IfType                uint32
102	OperStatus            uint32
103	Ipv6IfIndex           uint32
104	ZoneIndices           [16]uint32
105	FirstPrefix           *IpAdapterPrefix
106	/* more fields might be present here. */
107}
108
109const (
110	IfOperStatusUp             = 1
111	IfOperStatusDown           = 2
112	IfOperStatusTesting        = 3
113	IfOperStatusUnknown        = 4
114	IfOperStatusDormant        = 5
115	IfOperStatusNotPresent     = 6
116	IfOperStatusLowerLayerDown = 7
117)
118
119//sys	GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
120//sys	GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
121//sys	MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
122//sys	GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
123
124const (
125	WSA_FLAG_OVERLAPPED        = 0x01
126	WSA_FLAG_NO_HANDLE_INHERIT = 0x80
127
128	WSAEMSGSIZE syscall.Errno = 10040
129
130	MSG_PEEK   = 0x2
131	MSG_TRUNC  = 0x0100
132	MSG_CTRUNC = 0x0200
133
134	socket_error = uintptr(^uint32(0))
135)
136
137var WSAID_WSASENDMSG = syscall.GUID{
138	Data1: 0xa441e712,
139	Data2: 0x754f,
140	Data3: 0x43ca,
141	Data4: [8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
142}
143
144var WSAID_WSARECVMSG = syscall.GUID{
145	Data1: 0xf689d7c8,
146	Data2: 0x6f1f,
147	Data3: 0x436b,
148	Data4: [8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
149}
150
151var sendRecvMsgFunc struct {
152	once     sync.Once
153	sendAddr uintptr
154	recvAddr uintptr
155	err      error
156}
157
158type WSAMsg struct {
159	Name        *syscall.RawSockaddrAny
160	Namelen     int32
161	Buffers     *syscall.WSABuf
162	BufferCount uint32
163	Control     syscall.WSABuf
164	Flags       uint32
165}
166
167//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
168
169func loadWSASendRecvMsg() error {
170	sendRecvMsgFunc.once.Do(func() {
171		var s syscall.Handle
172		s, sendRecvMsgFunc.err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
173		if sendRecvMsgFunc.err != nil {
174			return
175		}
176		defer syscall.CloseHandle(s)
177		var n uint32
178		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
179			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
180			(*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)),
181			uint32(unsafe.Sizeof(WSAID_WSARECVMSG)),
182			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)),
183			uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)),
184			&n, nil, 0)
185		if sendRecvMsgFunc.err != nil {
186			return
187		}
188		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
189			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
190			(*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)),
191			uint32(unsafe.Sizeof(WSAID_WSASENDMSG)),
192			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)),
193			uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)),
194			&n, nil, 0)
195	})
196	return sendRecvMsgFunc.err
197}
198
199func WSASendMsg(fd syscall.Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
200	err := loadWSASendRecvMsg()
201	if err != nil {
202		return err
203	}
204	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)))
205	if r1 == socket_error {
206		if e1 != 0 {
207			err = errnoErr(e1)
208		} else {
209			err = syscall.EINVAL
210		}
211	}
212	return err
213}
214
215func WSARecvMsg(fd syscall.Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
216	err := loadWSASendRecvMsg()
217	if err != nil {
218		return err
219	}
220	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)
221	if r1 == socket_error {
222		if e1 != 0 {
223			err = errnoErr(e1)
224		} else {
225			err = syscall.EINVAL
226		}
227	}
228	return err
229}
230
231const (
232	ComputerNameNetBIOS                   = 0
233	ComputerNameDnsHostname               = 1
234	ComputerNameDnsDomain                 = 2
235	ComputerNameDnsFullyQualified         = 3
236	ComputerNamePhysicalNetBIOS           = 4
237	ComputerNamePhysicalDnsHostname       = 5
238	ComputerNamePhysicalDnsDomain         = 6
239	ComputerNamePhysicalDnsFullyQualified = 7
240	ComputerNameMax                       = 8
241
242	MOVEFILE_REPLACE_EXISTING      = 0x1
243	MOVEFILE_COPY_ALLOWED          = 0x2
244	MOVEFILE_DELAY_UNTIL_REBOOT    = 0x4
245	MOVEFILE_WRITE_THROUGH         = 0x8
246	MOVEFILE_CREATE_HARDLINK       = 0x10
247	MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20
248)
249
250func Rename(oldpath, newpath string) error {
251	from, err := syscall.UTF16PtrFromString(oldpath)
252	if err != nil {
253		return err
254	}
255	to, err := syscall.UTF16PtrFromString(newpath)
256	if err != nil {
257		return err
258	}
259	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
260}
261
262//sys LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.LockFileEx
263//sys UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.UnlockFileEx
264
265const (
266	LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
267	LOCKFILE_EXCLUSIVE_LOCK   = 0x00000002
268)
269
270const MB_ERR_INVALID_CHARS = 8
271
272//sys	GetACP() (acp uint32) = kernel32.GetACP
273//sys	GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
274//sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
275//sys	GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread
276
277const STYPE_DISKTREE = 0x00
278
279type SHARE_INFO_2 struct {
280	Netname     *uint16
281	Type        uint32
282	Remark      *uint16
283	Permissions uint32
284	MaxUses     uint32
285	CurrentUses uint32
286	Path        *uint16
287	Passwd      *uint16
288}
289
290//sys  NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd
291//sys  NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel
292
293const (
294	FILE_NAME_NORMALIZED = 0x0
295	FILE_NAME_OPENED     = 0x8
296
297	VOLUME_NAME_DOS  = 0x0
298	VOLUME_NAME_GUID = 0x1
299	VOLUME_NAME_NONE = 0x4
300	VOLUME_NAME_NT   = 0x2
301)
302
303//sys	GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
304
305func LoadGetFinalPathNameByHandle() error {
306	return procGetFinalPathNameByHandleW.Find()
307}
308