// 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" "unsafe" ) // CanUseLongPaths is true when the OS supports opting into // proper long path handling without the need for fixups. // //go:linkname CanUseLongPaths var CanUseLongPaths bool // UTF16PtrToString is like UTF16ToString, but takes *uint16 // as a parameter instead of []uint16. func UTF16PtrToString(p *uint16) string { if p == nil { return "" } end := unsafe.Pointer(p) n := 0 for *(*uint16)(end) != 0 { end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) n++ } return syscall.UTF16ToString(unsafe.Slice(p, n)) } 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_TOKEN syscall.Errno = 1008 ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113 ) const ( GAA_FLAG_INCLUDE_PREFIX = 0x00000010 GAA_FLAG_INCLUDE_GATEWAYS = 0x0080 ) 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 IpAdapterWinsServerAddress struct { Length uint32 Reserved uint32 Next *IpAdapterWinsServerAddress Address SocketAddress } type IpAdapterGatewayAddress struct { Length uint32 Reserved uint32 Next *IpAdapterGatewayAddress Address SocketAddress } 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 TransmitLinkSpeed uint64 ReceiveLinkSpeed uint64 FirstWinsServerAddress *IpAdapterWinsServerAddress FirstGatewayAddress *IpAdapterGatewayAddress /* more fields might be present here. */ } type SecurityAttributes struct { Length uint16 SecurityDescriptor uintptr InheritHandle bool } type FILE_BASIC_INFO struct { CreationTime int64 LastAccessTime int64 LastWriteTime int64 ChangedTime int64 FileAttributes uint32 // Pad out to 8-byte alignment. // // Without this padding, TestChmod fails due to an argument validation error // in SetFileInformationByHandle on windows/386. // // https://learn.microsoft.com/en-us/cpp/build/reference/zp-struct-member-alignment?view=msvc-170 // says that “The C/C++ headers in the Windows SDK assume the platform's // default alignment is used.” What we see here is padding rather than // alignment, but maybe it is related. _ 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 unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle //sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery //sys GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W 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 WSAEINVAL syscall.Errno = 10022 WSAEMSGSIZE syscall.Errno = 10040 WSAEAFNOSUPPORT syscall.Errno = 10047 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 //sys WSAGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult 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 // Constants from lmshare.h const ( STYPE_DISKTREE = 0x00 STYPE_TEMPORARY = 0x40000000 ) 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 ErrorLoadingGetTempPath2() error { return procGetTempPath2W.Find() } //sys CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW //sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng 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 } type FILE_FULL_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 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 //sys GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) = GetVolumeNameForVolumeMountPointW //sys RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry //sys RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind type SERVICE_STATUS struct { ServiceType uint32 CurrentState uint32 ControlsAccepted uint32 Win32ExitCode uint32 ServiceSpecificExitCode uint32 CheckPoint uint32 WaitHint uint32 } const ( SERVICE_RUNNING = 4 SERVICE_QUERY_STATUS = 4 ) //sys OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) = advapi32.OpenServiceW //sys QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus //sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error) [failretval==0] = advapi32.OpenSCManagerW func FinalPath(h syscall.Handle, flags uint32) (string, error) { buf := make([]uint16, 100) for { n, err := GetFinalPathNameByHandle(h, &buf[0], uint32(len(buf)), flags) if err != nil { return "", err } if n < uint32(len(buf)) { break } buf = make([]uint16, n) } return syscall.UTF16ToString(buf), nil } // QueryPerformanceCounter retrieves the current value of performance counter. // //go:linkname QueryPerformanceCounter func QueryPerformanceCounter() int64 // Implemented in runtime package. // QueryPerformanceFrequency retrieves the frequency of the performance counter. // The returned value is represented as counts per second. // //go:linkname QueryPerformanceFrequency func QueryPerformanceFrequency() int64 // Implemented in runtime package. //sys GetModuleHandle(modulename *uint16) (handle syscall.Handle, err error) = kernel32.GetModuleHandleW // NTStatus corresponds with NTSTATUS, error values returned by ntdll.dll and // other native functions. type NTStatus uint32 func (s NTStatus) Errno() syscall.Errno { return rtlNtStatusToDosErrorNoTeb(s) } func langID(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) } func (s NTStatus) Error() string { return s.Errno().Error() } // x/sys/windows/mkerrors.bash can generate a complete list of NTStatus codes. // // At the moment, we only need a couple, so just put them here manually. // If this list starts getting long, we should consider generating the full set. const ( STATUS_FILE_IS_A_DIRECTORY NTStatus = 0xC00000BA STATUS_NOT_A_DIRECTORY NTStatus = 0xC0000103 STATUS_REPARSE_POINT_ENCOUNTERED NTStatus = 0xC000050B ) // NT Native APIs //sys NtCreateFile(handle *syscall.Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile //sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb