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	"internal/unsafeheader"
9	"sync"
10	"syscall"
11	"unicode/utf16"
12	"unsafe"
13)
14
15// UTF16PtrToString is like UTF16ToString, but takes *uint16
16// as a parameter instead of []uint16.
17func UTF16PtrToString(p *uint16) string {
18	if p == nil {
19		return ""
20	}
21	// Find NUL terminator.
22	end := unsafe.Pointer(p)
23	n := 0
24	for *(*uint16)(end) != 0 {
25		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
26		n++
27	}
28	// Turn *uint16 into []uint16.
29	var s []uint16
30	hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
31	hdr.Data = unsafe.Pointer(p)
32	hdr.Cap = n
33	hdr.Len = n
34	// Decode []uint16 into string.
35	return string(utf16.Decode(s))
36}
37
38const (
39	ERROR_SHARING_VIOLATION      syscall.Errno = 32
40	ERROR_LOCK_VIOLATION         syscall.Errno = 33
41	ERROR_NOT_SUPPORTED          syscall.Errno = 50
42	ERROR_CALL_NOT_IMPLEMENTED   syscall.Errno = 120
43	ERROR_INVALID_NAME           syscall.Errno = 123
44	ERROR_LOCK_FAILED            syscall.Errno = 167
45	ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113
46)
47
48const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
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 IpAdapterAddresses struct {
111	Length                uint32
112	IfIndex               uint32
113	Next                  *IpAdapterAddresses
114	AdapterName           *byte
115	FirstUnicastAddress   *IpAdapterUnicastAddress
116	FirstAnycastAddress   *IpAdapterAnycastAddress
117	FirstMulticastAddress *IpAdapterMulticastAddress
118	FirstDnsServerAddress *IpAdapterDnsServerAdapter
119	DnsSuffix             *uint16
120	Description           *uint16
121	FriendlyName          *uint16
122	PhysicalAddress       [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
123	PhysicalAddressLength uint32
124	Flags                 uint32
125	Mtu                   uint32
126	IfType                uint32
127	OperStatus            uint32
128	Ipv6IfIndex           uint32
129	ZoneIndices           [16]uint32
130	FirstPrefix           *IpAdapterPrefix
131	/* more fields might be present here. */
132}
133
134type FILE_BASIC_INFO struct {
135	CreationTime   syscall.Filetime
136	LastAccessTime syscall.Filetime
137	LastWriteTime  syscall.Filetime
138	ChangedTime    syscall.Filetime
139	FileAttributes uint32
140}
141
142const (
143	IfOperStatusUp             = 1
144	IfOperStatusDown           = 2
145	IfOperStatusTesting        = 3
146	IfOperStatusUnknown        = 4
147	IfOperStatusDormant        = 5
148	IfOperStatusNotPresent     = 6
149	IfOperStatusLowerLayerDown = 7
150)
151
152//sys	GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
153//sys	GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
154//sys	MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
155//sys	GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
156//sys	SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
157
158const (
159	WSA_FLAG_OVERLAPPED        = 0x01
160	WSA_FLAG_NO_HANDLE_INHERIT = 0x80
161
162	WSAEMSGSIZE syscall.Errno = 10040
163
164	MSG_PEEK   = 0x2
165	MSG_TRUNC  = 0x0100
166	MSG_CTRUNC = 0x0200
167
168	socket_error = uintptr(^uint32(0))
169)
170
171var WSAID_WSASENDMSG = syscall.GUID{
172	Data1: 0xa441e712,
173	Data2: 0x754f,
174	Data3: 0x43ca,
175	Data4: [8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
176}
177
178var WSAID_WSARECVMSG = syscall.GUID{
179	Data1: 0xf689d7c8,
180	Data2: 0x6f1f,
181	Data3: 0x436b,
182	Data4: [8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
183}
184
185var sendRecvMsgFunc struct {
186	once     sync.Once
187	sendAddr uintptr
188	recvAddr uintptr
189	err      error
190}
191
192type WSAMsg struct {
193	Name        syscall.Pointer
194	Namelen     int32
195	Buffers     *syscall.WSABuf
196	BufferCount uint32
197	Control     syscall.WSABuf
198	Flags       uint32
199}
200
201//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
202
203func loadWSASendRecvMsg() error {
204	sendRecvMsgFunc.once.Do(func() {
205		var s syscall.Handle
206		s, sendRecvMsgFunc.err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
207		if sendRecvMsgFunc.err != nil {
208			return
209		}
210		defer syscall.CloseHandle(s)
211		var n uint32
212		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
213			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
214			(*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)),
215			uint32(unsafe.Sizeof(WSAID_WSARECVMSG)),
216			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)),
217			uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)),
218			&n, nil, 0)
219		if sendRecvMsgFunc.err != nil {
220			return
221		}
222		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
223			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
224			(*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)),
225			uint32(unsafe.Sizeof(WSAID_WSASENDMSG)),
226			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)),
227			uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)),
228			&n, nil, 0)
229	})
230	return sendRecvMsgFunc.err
231}
232
233func WSASendMsg(fd syscall.Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
234	err := loadWSASendRecvMsg()
235	if err != nil {
236		return err
237	}
238	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)))
239	if r1 == socket_error {
240		if e1 != 0 {
241			err = errnoErr(e1)
242		} else {
243			err = syscall.EINVAL
244		}
245	}
246	return err
247}
248
249func WSARecvMsg(fd syscall.Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
250	err := loadWSASendRecvMsg()
251	if err != nil {
252		return err
253	}
254	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)
255	if r1 == socket_error {
256		if e1 != 0 {
257			err = errnoErr(e1)
258		} else {
259			err = syscall.EINVAL
260		}
261	}
262	return err
263}
264
265const (
266	ComputerNameNetBIOS                   = 0
267	ComputerNameDnsHostname               = 1
268	ComputerNameDnsDomain                 = 2
269	ComputerNameDnsFullyQualified         = 3
270	ComputerNamePhysicalNetBIOS           = 4
271	ComputerNamePhysicalDnsHostname       = 5
272	ComputerNamePhysicalDnsDomain         = 6
273	ComputerNamePhysicalDnsFullyQualified = 7
274	ComputerNameMax                       = 8
275
276	MOVEFILE_REPLACE_EXISTING      = 0x1
277	MOVEFILE_COPY_ALLOWED          = 0x2
278	MOVEFILE_DELAY_UNTIL_REBOOT    = 0x4
279	MOVEFILE_WRITE_THROUGH         = 0x8
280	MOVEFILE_CREATE_HARDLINK       = 0x10
281	MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20
282)
283
284func Rename(oldpath, newpath string) error {
285	from, err := syscall.UTF16PtrFromString(oldpath)
286	if err != nil {
287		return err
288	}
289	to, err := syscall.UTF16PtrFromString(newpath)
290	if err != nil {
291		return err
292	}
293	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
294}
295
296//sys LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.LockFileEx
297//sys UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.UnlockFileEx
298
299const (
300	LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
301	LOCKFILE_EXCLUSIVE_LOCK   = 0x00000002
302)
303
304const MB_ERR_INVALID_CHARS = 8
305
306//sys	GetACP() (acp uint32) = kernel32.GetACP
307//sys	GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
308//sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
309//sys	GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread
310
311const STYPE_DISKTREE = 0x00
312
313type SHARE_INFO_2 struct {
314	Netname     *uint16
315	Type        uint32
316	Remark      *uint16
317	Permissions uint32
318	MaxUses     uint32
319	CurrentUses uint32
320	Path        *uint16
321	Passwd      *uint16
322}
323
324//sys  NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd
325//sys  NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel
326
327const (
328	FILE_NAME_NORMALIZED = 0x0
329	FILE_NAME_OPENED     = 0x8
330
331	VOLUME_NAME_DOS  = 0x0
332	VOLUME_NAME_GUID = 0x1
333	VOLUME_NAME_NONE = 0x4
334	VOLUME_NAME_NT   = 0x2
335)
336
337//sys	GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
338
339func LoadGetFinalPathNameByHandle() error {
340	return procGetFinalPathNameByHandleW.Find()
341}
342
343//sys	CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
344//sys	DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
345
346//sys	RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036
347