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