mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
The unsafe.Pointer -> uintptr conversion must happen when calling syscall.Syscall, not when calling the auto-generated wrapper function, else the Go compiler doesn't know that it has to keep the pointer alive. This can cause undefined behavior and stack corruption. Fixes #73135. Fixes #73112 (potentially). Fixes #73128 (potentially). Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-race Change-Id: Ib3ad8b99618d8997bfd0742c0e44aeda696856c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/662575 Reviewed-by: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Carlos Amedee <carlos@golang.org> Auto-Submit: Carlos Amedee <carlos@golang.org>
562 lines
18 KiB
Go
562 lines
18 KiB
Go
// 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
|
|
ERROR_CANT_ACCESS_FILE syscall.Errno = 1920
|
|
)
|
|
|
|
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
|
|
|
|
const (
|
|
PIPE_ACCESS_INBOUND = 0x00000001
|
|
PIPE_ACCESS_OUTBOUND = 0x00000002
|
|
PIPE_ACCESS_DUPLEX = 0x00000003
|
|
|
|
PIPE_TYPE_BYTE = 0x00000000
|
|
PIPE_TYPE_MESSAGE = 0x00000004
|
|
)
|
|
|
|
//sys CreateIoCompletionPort(filehandle syscall.Handle, cphandle syscall.Handle, key uintptr, threadcnt uint32) (handle syscall.Handle, err error)
|
|
//sys GetOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, done *uint32, wait bool) (err error)
|
|
//sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
|
|
|
// 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_DIRECTORY_NOT_EMPTY NTStatus = 0xC0000101
|
|
STATUS_NOT_A_DIRECTORY NTStatus = 0xC0000103
|
|
STATUS_CANNOT_DELETE NTStatus = 0xC0000121
|
|
STATUS_REPARSE_POINT_ENCOUNTERED NTStatus = 0xC000050B
|
|
)
|
|
|
|
const (
|
|
FileModeInformation = 16
|
|
)
|
|
|
|
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_mode_information
|
|
type FILE_MODE_INFORMATION struct {
|
|
Mode uint32
|
|
}
|
|
|
|
// 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 NtOpenFile(handle *syscall.Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, options uint32) (ntstatus error) = ntdll.NtOpenFile
|
|
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
|
|
//sys NtSetInformationFile(handle syscall.Handle, iosb *IO_STATUS_BLOCK, inBuffer uintptr, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile
|
|
//sys RtlIsDosDeviceName_U(name *uint16) (ret uint32) = ntdll.RtlIsDosDeviceName_U
|
|
//sys NtQueryInformationFile(handle syscall.Handle, iosb *IO_STATUS_BLOCK, inBuffer unsafe.Pointer, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtQueryInformationFile
|