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 "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 17var CanUseLongPaths bool 18 19// UTF16PtrToString is like UTF16ToString, but takes *uint16 20// as a parameter instead of []uint16. 21func 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 34const ( 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 45const ( 46 GAA_FLAG_INCLUDE_PREFIX = 0x00000010 47 GAA_FLAG_INCLUDE_GATEWAYS = 0x0080 48) 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 IpAdapterWinsServerAddress struct { 111 Length uint32 112 Reserved uint32 113 Next *IpAdapterWinsServerAddress 114 Address SocketAddress 115} 116 117type IpAdapterGatewayAddress struct { 118 Length uint32 119 Reserved uint32 120 Next *IpAdapterGatewayAddress 121 Address SocketAddress 122} 123 124type 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 152type SecurityAttributes struct { 153 Length uint16 154 SecurityDescriptor uintptr 155 InheritHandle bool 156} 157 158type 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 177const ( 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 195const ( 196 // flags for CreateToolhelp32Snapshot 197 TH32CS_SNAPMODULE = 0x08 198 TH32CS_SNAPMODULE32 = 0x10 199) 200 201const MAX_MODULE_NAME32 = 255 202 203type 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 216const 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 221const ( 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 236var 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 243var 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 250var sendRecvMsgFunc struct { 251 once sync.Once 252 sendAddr uintptr 253 recvAddr uintptr 254 err error 255} 256 257type 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 269func 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 299func 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 315func 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 331const ( 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 350func 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 365const ( 366 LOCKFILE_FAIL_IMMEDIATELY = 0x00000001 367 LOCKFILE_EXCLUSIVE_LOCK = 0x00000002 368) 369 370const 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 378const ( 379 STYPE_DISKTREE = 0x00 380 STYPE_TEMPORARY = 0x40000000 381) 382 383type 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 397const ( 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 409func 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 419type 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 437type 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 458type 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 468const ( 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 477func 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 495func 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 501func QueryPerformanceFrequency() int64 // Implemented in runtime package. 502