Source file src/internal/syscall/windows/syscall_windows.go

     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  
     5  package windows
     6  
     7  import (
     8  	"sync"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  // CanUseLongPaths is true when the OS supports opting into
    14  // proper long path handling without the need for fixups.
    15  //
    16  //go:linkname CanUseLongPaths
    17  var CanUseLongPaths bool
    18  
    19  // UTF16PtrToString is like UTF16ToString, but takes *uint16
    20  // as a parameter instead of []uint16.
    21  func UTF16PtrToString(p *uint16) string {
    22  	if p == nil {
    23  		return ""
    24  	}
    25  	end := unsafe.Pointer(p)
    26  	n := 0
    27  	for *(*uint16)(end) != 0 {
    28  		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
    29  		n++
    30  	}
    31  	return syscall.UTF16ToString(unsafe.Slice(p, n))
    32  }
    33  
    34  const (
    35  	ERROR_BAD_LENGTH             syscall.Errno = 24
    36  	ERROR_SHARING_VIOLATION      syscall.Errno = 32
    37  	ERROR_LOCK_VIOLATION         syscall.Errno = 33
    38  	ERROR_NOT_SUPPORTED          syscall.Errno = 50
    39  	ERROR_CALL_NOT_IMPLEMENTED   syscall.Errno = 120
    40  	ERROR_INVALID_NAME           syscall.Errno = 123
    41  	ERROR_LOCK_FAILED            syscall.Errno = 167
    42  	ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113
    43  )
    44  
    45  const (
    46  	GAA_FLAG_INCLUDE_PREFIX   = 0x00000010
    47  	GAA_FLAG_INCLUDE_GATEWAYS = 0x0080
    48  )
    49  
    50  const (
    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  
    62  type SocketAddress struct {
    63  	Sockaddr       *syscall.RawSockaddrAny
    64  	SockaddrLength int32
    65  }
    66  
    67  type 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  
    81  type IpAdapterAnycastAddress struct {
    82  	Length  uint32
    83  	Flags   uint32
    84  	Next    *IpAdapterAnycastAddress
    85  	Address SocketAddress
    86  }
    87  
    88  type IpAdapterMulticastAddress struct {
    89  	Length  uint32
    90  	Flags   uint32
    91  	Next    *IpAdapterMulticastAddress
    92  	Address SocketAddress
    93  }
    94  
    95  type IpAdapterDnsServerAdapter struct {
    96  	Length   uint32
    97  	Reserved uint32
    98  	Next     *IpAdapterDnsServerAdapter
    99  	Address  SocketAddress
   100  }
   101  
   102  type IpAdapterPrefix struct {
   103  	Length       uint32
   104  	Flags        uint32
   105  	Next         *IpAdapterPrefix
   106  	Address      SocketAddress
   107  	PrefixLength uint32
   108  }
   109  
   110  type IpAdapterWinsServerAddress struct {
   111  	Length   uint32
   112  	Reserved uint32
   113  	Next     *IpAdapterWinsServerAddress
   114  	Address  SocketAddress
   115  }
   116  
   117  type IpAdapterGatewayAddress struct {
   118  	Length   uint32
   119  	Reserved uint32
   120  	Next     *IpAdapterGatewayAddress
   121  	Address  SocketAddress
   122  }
   123  
   124  type IpAdapterAddresses struct {
   125  	Length                 uint32
   126  	IfIndex                uint32
   127  	Next                   *IpAdapterAddresses
   128  	AdapterName            *byte
   129  	FirstUnicastAddress    *IpAdapterUnicastAddress
   130  	FirstAnycastAddress    *IpAdapterAnycastAddress
   131  	FirstMulticastAddress  *IpAdapterMulticastAddress
   132  	FirstDnsServerAddress  *IpAdapterDnsServerAdapter
   133  	DnsSuffix              *uint16
   134  	Description            *uint16
   135  	FriendlyName           *uint16
   136  	PhysicalAddress        [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
   137  	PhysicalAddressLength  uint32
   138  	Flags                  uint32
   139  	Mtu                    uint32
   140  	IfType                 uint32
   141  	OperStatus             uint32
   142  	Ipv6IfIndex            uint32
   143  	ZoneIndices            [16]uint32
   144  	FirstPrefix            *IpAdapterPrefix
   145  	TransmitLinkSpeed      uint64
   146  	ReceiveLinkSpeed       uint64
   147  	FirstWinsServerAddress *IpAdapterWinsServerAddress
   148  	FirstGatewayAddress    *IpAdapterGatewayAddress
   149  	/* more fields might be present here. */
   150  }
   151  
   152  type SecurityAttributes struct {
   153  	Length             uint16
   154  	SecurityDescriptor uintptr
   155  	InheritHandle      bool
   156  }
   157  
   158  type FILE_BASIC_INFO struct {
   159  	CreationTime   int64
   160  	LastAccessTime int64
   161  	LastWriteTime  int64
   162  	ChangedTime    int64
   163  	FileAttributes uint32
   164  
   165  	// Pad out to 8-byte alignment.
   166  	//
   167  	// Without this padding, TestChmod fails due to an argument validation error
   168  	// in SetFileInformationByHandle on windows/386.
   169  	//
   170  	// https://learn.microsoft.com/en-us/cpp/build/reference/zp-struct-member-alignment?view=msvc-170
   171  	// says that “The C/C++ headers in the Windows SDK assume the platform's
   172  	// default alignment is used.” What we see here is padding rather than
   173  	// alignment, but maybe it is related.
   174  	_ uint32
   175  }
   176  
   177  const (
   178  	IfOperStatusUp             = 1
   179  	IfOperStatusDown           = 2
   180  	IfOperStatusTesting        = 3
   181  	IfOperStatusUnknown        = 4
   182  	IfOperStatusDormant        = 5
   183  	IfOperStatusNotPresent     = 6
   184  	IfOperStatusLowerLayerDown = 7
   185  )
   186  
   187  //sys	GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
   188  //sys	GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
   189  //sys	MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
   190  //sys	GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
   191  //sys	SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
   192  //sys	VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery
   193  //sys	GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W
   194  
   195  const (
   196  	// flags for CreateToolhelp32Snapshot
   197  	TH32CS_SNAPMODULE   = 0x08
   198  	TH32CS_SNAPMODULE32 = 0x10
   199  )
   200  
   201  const MAX_MODULE_NAME32 = 255
   202  
   203  type ModuleEntry32 struct {
   204  	Size         uint32
   205  	ModuleID     uint32
   206  	ProcessID    uint32
   207  	GlblcntUsage uint32
   208  	ProccntUsage uint32
   209  	ModBaseAddr  uintptr
   210  	ModBaseSize  uint32
   211  	ModuleHandle syscall.Handle
   212  	Module       [MAX_MODULE_NAME32 + 1]uint16
   213  	ExePath      [syscall.MAX_PATH]uint16
   214  }
   215  
   216  const SizeofModuleEntry32 = unsafe.Sizeof(ModuleEntry32{})
   217  
   218  //sys	Module32First(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
   219  //sys	Module32Next(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32NextW
   220  
   221  const (
   222  	WSA_FLAG_OVERLAPPED        = 0x01
   223  	WSA_FLAG_NO_HANDLE_INHERIT = 0x80
   224  
   225  	WSAEINVAL       syscall.Errno = 10022
   226  	WSAEMSGSIZE     syscall.Errno = 10040
   227  	WSAEAFNOSUPPORT syscall.Errno = 10047
   228  
   229  	MSG_PEEK   = 0x2
   230  	MSG_TRUNC  = 0x0100
   231  	MSG_CTRUNC = 0x0200
   232  
   233  	socket_error = uintptr(^uint32(0))
   234  )
   235  
   236  var WSAID_WSASENDMSG = syscall.GUID{
   237  	Data1: 0xa441e712,
   238  	Data2: 0x754f,
   239  	Data3: 0x43ca,
   240  	Data4: [8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
   241  }
   242  
   243  var WSAID_WSARECVMSG = syscall.GUID{
   244  	Data1: 0xf689d7c8,
   245  	Data2: 0x6f1f,
   246  	Data3: 0x436b,
   247  	Data4: [8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
   248  }
   249  
   250  var sendRecvMsgFunc struct {
   251  	once     sync.Once
   252  	sendAddr uintptr
   253  	recvAddr uintptr
   254  	err      error
   255  }
   256  
   257  type WSAMsg struct {
   258  	Name        syscall.Pointer
   259  	Namelen     int32
   260  	Buffers     *syscall.WSABuf
   261  	BufferCount uint32
   262  	Control     syscall.WSABuf
   263  	Flags       uint32
   264  }
   265  
   266  //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
   267  //sys	WSAGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
   268  
   269  func loadWSASendRecvMsg() error {
   270  	sendRecvMsgFunc.once.Do(func() {
   271  		var s syscall.Handle
   272  		s, sendRecvMsgFunc.err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
   273  		if sendRecvMsgFunc.err != nil {
   274  			return
   275  		}
   276  		defer syscall.CloseHandle(s)
   277  		var n uint32
   278  		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
   279  			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
   280  			(*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)),
   281  			uint32(unsafe.Sizeof(WSAID_WSARECVMSG)),
   282  			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)),
   283  			uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)),
   284  			&n, nil, 0)
   285  		if sendRecvMsgFunc.err != nil {
   286  			return
   287  		}
   288  		sendRecvMsgFunc.err = syscall.WSAIoctl(s,
   289  			syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
   290  			(*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)),
   291  			uint32(unsafe.Sizeof(WSAID_WSASENDMSG)),
   292  			(*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)),
   293  			uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)),
   294  			&n, nil, 0)
   295  	})
   296  	return sendRecvMsgFunc.err
   297  }
   298  
   299  func WSASendMsg(fd syscall.Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
   300  	err := loadWSASendRecvMsg()
   301  	if err != nil {
   302  		return err
   303  	}
   304  	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)))
   305  	if r1 == socket_error {
   306  		if e1 != 0 {
   307  			err = errnoErr(e1)
   308  		} else {
   309  			err = syscall.EINVAL
   310  		}
   311  	}
   312  	return err
   313  }
   314  
   315  func WSARecvMsg(fd syscall.Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
   316  	err := loadWSASendRecvMsg()
   317  	if err != nil {
   318  		return err
   319  	}
   320  	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)
   321  	if r1 == socket_error {
   322  		if e1 != 0 {
   323  			err = errnoErr(e1)
   324  		} else {
   325  			err = syscall.EINVAL
   326  		}
   327  	}
   328  	return err
   329  }
   330  
   331  const (
   332  	ComputerNameNetBIOS                   = 0
   333  	ComputerNameDnsHostname               = 1
   334  	ComputerNameDnsDomain                 = 2
   335  	ComputerNameDnsFullyQualified         = 3
   336  	ComputerNamePhysicalNetBIOS           = 4
   337  	ComputerNamePhysicalDnsHostname       = 5
   338  	ComputerNamePhysicalDnsDomain         = 6
   339  	ComputerNamePhysicalDnsFullyQualified = 7
   340  	ComputerNameMax                       = 8
   341  
   342  	MOVEFILE_REPLACE_EXISTING      = 0x1
   343  	MOVEFILE_COPY_ALLOWED          = 0x2
   344  	MOVEFILE_DELAY_UNTIL_REBOOT    = 0x4
   345  	MOVEFILE_WRITE_THROUGH         = 0x8
   346  	MOVEFILE_CREATE_HARDLINK       = 0x10
   347  	MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20
   348  )
   349  
   350  func Rename(oldpath, newpath string) error {
   351  	from, err := syscall.UTF16PtrFromString(oldpath)
   352  	if err != nil {
   353  		return err
   354  	}
   355  	to, err := syscall.UTF16PtrFromString(newpath)
   356  	if err != nil {
   357  		return err
   358  	}
   359  	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
   360  }
   361  
   362  //sys LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.LockFileEx
   363  //sys UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.UnlockFileEx
   364  
   365  const (
   366  	LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
   367  	LOCKFILE_EXCLUSIVE_LOCK   = 0x00000002
   368  )
   369  
   370  const MB_ERR_INVALID_CHARS = 8
   371  
   372  //sys	GetACP() (acp uint32) = kernel32.GetACP
   373  //sys	GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
   374  //sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
   375  //sys	GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread
   376  
   377  // Constants from lmshare.h
   378  const (
   379  	STYPE_DISKTREE  = 0x00
   380  	STYPE_TEMPORARY = 0x40000000
   381  )
   382  
   383  type SHARE_INFO_2 struct {
   384  	Netname     *uint16
   385  	Type        uint32
   386  	Remark      *uint16
   387  	Permissions uint32
   388  	MaxUses     uint32
   389  	CurrentUses uint32
   390  	Path        *uint16
   391  	Passwd      *uint16
   392  }
   393  
   394  //sys  NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd
   395  //sys  NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel
   396  
   397  const (
   398  	FILE_NAME_NORMALIZED = 0x0
   399  	FILE_NAME_OPENED     = 0x8
   400  
   401  	VOLUME_NAME_DOS  = 0x0
   402  	VOLUME_NAME_GUID = 0x1
   403  	VOLUME_NAME_NONE = 0x4
   404  	VOLUME_NAME_NT   = 0x2
   405  )
   406  
   407  //sys	GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
   408  
   409  func ErrorLoadingGetTempPath2() error {
   410  	return procGetTempPath2W.Find()
   411  }
   412  
   413  //sys	CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
   414  //sys	DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
   415  //sys	CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
   416  
   417  //sys	ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng
   418  
   419  type FILE_ID_BOTH_DIR_INFO struct {
   420  	NextEntryOffset uint32
   421  	FileIndex       uint32
   422  	CreationTime    syscall.Filetime
   423  	LastAccessTime  syscall.Filetime
   424  	LastWriteTime   syscall.Filetime
   425  	ChangeTime      syscall.Filetime
   426  	EndOfFile       uint64
   427  	AllocationSize  uint64
   428  	FileAttributes  uint32
   429  	FileNameLength  uint32
   430  	EaSize          uint32
   431  	ShortNameLength uint32
   432  	ShortName       [12]uint16
   433  	FileID          uint64
   434  	FileName        [1]uint16
   435  }
   436  
   437  type FILE_FULL_DIR_INFO struct {
   438  	NextEntryOffset uint32
   439  	FileIndex       uint32
   440  	CreationTime    syscall.Filetime
   441  	LastAccessTime  syscall.Filetime
   442  	LastWriteTime   syscall.Filetime
   443  	ChangeTime      syscall.Filetime
   444  	EndOfFile       uint64
   445  	AllocationSize  uint64
   446  	FileAttributes  uint32
   447  	FileNameLength  uint32
   448  	EaSize          uint32
   449  	FileName        [1]uint16
   450  }
   451  
   452  //sys	GetVolumeInformationByHandle(file syscall.Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) = GetVolumeInformationByHandleW
   453  //sys	GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) = GetVolumeNameForVolumeMountPointW
   454  
   455  //sys	RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry
   456  //sys	RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind
   457  
   458  type SERVICE_STATUS struct {
   459  	ServiceType             uint32
   460  	CurrentState            uint32
   461  	ControlsAccepted        uint32
   462  	Win32ExitCode           uint32
   463  	ServiceSpecificExitCode uint32
   464  	CheckPoint              uint32
   465  	WaitHint                uint32
   466  }
   467  
   468  const (
   469  	SERVICE_RUNNING      = 4
   470  	SERVICE_QUERY_STATUS = 4
   471  )
   472  
   473  //sys    OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) = advapi32.OpenServiceW
   474  //sys	QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error)  = advapi32.QueryServiceStatus
   475  //sys    OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error)  [failretval==0] = advapi32.OpenSCManagerW
   476  
   477  func FinalPath(h syscall.Handle, flags uint32) (string, error) {
   478  	buf := make([]uint16, 100)
   479  	for {
   480  		n, err := GetFinalPathNameByHandle(h, &buf[0], uint32(len(buf)), flags)
   481  		if err != nil {
   482  			return "", err
   483  		}
   484  		if n < uint32(len(buf)) {
   485  			break
   486  		}
   487  		buf = make([]uint16, n)
   488  	}
   489  	return syscall.UTF16ToString(buf), nil
   490  }
   491  
   492  // QueryPerformanceCounter retrieves the current value of performance counter.
   493  //
   494  //go:linkname QueryPerformanceCounter
   495  func QueryPerformanceCounter() int64 // Implemented in runtime package.
   496  
   497  // QueryPerformanceFrequency retrieves the frequency of the performance counter.
   498  // The returned value is represented as counts per second.
   499  //
   500  //go:linkname QueryPerformanceFrequency
   501  func QueryPerformanceFrequency() int64 // Implemented in runtime package.
   502  

View as plain text