| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package windows |
| |
| import ( |
| "sync" |
| "syscall" |
| "unicode/utf16" |
| "unsafe" |
| ) |
| |
| // UTF16PtrToString is like UTF16ToString, but takes *uint16 |
| // as a parameter instead of []uint16. |
| func UTF16PtrToString(p *uint16) string { |
| if p == nil { |
| return "" |
| } |
| // Find NUL terminator. |
| end := unsafe.Pointer(p) |
| n := 0 |
| for *(*uint16)(end) != 0 { |
| end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) |
| n++ |
| } |
| // Turn *uint16 into []uint16. |
| s := unsafe.Slice(p, n) |
| // Decode []uint16 into string. |
| return string(utf16.Decode(s)) |
| } |
| |
| const ( |
| ERROR_BAD_LENGTH syscall.Errno = 24 |
| ERROR_SHARING_VIOLATION syscall.Errno = 32 |
| ERROR_LOCK_VIOLATION syscall.Errno = 33 |
| ERROR_NOT_SUPPORTED syscall.Errno = 50 |
| ERROR_CALL_NOT_IMPLEMENTED syscall.Errno = 120 |
| ERROR_INVALID_NAME syscall.Errno = 123 |
| ERROR_LOCK_FAILED syscall.Errno = 167 |
| ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113 |
| ) |
| |
| const GAA_FLAG_INCLUDE_PREFIX = 0x00000010 |
| |
| const ( |
| IF_TYPE_OTHER = 1 |
| IF_TYPE_ETHERNET_CSMACD = 6 |
| IF_TYPE_ISO88025_TOKENRING = 9 |
| IF_TYPE_PPP = 23 |
| IF_TYPE_SOFTWARE_LOOPBACK = 24 |
| IF_TYPE_ATM = 37 |
| IF_TYPE_IEEE80211 = 71 |
| IF_TYPE_TUNNEL = 131 |
| IF_TYPE_IEEE1394 = 144 |
| ) |
| |
| type SocketAddress struct { |
| Sockaddr *syscall.RawSockaddrAny |
| SockaddrLength int32 |
| } |
| |
| type IpAdapterUnicastAddress struct { |
| Length uint32 |
| Flags uint32 |
| Next *IpAdapterUnicastAddress |
| Address SocketAddress |
| PrefixOrigin int32 |
| SuffixOrigin int32 |
| DadState int32 |
| ValidLifetime uint32 |
| PreferredLifetime uint32 |
| LeaseLifetime uint32 |
| OnLinkPrefixLength uint8 |
| } |
| |
| type IpAdapterAnycastAddress struct { |
| Length uint32 |
| Flags uint32 |
| Next *IpAdapterAnycastAddress |
| Address SocketAddress |
| } |
| |
| type IpAdapterMulticastAddress struct { |
| Length uint32 |
| Flags uint32 |
| Next *IpAdapterMulticastAddress |
| Address SocketAddress |
| } |
| |
| type IpAdapterDnsServerAdapter struct { |
| Length uint32 |
| Reserved uint32 |
| Next *IpAdapterDnsServerAdapter |
| Address SocketAddress |
| } |
| |
| type IpAdapterPrefix struct { |
| Length uint32 |
| Flags uint32 |
| Next *IpAdapterPrefix |
| Address SocketAddress |
| PrefixLength uint32 |
| } |
| |
| type IpAdapterAddresses struct { |
| Length uint32 |
| IfIndex uint32 |
| Next *IpAdapterAddresses |
| AdapterName *byte |
| FirstUnicastAddress *IpAdapterUnicastAddress |
| FirstAnycastAddress *IpAdapterAnycastAddress |
| FirstMulticastAddress *IpAdapterMulticastAddress |
| FirstDnsServerAddress *IpAdapterDnsServerAdapter |
| DnsSuffix *uint16 |
| Description *uint16 |
| FriendlyName *uint16 |
| PhysicalAddress [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte |
| PhysicalAddressLength uint32 |
| Flags uint32 |
| Mtu uint32 |
| IfType uint32 |
| OperStatus uint32 |
| Ipv6IfIndex uint32 |
| ZoneIndices [16]uint32 |
| FirstPrefix *IpAdapterPrefix |
| /* more fields might be present here. */ |
| } |
| |
| type FILE_BASIC_INFO struct { |
| CreationTime syscall.Filetime |
| LastAccessTime syscall.Filetime |
| LastWriteTime syscall.Filetime |
| ChangedTime syscall.Filetime |
| FileAttributes uint32 |
| } |
| |
| const ( |
| IfOperStatusUp = 1 |
| IfOperStatusDown = 2 |
| IfOperStatusTesting = 3 |
| IfOperStatusUnknown = 4 |
| IfOperStatusDormant = 5 |
| IfOperStatusNotPresent = 6 |
| IfOperStatusLowerLayerDown = 7 |
| ) |
| |
| //sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses |
| //sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW |
| //sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW |
| //sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW |
| //sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle |
| //sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery |
| |
| const ( |
| // flags for CreateToolhelp32Snapshot |
| TH32CS_SNAPMODULE = 0x08 |
| TH32CS_SNAPMODULE32 = 0x10 |
| ) |
| |
| const MAX_MODULE_NAME32 = 255 |
| |
| type ModuleEntry32 struct { |
| Size uint32 |
| ModuleID uint32 |
| ProcessID uint32 |
| GlblcntUsage uint32 |
| ProccntUsage uint32 |
| ModBaseAddr uintptr |
| ModBaseSize uint32 |
| ModuleHandle syscall.Handle |
| Module [MAX_MODULE_NAME32 + 1]uint16 |
| ExePath [syscall.MAX_PATH]uint16 |
| } |
| |
| const SizeofModuleEntry32 = unsafe.Sizeof(ModuleEntry32{}) |
| |
| //sys Module32First(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW |
| //sys Module32Next(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32NextW |
| |
| const ( |
| WSA_FLAG_OVERLAPPED = 0x01 |
| WSA_FLAG_NO_HANDLE_INHERIT = 0x80 |
| |
| WSAEMSGSIZE syscall.Errno = 10040 |
| |
| MSG_PEEK = 0x2 |
| MSG_TRUNC = 0x0100 |
| MSG_CTRUNC = 0x0200 |
| |
| socket_error = uintptr(^uint32(0)) |
| ) |
| |
| var WSAID_WSASENDMSG = syscall.GUID{ |
| Data1: 0xa441e712, |
| Data2: 0x754f, |
| Data3: 0x43ca, |
| Data4: [8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d}, |
| } |
| |
| var WSAID_WSARECVMSG = syscall.GUID{ |
| Data1: 0xf689d7c8, |
| Data2: 0x6f1f, |
| Data3: 0x436b, |
| Data4: [8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22}, |
| } |
| |
| var sendRecvMsgFunc struct { |
| once sync.Once |
| sendAddr uintptr |
| recvAddr uintptr |
| err error |
| } |
| |
| type WSAMsg struct { |
| Name syscall.Pointer |
| Namelen int32 |
| Buffers *syscall.WSABuf |
| BufferCount uint32 |
| Control syscall.WSABuf |
| Flags uint32 |
| } |
| |
| //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 |
| |
| func loadWSASendRecvMsg() error { |
| sendRecvMsgFunc.once.Do(func() { |
| var s syscall.Handle |
| s, sendRecvMsgFunc.err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) |
| if sendRecvMsgFunc.err != nil { |
| return |
| } |
| defer syscall.CloseHandle(s) |
| var n uint32 |
| sendRecvMsgFunc.err = syscall.WSAIoctl(s, |
| syscall.SIO_GET_EXTENSION_FUNCTION_POINTER, |
| (*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)), |
| uint32(unsafe.Sizeof(WSAID_WSARECVMSG)), |
| (*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)), |
| uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)), |
| &n, nil, 0) |
| if sendRecvMsgFunc.err != nil { |
| return |
| } |
| sendRecvMsgFunc.err = syscall.WSAIoctl(s, |
| syscall.SIO_GET_EXTENSION_FUNCTION_POINTER, |
| (*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)), |
| uint32(unsafe.Sizeof(WSAID_WSASENDMSG)), |
| (*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)), |
| uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)), |
| &n, nil, 0) |
| }) |
| return sendRecvMsgFunc.err |
| } |
| |
| func WSASendMsg(fd syscall.Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *syscall.Overlapped, croutine *byte) error { |
| err := loadWSASendRecvMsg() |
| if err != nil { |
| return err |
| } |
| 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))) |
| if r1 == socket_error { |
| if e1 != 0 { |
| err = errnoErr(e1) |
| } else { |
| err = syscall.EINVAL |
| } |
| } |
| return err |
| } |
| |
| func WSARecvMsg(fd syscall.Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *syscall.Overlapped, croutine *byte) error { |
| err := loadWSASendRecvMsg() |
| if err != nil { |
| return err |
| } |
| 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) |
| if r1 == socket_error { |
| if e1 != 0 { |
| err = errnoErr(e1) |
| } else { |
| err = syscall.EINVAL |
| } |
| } |
| return err |
| } |
| |
| const ( |
| ComputerNameNetBIOS = 0 |
| ComputerNameDnsHostname = 1 |
| ComputerNameDnsDomain = 2 |
| ComputerNameDnsFullyQualified = 3 |
| ComputerNamePhysicalNetBIOS = 4 |
| ComputerNamePhysicalDnsHostname = 5 |
| ComputerNamePhysicalDnsDomain = 6 |
| ComputerNamePhysicalDnsFullyQualified = 7 |
| ComputerNameMax = 8 |
| |
| MOVEFILE_REPLACE_EXISTING = 0x1 |
| MOVEFILE_COPY_ALLOWED = 0x2 |
| MOVEFILE_DELAY_UNTIL_REBOOT = 0x4 |
| MOVEFILE_WRITE_THROUGH = 0x8 |
| MOVEFILE_CREATE_HARDLINK = 0x10 |
| MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20 |
| ) |
| |
| func Rename(oldpath, newpath string) error { |
| from, err := syscall.UTF16PtrFromString(oldpath) |
| if err != nil { |
| return err |
| } |
| to, err := syscall.UTF16PtrFromString(newpath) |
| if err != nil { |
| return err |
| } |
| return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) |
| } |
| |
| //sys LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.LockFileEx |
| //sys UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.UnlockFileEx |
| |
| const ( |
| LOCKFILE_FAIL_IMMEDIATELY = 0x00000001 |
| LOCKFILE_EXCLUSIVE_LOCK = 0x00000002 |
| ) |
| |
| const MB_ERR_INVALID_CHARS = 8 |
| |
| //sys GetACP() (acp uint32) = kernel32.GetACP |
| //sys GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP |
| //sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar |
| //sys GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread |
| |
| const STYPE_DISKTREE = 0x00 |
| |
| type SHARE_INFO_2 struct { |
| Netname *uint16 |
| Type uint32 |
| Remark *uint16 |
| Permissions uint32 |
| MaxUses uint32 |
| CurrentUses uint32 |
| Path *uint16 |
| Passwd *uint16 |
| } |
| |
| //sys NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd |
| //sys NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel |
| |
| const ( |
| FILE_NAME_NORMALIZED = 0x0 |
| FILE_NAME_OPENED = 0x8 |
| |
| VOLUME_NAME_DOS = 0x0 |
| VOLUME_NAME_GUID = 0x1 |
| VOLUME_NAME_NONE = 0x4 |
| VOLUME_NAME_NT = 0x2 |
| ) |
| |
| //sys GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW |
| |
| func LoadGetFinalPathNameByHandle() error { |
| return procGetFinalPathNameByHandleW.Find() |
| } |
| |
| //sys CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock |
| //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock |
| |
| //sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036 |
| |
| type FILE_ID_BOTH_DIR_INFO struct { |
| NextEntryOffset uint32 |
| FileIndex uint32 |
| CreationTime syscall.Filetime |
| LastAccessTime syscall.Filetime |
| LastWriteTime syscall.Filetime |
| ChangeTime syscall.Filetime |
| EndOfFile uint64 |
| AllocationSize uint64 |
| FileAttributes uint32 |
| FileNameLength uint32 |
| EaSize uint32 |
| ShortNameLength uint32 |
| ShortName [12]uint16 |
| FileID uint64 |
| FileName [1]uint16 |
| } |
| |
| //sys GetVolumeInformationByHandle(file syscall.Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) = GetVolumeInformationByHandleW |