1// Copyright 2009 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// Windows system calls. 6 7package windows 8 9import ( 10 errorspkg "errors" 11 "sync" 12 "syscall" 13 "time" 14 "unicode/utf16" 15 "unsafe" 16 17 "golang.org/x/sys/internal/unsafeheader" 18) 19 20type Handle uintptr 21 22const ( 23 InvalidHandle = ^Handle(0) 24 25 // Flags for DefineDosDevice. 26 DDD_EXACT_MATCH_ON_REMOVE = 0x00000004 27 DDD_NO_BROADCAST_SYSTEM = 0x00000008 28 DDD_RAW_TARGET_PATH = 0x00000001 29 DDD_REMOVE_DEFINITION = 0x00000002 30 31 // Return values for GetDriveType. 32 DRIVE_UNKNOWN = 0 33 DRIVE_NO_ROOT_DIR = 1 34 DRIVE_REMOVABLE = 2 35 DRIVE_FIXED = 3 36 DRIVE_REMOTE = 4 37 DRIVE_CDROM = 5 38 DRIVE_RAMDISK = 6 39 40 // File system flags from GetVolumeInformation and GetVolumeInformationByHandle. 41 FILE_CASE_SENSITIVE_SEARCH = 0x00000001 42 FILE_CASE_PRESERVED_NAMES = 0x00000002 43 FILE_FILE_COMPRESSION = 0x00000010 44 FILE_DAX_VOLUME = 0x20000000 45 FILE_NAMED_STREAMS = 0x00040000 46 FILE_PERSISTENT_ACLS = 0x00000008 47 FILE_READ_ONLY_VOLUME = 0x00080000 48 FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000 49 FILE_SUPPORTS_ENCRYPTION = 0x00020000 50 FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000 51 FILE_SUPPORTS_HARD_LINKS = 0x00400000 52 FILE_SUPPORTS_OBJECT_IDS = 0x00010000 53 FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000 54 FILE_SUPPORTS_REPARSE_POINTS = 0x00000080 55 FILE_SUPPORTS_SPARSE_FILES = 0x00000040 56 FILE_SUPPORTS_TRANSACTIONS = 0x00200000 57 FILE_SUPPORTS_USN_JOURNAL = 0x02000000 58 FILE_UNICODE_ON_DISK = 0x00000004 59 FILE_VOLUME_IS_COMPRESSED = 0x00008000 60 FILE_VOLUME_QUOTAS = 0x00000020 61 62 // Flags for LockFileEx. 63 LOCKFILE_FAIL_IMMEDIATELY = 0x00000001 64 LOCKFILE_EXCLUSIVE_LOCK = 0x00000002 65 66 // Return values of SleepEx and other APC functions 67 STATUS_USER_APC = 0x000000C0 68 WAIT_IO_COMPLETION = STATUS_USER_APC 69) 70 71// StringToUTF16 is deprecated. Use UTF16FromString instead. 72// If s contains a NUL byte this function panics instead of 73// returning an error. 74func StringToUTF16(s string) []uint16 { 75 a, err := UTF16FromString(s) 76 if err != nil { 77 panic("windows: string with NUL passed to StringToUTF16") 78 } 79 return a 80} 81 82// UTF16FromString returns the UTF-16 encoding of the UTF-8 string 83// s, with a terminating NUL added. If s contains a NUL byte at any 84// location, it returns (nil, syscall.EINVAL). 85func UTF16FromString(s string) ([]uint16, error) { 86 for i := 0; i < len(s); i++ { 87 if s[i] == 0 { 88 return nil, syscall.EINVAL 89 } 90 } 91 return utf16.Encode([]rune(s + "\x00")), nil 92} 93 94// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, 95// with a terminating NUL and any bytes after the NUL removed. 96func UTF16ToString(s []uint16) string { 97 for i, v := range s { 98 if v == 0 { 99 s = s[:i] 100 break 101 } 102 } 103 return string(utf16.Decode(s)) 104} 105 106// StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead. 107// If s contains a NUL byte this function panics instead of 108// returning an error. 109func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } 110 111// UTF16PtrFromString returns pointer to the UTF-16 encoding of 112// the UTF-8 string s, with a terminating NUL added. If s 113// contains a NUL byte at any location, it returns (nil, syscall.EINVAL). 114func UTF16PtrFromString(s string) (*uint16, error) { 115 a, err := UTF16FromString(s) 116 if err != nil { 117 return nil, err 118 } 119 return &a[0], nil 120} 121 122// UTF16PtrToString takes a pointer to a UTF-16 sequence and returns the corresponding UTF-8 encoded string. 123// If the pointer is nil, it returns the empty string. It assumes that the UTF-16 sequence is terminated 124// at a zero word; if the zero word is not present, the program may crash. 125func UTF16PtrToString(p *uint16) string { 126 if p == nil { 127 return "" 128 } 129 if *p == 0 { 130 return "" 131 } 132 133 // Find NUL terminator. 134 n := 0 135 for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ { 136 ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p)) 137 } 138 139 var s []uint16 140 h := (*unsafeheader.Slice)(unsafe.Pointer(&s)) 141 h.Data = unsafe.Pointer(p) 142 h.Len = n 143 h.Cap = n 144 145 return string(utf16.Decode(s)) 146} 147 148func Getpagesize() int { return 4096 } 149 150// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. 151// This is useful when interoperating with Windows code requiring callbacks. 152// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. 153func NewCallback(fn interface{}) uintptr { 154 return syscall.NewCallback(fn) 155} 156 157// NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention. 158// This is useful when interoperating with Windows code requiring callbacks. 159// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. 160func NewCallbackCDecl(fn interface{}) uintptr { 161 return syscall.NewCallbackCDecl(fn) 162} 163 164// windows api calls 165 166//sys GetLastError() (lasterr error) 167//sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW 168//sys LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) = LoadLibraryExW 169//sys FreeLibrary(handle Handle) (err error) 170//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) 171//sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW 172//sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW 173//sys GetVersion() (ver uint32, err error) 174//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW 175//sys ExitProcess(exitcode uint32) 176//sys IsWow64Process(handle Handle, isWow64 *bool) (err error) = IsWow64Process 177//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW 178//sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) 179//sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) 180//sys GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) 181//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff] 182//sys CloseHandle(handle Handle) (err error) 183//sys GetStdHandle(stdhandle uint32) (handle Handle, err error) [failretval==InvalidHandle] 184//sys SetStdHandle(stdhandle uint32, handle Handle) (err error) 185//sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW 186//sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW 187//sys FindClose(handle Handle) (err error) 188//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) 189//sys GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) 190//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW 191//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW 192//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW 193//sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW 194//sys DeleteFile(path *uint16) (err error) = DeleteFileW 195//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW 196//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW 197//sys LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) 198//sys UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) 199//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW 200//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW 201//sys SetEndOfFile(handle Handle) (err error) 202//sys GetSystemTimeAsFileTime(time *Filetime) 203//sys GetSystemTimePreciseAsFileTime(time *Filetime) 204//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] 205//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) 206//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) 207//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) 208//sys CancelIo(s Handle) (err error) 209//sys CancelIoEx(s Handle, o *Overlapped) (err error) 210//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW 211//sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) 212//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW 213//sys shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) = shell32.SHGetKnownFolderPath 214//sys TerminateProcess(handle Handle, exitcode uint32) (err error) 215//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) 216//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW 217//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) 218//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) 219//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] 220//sys waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] = WaitForMultipleObjects 221//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW 222//sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) 223//sys GetFileType(filehandle Handle) (n uint32, err error) 224//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW 225//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext 226//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom 227//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW 228//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW 229//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW 230//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW 231//sys CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock 232//sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock 233//sys getTickCount64() (ms uint64) = kernel32.GetTickCount64 234//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) 235//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW 236//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW 237//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW 238//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW 239//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW 240//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0] 241//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) 242//sys FlushFileBuffers(handle Handle) (err error) 243//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW 244//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW 245//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW 246//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW 247//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) 248//sys UnmapViewOfFile(addr uintptr) (err error) 249//sys FlushViewOfFile(addr uintptr, length uintptr) (err error) 250//sys VirtualLock(addr uintptr, length uintptr) (err error) 251//sys VirtualUnlock(addr uintptr, length uintptr) (err error) 252//sys VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) = kernel32.VirtualAlloc 253//sys VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) = kernel32.VirtualFree 254//sys VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) = kernel32.VirtualProtect 255//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile 256//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW 257//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW 258//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore 259//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore 260//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore 261//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore 262//sys CertDeleteCertificateFromStore(certContext *CertContext) (err error) = crypt32.CertDeleteCertificateFromStore 263//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain 264//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain 265//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext 266//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext 267//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy 268//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW 269//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey 270//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW 271//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW 272//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW 273//sys GetCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId 274//sys ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) = kernel32.ProcessIdToSessionId 275//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode 276//sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode 277//sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo 278//sys setConsoleCursorPosition(console Handle, position uint32) (err error) = kernel32.SetConsoleCursorPosition 279//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW 280//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW 281//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot 282//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW 283//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW 284//sys Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) 285//sys Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) 286//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) 287// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. 288//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW 289//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW 290//sys GetCurrentThreadId() (id uint32) 291//sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) = kernel32.CreateEventW 292//sys CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateEventExW 293//sys OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenEventW 294//sys SetEvent(event Handle) (err error) = kernel32.SetEvent 295//sys ResetEvent(event Handle) (err error) = kernel32.ResetEvent 296//sys PulseEvent(event Handle) (err error) = kernel32.PulseEvent 297//sys CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) = kernel32.CreateMutexW 298//sys CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateMutexExW 299//sys OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenMutexW 300//sys ReleaseMutex(mutex Handle) (err error) = kernel32.ReleaseMutex 301//sys SleepEx(milliseconds uint32, alertable bool) (ret uint32) = kernel32.SleepEx 302//sys CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) = kernel32.CreateJobObjectW 303//sys AssignProcessToJobObject(job Handle, process Handle) (err error) = kernel32.AssignProcessToJobObject 304//sys TerminateJobObject(job Handle, exitCode uint32) (err error) = kernel32.TerminateJobObject 305//sys SetErrorMode(mode uint32) (ret uint32) = kernel32.SetErrorMode 306//sys ResumeThread(thread Handle) (ret uint32, err error) [failretval==0xffffffff] = kernel32.ResumeThread 307//sys SetPriorityClass(process Handle, priorityClass uint32) (err error) = kernel32.SetPriorityClass 308//sys GetPriorityClass(process Handle) (ret uint32, err error) = kernel32.GetPriorityClass 309//sys QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobObjectInformation uintptr, JobObjectInformationLength uint32, retlen *uint32) (err error) = kernel32.QueryInformationJobObject 310//sys SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) 311//sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) 312//sys GetProcessId(process Handle) (id uint32, err error) 313//sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) 314//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost 315//sys GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) 316//sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) 317 318// Volume Management Functions 319//sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW 320//sys DeleteVolumeMountPoint(volumeMountPoint *uint16) (err error) = DeleteVolumeMountPointW 321//sys FindFirstVolume(volumeName *uint16, bufferLength uint32) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstVolumeW 322//sys FindFirstVolumeMountPoint(rootPathName *uint16, volumeMountPoint *uint16, bufferLength uint32) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstVolumeMountPointW 323//sys FindNextVolume(findVolume Handle, volumeName *uint16, bufferLength uint32) (err error) = FindNextVolumeW 324//sys FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) = FindNextVolumeMountPointW 325//sys FindVolumeClose(findVolume Handle) (err error) 326//sys FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) 327//sys GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = GetDiskFreeSpaceExW 328//sys GetDriveType(rootPathName *uint16) (driveType uint32) = GetDriveTypeW 329//sys GetLogicalDrives() (drivesBitMask uint32, err error) [failretval==0] 330//sys GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) [failretval==0] = GetLogicalDriveStringsW 331//sys GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) = GetVolumeInformationW 332//sys GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) = GetVolumeInformationByHandleW 333//sys GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) = GetVolumeNameForVolumeMountPointW 334//sys GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength uint32) (err error) = GetVolumePathNameW 335//sys GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16, bufferLength uint32, returnLength *uint32) (err error) = GetVolumePathNamesForVolumeNameW 336//sys QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) [failretval==0] = QueryDosDeviceW 337//sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW 338//sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW 339//sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW 340//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx 341//sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW 342//sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters 343//sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters 344//sys clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) = ole32.CLSIDFromString 345//sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2 346//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid 347//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree 348//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion 349//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers 350//sys getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetProcessPreferredUILanguages 351//sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages 352//sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages 353//sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages 354//sys GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW 355 356// Process Status API (PSAPI) 357//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses 358 359// syscall interface implementation for other packages 360 361// GetCurrentProcess returns the handle for the current process. 362// It is a pseudo handle that does not need to be closed. 363// The returned error is always nil. 364// 365// Deprecated: use CurrentProcess for the same Handle without the nil 366// error. 367func GetCurrentProcess() (Handle, error) { 368 return CurrentProcess(), nil 369} 370 371// CurrentProcess returns the handle for the current process. 372// It is a pseudo handle that does not need to be closed. 373func CurrentProcess() Handle { return Handle(^uintptr(1 - 1)) } 374 375// GetCurrentThread returns the handle for the current thread. 376// It is a pseudo handle that does not need to be closed. 377// The returned error is always nil. 378// 379// Deprecated: use CurrentThread for the same Handle without the nil 380// error. 381func GetCurrentThread() (Handle, error) { 382 return CurrentThread(), nil 383} 384 385// CurrentThread returns the handle for the current thread. 386// It is a pseudo handle that does not need to be closed. 387func CurrentThread() Handle { return Handle(^uintptr(2 - 1)) } 388 389// GetProcAddressByOrdinal retrieves the address of the exported 390// function from module by ordinal. 391func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err error) { 392 r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0) 393 proc = uintptr(r0) 394 if proc == 0 { 395 err = errnoErr(e1) 396 } 397 return 398} 399 400func Exit(code int) { ExitProcess(uint32(code)) } 401 402func makeInheritSa() *SecurityAttributes { 403 var sa SecurityAttributes 404 sa.Length = uint32(unsafe.Sizeof(sa)) 405 sa.InheritHandle = 1 406 return &sa 407} 408 409func Open(path string, mode int, perm uint32) (fd Handle, err error) { 410 if len(path) == 0 { 411 return InvalidHandle, ERROR_FILE_NOT_FOUND 412 } 413 pathp, err := UTF16PtrFromString(path) 414 if err != nil { 415 return InvalidHandle, err 416 } 417 var access uint32 418 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) { 419 case O_RDONLY: 420 access = GENERIC_READ 421 case O_WRONLY: 422 access = GENERIC_WRITE 423 case O_RDWR: 424 access = GENERIC_READ | GENERIC_WRITE 425 } 426 if mode&O_CREAT != 0 { 427 access |= GENERIC_WRITE 428 } 429 if mode&O_APPEND != 0 { 430 access &^= GENERIC_WRITE 431 access |= FILE_APPEND_DATA 432 } 433 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE) 434 var sa *SecurityAttributes 435 if mode&O_CLOEXEC == 0 { 436 sa = makeInheritSa() 437 } 438 var createmode uint32 439 switch { 440 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): 441 createmode = CREATE_NEW 442 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): 443 createmode = CREATE_ALWAYS 444 case mode&O_CREAT == O_CREAT: 445 createmode = OPEN_ALWAYS 446 case mode&O_TRUNC == O_TRUNC: 447 createmode = TRUNCATE_EXISTING 448 default: 449 createmode = OPEN_EXISTING 450 } 451 var attrs uint32 = FILE_ATTRIBUTE_NORMAL 452 if perm&S_IWRITE == 0 { 453 attrs = FILE_ATTRIBUTE_READONLY 454 } 455 h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) 456 return h, e 457} 458 459func Read(fd Handle, p []byte) (n int, err error) { 460 var done uint32 461 e := ReadFile(fd, p, &done, nil) 462 if e != nil { 463 if e == ERROR_BROKEN_PIPE { 464 // NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin 465 return 0, nil 466 } 467 return 0, e 468 } 469 if raceenabled { 470 if done > 0 { 471 raceWriteRange(unsafe.Pointer(&p[0]), int(done)) 472 } 473 raceAcquire(unsafe.Pointer(&ioSync)) 474 } 475 return int(done), nil 476} 477 478func Write(fd Handle, p []byte) (n int, err error) { 479 if raceenabled { 480 raceReleaseMerge(unsafe.Pointer(&ioSync)) 481 } 482 var done uint32 483 e := WriteFile(fd, p, &done, nil) 484 if e != nil { 485 return 0, e 486 } 487 if raceenabled && done > 0 { 488 raceReadRange(unsafe.Pointer(&p[0]), int(done)) 489 } 490 return int(done), nil 491} 492 493var ioSync int64 494 495func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) { 496 var w uint32 497 switch whence { 498 case 0: 499 w = FILE_BEGIN 500 case 1: 501 w = FILE_CURRENT 502 case 2: 503 w = FILE_END 504 } 505 hi := int32(offset >> 32) 506 lo := int32(offset) 507 // use GetFileType to check pipe, pipe can't do seek 508 ft, _ := GetFileType(fd) 509 if ft == FILE_TYPE_PIPE { 510 return 0, syscall.EPIPE 511 } 512 rlo, e := SetFilePointer(fd, lo, &hi, w) 513 if e != nil { 514 return 0, e 515 } 516 return int64(hi)<<32 + int64(rlo), nil 517} 518 519func Close(fd Handle) (err error) { 520 return CloseHandle(fd) 521} 522 523var ( 524 Stdin = getStdHandle(STD_INPUT_HANDLE) 525 Stdout = getStdHandle(STD_OUTPUT_HANDLE) 526 Stderr = getStdHandle(STD_ERROR_HANDLE) 527) 528 529func getStdHandle(stdhandle uint32) (fd Handle) { 530 r, _ := GetStdHandle(stdhandle) 531 CloseOnExec(r) 532 return r 533} 534 535const ImplementsGetwd = true 536 537func Getwd() (wd string, err error) { 538 b := make([]uint16, 300) 539 n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) 540 if e != nil { 541 return "", e 542 } 543 return string(utf16.Decode(b[0:n])), nil 544} 545 546func Chdir(path string) (err error) { 547 pathp, err := UTF16PtrFromString(path) 548 if err != nil { 549 return err 550 } 551 return SetCurrentDirectory(pathp) 552} 553 554func Mkdir(path string, mode uint32) (err error) { 555 pathp, err := UTF16PtrFromString(path) 556 if err != nil { 557 return err 558 } 559 return CreateDirectory(pathp, nil) 560} 561 562func Rmdir(path string) (err error) { 563 pathp, err := UTF16PtrFromString(path) 564 if err != nil { 565 return err 566 } 567 return RemoveDirectory(pathp) 568} 569 570func Unlink(path string) (err error) { 571 pathp, err := UTF16PtrFromString(path) 572 if err != nil { 573 return err 574 } 575 return DeleteFile(pathp) 576} 577 578func Rename(oldpath, newpath string) (err error) { 579 from, err := UTF16PtrFromString(oldpath) 580 if err != nil { 581 return err 582 } 583 to, err := UTF16PtrFromString(newpath) 584 if err != nil { 585 return err 586 } 587 return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) 588} 589 590func ComputerName() (name string, err error) { 591 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1 592 b := make([]uint16, n) 593 e := GetComputerName(&b[0], &n) 594 if e != nil { 595 return "", e 596 } 597 return string(utf16.Decode(b[0:n])), nil 598} 599 600func DurationSinceBoot() time.Duration { 601 return time.Duration(getTickCount64()) * time.Millisecond 602} 603 604func Ftruncate(fd Handle, length int64) (err error) { 605 curoffset, e := Seek(fd, 0, 1) 606 if e != nil { 607 return e 608 } 609 defer Seek(fd, curoffset, 0) 610 _, e = Seek(fd, length, 0) 611 if e != nil { 612 return e 613 } 614 e = SetEndOfFile(fd) 615 if e != nil { 616 return e 617 } 618 return nil 619} 620 621func Gettimeofday(tv *Timeval) (err error) { 622 var ft Filetime 623 GetSystemTimeAsFileTime(&ft) 624 *tv = NsecToTimeval(ft.Nanoseconds()) 625 return nil 626} 627 628func Pipe(p []Handle) (err error) { 629 if len(p) != 2 { 630 return syscall.EINVAL 631 } 632 var r, w Handle 633 e := CreatePipe(&r, &w, makeInheritSa(), 0) 634 if e != nil { 635 return e 636 } 637 p[0] = r 638 p[1] = w 639 return nil 640} 641 642func Utimes(path string, tv []Timeval) (err error) { 643 if len(tv) != 2 { 644 return syscall.EINVAL 645 } 646 pathp, e := UTF16PtrFromString(path) 647 if e != nil { 648 return e 649 } 650 h, e := CreateFile(pathp, 651 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 652 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) 653 if e != nil { 654 return e 655 } 656 defer Close(h) 657 a := NsecToFiletime(tv[0].Nanoseconds()) 658 w := NsecToFiletime(tv[1].Nanoseconds()) 659 return SetFileTime(h, nil, &a, &w) 660} 661 662func UtimesNano(path string, ts []Timespec) (err error) { 663 if len(ts) != 2 { 664 return syscall.EINVAL 665 } 666 pathp, e := UTF16PtrFromString(path) 667 if e != nil { 668 return e 669 } 670 h, e := CreateFile(pathp, 671 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 672 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) 673 if e != nil { 674 return e 675 } 676 defer Close(h) 677 a := NsecToFiletime(TimespecToNsec(ts[0])) 678 w := NsecToFiletime(TimespecToNsec(ts[1])) 679 return SetFileTime(h, nil, &a, &w) 680} 681 682func Fsync(fd Handle) (err error) { 683 return FlushFileBuffers(fd) 684} 685 686func Chmod(path string, mode uint32) (err error) { 687 p, e := UTF16PtrFromString(path) 688 if e != nil { 689 return e 690 } 691 attrs, e := GetFileAttributes(p) 692 if e != nil { 693 return e 694 } 695 if mode&S_IWRITE != 0 { 696 attrs &^= FILE_ATTRIBUTE_READONLY 697 } else { 698 attrs |= FILE_ATTRIBUTE_READONLY 699 } 700 return SetFileAttributes(p, attrs) 701} 702 703func LoadGetSystemTimePreciseAsFileTime() error { 704 return procGetSystemTimePreciseAsFileTime.Find() 705} 706 707func LoadCancelIoEx() error { 708 return procCancelIoEx.Find() 709} 710 711func LoadSetFileCompletionNotificationModes() error { 712 return procSetFileCompletionNotificationModes.Find() 713} 714 715func WaitForMultipleObjects(handles []Handle, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { 716 // Every other win32 array API takes arguments as "pointer, count", except for this function. So we 717 // can't declare it as a usual [] type, because mksyscall will use the opposite order. We therefore 718 // trivially stub this ourselves. 719 720 var handlePtr *Handle 721 if len(handles) > 0 { 722 handlePtr = &handles[0] 723 } 724 return waitForMultipleObjects(uint32(len(handles)), uintptr(unsafe.Pointer(handlePtr)), waitAll, waitMilliseconds) 725} 726 727// net api calls 728 729const socket_error = uintptr(^uint32(0)) 730 731//sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup 732//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup 733//sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl 734//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket 735//sys sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) [failretval==socket_error] = ws2_32.sendto 736//sys recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) [failretval==-1] = ws2_32.recvfrom 737//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt 738//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt 739//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind 740//sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect 741//sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname 742//sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername 743//sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen 744//sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown 745//sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket 746//sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx 747//sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs 748//sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv 749//sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend 750//sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom 751//sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo 752//sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname 753//sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname 754//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs 755//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname 756//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W 757//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree 758//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W 759//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW 760//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW 761//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry 762//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo 763//sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes 764//sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW 765//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses 766//sys GetACP() (acp uint32) = kernel32.GetACP 767//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar 768 769// For testing: clients can set this flag to force 770// creation of IPv6 sockets to return EAFNOSUPPORT. 771var SocketDisableIPv6 bool 772 773type RawSockaddrInet4 struct { 774 Family uint16 775 Port uint16 776 Addr [4]byte /* in_addr */ 777 Zero [8]uint8 778} 779 780type RawSockaddrInet6 struct { 781 Family uint16 782 Port uint16 783 Flowinfo uint32 784 Addr [16]byte /* in6_addr */ 785 Scope_id uint32 786} 787 788type RawSockaddr struct { 789 Family uint16 790 Data [14]int8 791} 792 793type RawSockaddrAny struct { 794 Addr RawSockaddr 795 Pad [100]int8 796} 797 798type Sockaddr interface { 799 sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs 800} 801 802type SockaddrInet4 struct { 803 Port int 804 Addr [4]byte 805 raw RawSockaddrInet4 806} 807 808func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { 809 if sa.Port < 0 || sa.Port > 0xFFFF { 810 return nil, 0, syscall.EINVAL 811 } 812 sa.raw.Family = AF_INET 813 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 814 p[0] = byte(sa.Port >> 8) 815 p[1] = byte(sa.Port) 816 for i := 0; i < len(sa.Addr); i++ { 817 sa.raw.Addr[i] = sa.Addr[i] 818 } 819 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil 820} 821 822type SockaddrInet6 struct { 823 Port int 824 ZoneId uint32 825 Addr [16]byte 826 raw RawSockaddrInet6 827} 828 829func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { 830 if sa.Port < 0 || sa.Port > 0xFFFF { 831 return nil, 0, syscall.EINVAL 832 } 833 sa.raw.Family = AF_INET6 834 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 835 p[0] = byte(sa.Port >> 8) 836 p[1] = byte(sa.Port) 837 sa.raw.Scope_id = sa.ZoneId 838 for i := 0; i < len(sa.Addr); i++ { 839 sa.raw.Addr[i] = sa.Addr[i] 840 } 841 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil 842} 843 844type RawSockaddrUnix struct { 845 Family uint16 846 Path [UNIX_PATH_MAX]int8 847} 848 849type SockaddrUnix struct { 850 Name string 851 raw RawSockaddrUnix 852} 853 854func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { 855 name := sa.Name 856 n := len(name) 857 if n > len(sa.raw.Path) { 858 return nil, 0, syscall.EINVAL 859 } 860 if n == len(sa.raw.Path) && name[0] != '@' { 861 return nil, 0, syscall.EINVAL 862 } 863 sa.raw.Family = AF_UNIX 864 for i := 0; i < n; i++ { 865 sa.raw.Path[i] = int8(name[i]) 866 } 867 // length is family (uint16), name, NUL. 868 sl := int32(2) 869 if n > 0 { 870 sl += int32(n) + 1 871 } 872 if sa.raw.Path[0] == '@' { 873 sa.raw.Path[0] = 0 874 // Don't count trailing NUL for abstract address. 875 sl-- 876 } 877 878 return unsafe.Pointer(&sa.raw), sl, nil 879} 880 881func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { 882 switch rsa.Addr.Family { 883 case AF_UNIX: 884 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 885 sa := new(SockaddrUnix) 886 if pp.Path[0] == 0 { 887 // "Abstract" Unix domain socket. 888 // Rewrite leading NUL as @ for textual display. 889 // (This is the standard convention.) 890 // Not friendly to overwrite in place, 891 // but the callers below don't care. 892 pp.Path[0] = '@' 893 } 894 895 // Assume path ends at NUL. 896 // This is not technically the Linux semantics for 897 // abstract Unix domain sockets--they are supposed 898 // to be uninterpreted fixed-size binary blobs--but 899 // everyone uses this convention. 900 n := 0 901 for n < len(pp.Path) && pp.Path[n] != 0 { 902 n++ 903 } 904 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 905 sa.Name = string(bytes) 906 return sa, nil 907 908 case AF_INET: 909 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 910 sa := new(SockaddrInet4) 911 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 912 sa.Port = int(p[0])<<8 + int(p[1]) 913 for i := 0; i < len(sa.Addr); i++ { 914 sa.Addr[i] = pp.Addr[i] 915 } 916 return sa, nil 917 918 case AF_INET6: 919 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 920 sa := new(SockaddrInet6) 921 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 922 sa.Port = int(p[0])<<8 + int(p[1]) 923 sa.ZoneId = pp.Scope_id 924 for i := 0; i < len(sa.Addr); i++ { 925 sa.Addr[i] = pp.Addr[i] 926 } 927 return sa, nil 928 } 929 return nil, syscall.EAFNOSUPPORT 930} 931 932func Socket(domain, typ, proto int) (fd Handle, err error) { 933 if domain == AF_INET6 && SocketDisableIPv6 { 934 return InvalidHandle, syscall.EAFNOSUPPORT 935 } 936 return socket(int32(domain), int32(typ), int32(proto)) 937} 938 939func SetsockoptInt(fd Handle, level, opt int, value int) (err error) { 940 v := int32(value) 941 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v))) 942} 943 944func Bind(fd Handle, sa Sockaddr) (err error) { 945 ptr, n, err := sa.sockaddr() 946 if err != nil { 947 return err 948 } 949 return bind(fd, ptr, n) 950} 951 952func Connect(fd Handle, sa Sockaddr) (err error) { 953 ptr, n, err := sa.sockaddr() 954 if err != nil { 955 return err 956 } 957 return connect(fd, ptr, n) 958} 959 960func Getsockname(fd Handle) (sa Sockaddr, err error) { 961 var rsa RawSockaddrAny 962 l := int32(unsafe.Sizeof(rsa)) 963 if err = getsockname(fd, &rsa, &l); err != nil { 964 return 965 } 966 return rsa.Sockaddr() 967} 968 969func Getpeername(fd Handle) (sa Sockaddr, err error) { 970 var rsa RawSockaddrAny 971 l := int32(unsafe.Sizeof(rsa)) 972 if err = getpeername(fd, &rsa, &l); err != nil { 973 return 974 } 975 return rsa.Sockaddr() 976} 977 978func Listen(s Handle, n int) (err error) { 979 return listen(s, int32(n)) 980} 981 982func Shutdown(fd Handle, how int) (err error) { 983 return shutdown(fd, int32(how)) 984} 985 986func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) { 987 rsa, l, err := to.sockaddr() 988 if err != nil { 989 return err 990 } 991 return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine) 992} 993 994func LoadGetAddrInfo() error { 995 return procGetAddrInfoW.Find() 996} 997 998var connectExFunc struct { 999 once sync.Once 1000 addr uintptr 1001 err error 1002} 1003 1004func LoadConnectEx() error { 1005 connectExFunc.once.Do(func() { 1006 var s Handle 1007 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 1008 if connectExFunc.err != nil { 1009 return 1010 } 1011 defer CloseHandle(s) 1012 var n uint32 1013 connectExFunc.err = WSAIoctl(s, 1014 SIO_GET_EXTENSION_FUNCTION_POINTER, 1015 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)), 1016 uint32(unsafe.Sizeof(WSAID_CONNECTEX)), 1017 (*byte)(unsafe.Pointer(&connectExFunc.addr)), 1018 uint32(unsafe.Sizeof(connectExFunc.addr)), 1019 &n, nil, 0) 1020 }) 1021 return connectExFunc.err 1022} 1023 1024func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) { 1025 r1, _, e1 := syscall.Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0) 1026 if r1 == 0 { 1027 if e1 != 0 { 1028 err = error(e1) 1029 } else { 1030 err = syscall.EINVAL 1031 } 1032 } 1033 return 1034} 1035 1036func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error { 1037 err := LoadConnectEx() 1038 if err != nil { 1039 return errorspkg.New("failed to find ConnectEx: " + err.Error()) 1040 } 1041 ptr, n, err := sa.sockaddr() 1042 if err != nil { 1043 return err 1044 } 1045 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) 1046} 1047 1048var sendRecvMsgFunc struct { 1049 once sync.Once 1050 sendAddr uintptr 1051 recvAddr uintptr 1052 err error 1053} 1054 1055func loadWSASendRecvMsg() error { 1056 sendRecvMsgFunc.once.Do(func() { 1057 var s Handle 1058 s, sendRecvMsgFunc.err = Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) 1059 if sendRecvMsgFunc.err != nil { 1060 return 1061 } 1062 defer CloseHandle(s) 1063 var n uint32 1064 sendRecvMsgFunc.err = WSAIoctl(s, 1065 SIO_GET_EXTENSION_FUNCTION_POINTER, 1066 (*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)), 1067 uint32(unsafe.Sizeof(WSAID_WSARECVMSG)), 1068 (*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)), 1069 uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)), 1070 &n, nil, 0) 1071 if sendRecvMsgFunc.err != nil { 1072 return 1073 } 1074 sendRecvMsgFunc.err = WSAIoctl(s, 1075 SIO_GET_EXTENSION_FUNCTION_POINTER, 1076 (*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)), 1077 uint32(unsafe.Sizeof(WSAID_WSASENDMSG)), 1078 (*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)), 1079 uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)), 1080 &n, nil, 0) 1081 }) 1082 return sendRecvMsgFunc.err 1083} 1084 1085func WSASendMsg(fd Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *Overlapped, croutine *byte) error { 1086 err := loadWSASendRecvMsg() 1087 if err != nil { 1088 return err 1089 } 1090 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))) 1091 if r1 == socket_error { 1092 err = errnoErr(e1) 1093 } 1094 return err 1095} 1096 1097func WSARecvMsg(fd Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *Overlapped, croutine *byte) error { 1098 err := loadWSASendRecvMsg() 1099 if err != nil { 1100 return err 1101 } 1102 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) 1103 if r1 == socket_error { 1104 err = errnoErr(e1) 1105 } 1106 return err 1107} 1108 1109// Invented structures to support what package os expects. 1110type Rusage struct { 1111 CreationTime Filetime 1112 ExitTime Filetime 1113 KernelTime Filetime 1114 UserTime Filetime 1115} 1116 1117type WaitStatus struct { 1118 ExitCode uint32 1119} 1120 1121func (w WaitStatus) Exited() bool { return true } 1122 1123func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) } 1124 1125func (w WaitStatus) Signal() Signal { return -1 } 1126 1127func (w WaitStatus) CoreDump() bool { return false } 1128 1129func (w WaitStatus) Stopped() bool { return false } 1130 1131func (w WaitStatus) Continued() bool { return false } 1132 1133func (w WaitStatus) StopSignal() Signal { return -1 } 1134 1135func (w WaitStatus) Signaled() bool { return false } 1136 1137func (w WaitStatus) TrapCause() int { return -1 } 1138 1139// Timespec is an invented structure on Windows, but here for 1140// consistency with the corresponding package for other operating systems. 1141type Timespec struct { 1142 Sec int64 1143 Nsec int64 1144} 1145 1146func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } 1147 1148func NsecToTimespec(nsec int64) (ts Timespec) { 1149 ts.Sec = nsec / 1e9 1150 ts.Nsec = nsec % 1e9 1151 return 1152} 1153 1154// TODO(brainman): fix all needed for net 1155 1156func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, syscall.EWINDOWS } 1157 1158func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) { 1159 var rsa RawSockaddrAny 1160 l := int32(unsafe.Sizeof(rsa)) 1161 n32, err := recvfrom(fd, p, int32(flags), &rsa, &l) 1162 n = int(n32) 1163 if err != nil { 1164 return 1165 } 1166 from, err = rsa.Sockaddr() 1167 return 1168} 1169 1170func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { 1171 ptr, l, err := to.sockaddr() 1172 if err != nil { 1173 return err 1174 } 1175 return sendto(fd, p, int32(flags), ptr, l) 1176} 1177 1178func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return syscall.EWINDOWS } 1179 1180// The Linger struct is wrong but we only noticed after Go 1. 1181// sysLinger is the real system call structure. 1182 1183// BUG(brainman): The definition of Linger is not appropriate for direct use 1184// with Setsockopt and Getsockopt. 1185// Use SetsockoptLinger instead. 1186 1187type Linger struct { 1188 Onoff int32 1189 Linger int32 1190} 1191 1192type sysLinger struct { 1193 Onoff uint16 1194 Linger uint16 1195} 1196 1197type IPMreq struct { 1198 Multiaddr [4]byte /* in_addr */ 1199 Interface [4]byte /* in_addr */ 1200} 1201 1202type IPv6Mreq struct { 1203 Multiaddr [16]byte /* in6_addr */ 1204 Interface uint32 1205} 1206 1207func GetsockoptInt(fd Handle, level, opt int) (int, error) { 1208 v := int32(0) 1209 l := int32(unsafe.Sizeof(v)) 1210 err := Getsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), &l) 1211 return int(v), err 1212} 1213 1214func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { 1215 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)} 1216 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys))) 1217} 1218 1219func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { 1220 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) 1221} 1222func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { 1223 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) 1224} 1225func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { 1226 return syscall.EWINDOWS 1227} 1228 1229func Getpid() (pid int) { return int(GetCurrentProcessId()) } 1230 1231func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) { 1232 // NOTE(rsc): The Win32finddata struct is wrong for the system call: 1233 // the two paths are each one uint16 short. Use the correct struct, 1234 // a win32finddata1, and then copy the results out. 1235 // There is no loss of expressivity here, because the final 1236 // uint16, if it is used, is supposed to be a NUL, and Go doesn't need that. 1237 // For Go 1.1, we might avoid the allocation of win32finddata1 here 1238 // by adding a final Bug [2]uint16 field to the struct and then 1239 // adjusting the fields in the result directly. 1240 var data1 win32finddata1 1241 handle, err = findFirstFile1(name, &data1) 1242 if err == nil { 1243 copyFindData(data, &data1) 1244 } 1245 return 1246} 1247 1248func FindNextFile(handle Handle, data *Win32finddata) (err error) { 1249 var data1 win32finddata1 1250 err = findNextFile1(handle, &data1) 1251 if err == nil { 1252 copyFindData(data, &data1) 1253 } 1254 return 1255} 1256 1257func getProcessEntry(pid int) (*ProcessEntry32, error) { 1258 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 1259 if err != nil { 1260 return nil, err 1261 } 1262 defer CloseHandle(snapshot) 1263 var procEntry ProcessEntry32 1264 procEntry.Size = uint32(unsafe.Sizeof(procEntry)) 1265 if err = Process32First(snapshot, &procEntry); err != nil { 1266 return nil, err 1267 } 1268 for { 1269 if procEntry.ProcessID == uint32(pid) { 1270 return &procEntry, nil 1271 } 1272 err = Process32Next(snapshot, &procEntry) 1273 if err != nil { 1274 return nil, err 1275 } 1276 } 1277} 1278 1279func Getppid() (ppid int) { 1280 pe, err := getProcessEntry(Getpid()) 1281 if err != nil { 1282 return -1 1283 } 1284 return int(pe.ParentProcessID) 1285} 1286 1287// TODO(brainman): fix all needed for os 1288func Fchdir(fd Handle) (err error) { return syscall.EWINDOWS } 1289func Link(oldpath, newpath string) (err error) { return syscall.EWINDOWS } 1290func Symlink(path, link string) (err error) { return syscall.EWINDOWS } 1291 1292func Fchmod(fd Handle, mode uint32) (err error) { return syscall.EWINDOWS } 1293func Chown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS } 1294func Lchown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS } 1295func Fchown(fd Handle, uid int, gid int) (err error) { return syscall.EWINDOWS } 1296 1297func Getuid() (uid int) { return -1 } 1298func Geteuid() (euid int) { return -1 } 1299func Getgid() (gid int) { return -1 } 1300func Getegid() (egid int) { return -1 } 1301func Getgroups() (gids []int, err error) { return nil, syscall.EWINDOWS } 1302 1303type Signal int 1304 1305func (s Signal) Signal() {} 1306 1307func (s Signal) String() string { 1308 if 0 <= s && int(s) < len(signals) { 1309 str := signals[s] 1310 if str != "" { 1311 return str 1312 } 1313 } 1314 return "signal " + itoa(int(s)) 1315} 1316 1317func LoadCreateSymbolicLink() error { 1318 return procCreateSymbolicLinkW.Find() 1319} 1320 1321// Readlink returns the destination of the named symbolic link. 1322func Readlink(path string, buf []byte) (n int, err error) { 1323 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING, 1324 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0) 1325 if err != nil { 1326 return -1, err 1327 } 1328 defer CloseHandle(fd) 1329 1330 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE) 1331 var bytesReturned uint32 1332 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil) 1333 if err != nil { 1334 return -1, err 1335 } 1336 1337 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0])) 1338 var s string 1339 switch rdb.ReparseTag { 1340 case IO_REPARSE_TAG_SYMLINK: 1341 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) 1342 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) 1343 s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2]) 1344 case IO_REPARSE_TAG_MOUNT_POINT: 1345 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) 1346 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) 1347 s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2]) 1348 default: 1349 // the path is not a symlink or junction but another type of reparse 1350 // point 1351 return -1, syscall.ENOENT 1352 } 1353 n = copy(buf, []byte(s)) 1354 1355 return n, nil 1356} 1357 1358// GUIDFromString parses a string in the form of 1359// "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" into a GUID. 1360func GUIDFromString(str string) (GUID, error) { 1361 guid := GUID{} 1362 str16, err := syscall.UTF16PtrFromString(str) 1363 if err != nil { 1364 return guid, err 1365 } 1366 err = clsidFromString(str16, &guid) 1367 if err != nil { 1368 return guid, err 1369 } 1370 return guid, nil 1371} 1372 1373// GenerateGUID creates a new random GUID. 1374func GenerateGUID() (GUID, error) { 1375 guid := GUID{} 1376 err := coCreateGuid(&guid) 1377 if err != nil { 1378 return guid, err 1379 } 1380 return guid, nil 1381} 1382 1383// String returns the canonical string form of the GUID, 1384// in the form of "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}". 1385func (guid GUID) String() string { 1386 var str [100]uint16 1387 chars := stringFromGUID2(&guid, &str[0], int32(len(str))) 1388 if chars <= 1 { 1389 return "" 1390 } 1391 return string(utf16.Decode(str[:chars-1])) 1392} 1393 1394// KnownFolderPath returns a well-known folder path for the current user, specified by one of 1395// the FOLDERID_ constants, and chosen and optionally created based on a KF_ flag. 1396func KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, error) { 1397 return Token(0).KnownFolderPath(folderID, flags) 1398} 1399 1400// KnownFolderPath returns a well-known folder path for the user token, specified by one of 1401// the FOLDERID_ constants, and chosen and optionally created based on a KF_ flag. 1402func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, error) { 1403 var p *uint16 1404 err := shGetKnownFolderPath(folderID, flags, t, &p) 1405 if err != nil { 1406 return "", err 1407 } 1408 defer CoTaskMemFree(unsafe.Pointer(p)) 1409 return UTF16PtrToString(p), nil 1410} 1411 1412// RtlGetVersion returns the version of the underlying operating system, ignoring 1413// manifest semantics but is affected by the application compatibility layer. 1414func RtlGetVersion() *OsVersionInfoEx { 1415 info := &OsVersionInfoEx{} 1416 info.osVersionInfoSize = uint32(unsafe.Sizeof(*info)) 1417 // According to documentation, this function always succeeds. 1418 // The function doesn't even check the validity of the 1419 // osVersionInfoSize member. Disassembling ntdll.dll indicates 1420 // that the documentation is indeed correct about that. 1421 _ = rtlGetVersion(info) 1422 return info 1423} 1424 1425// RtlGetNtVersionNumbers returns the version of the underlying operating system, 1426// ignoring manifest semantics and the application compatibility layer. 1427func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) { 1428 rtlGetNtVersionNumbers(&majorVersion, &minorVersion, &buildNumber) 1429 buildNumber &= 0xffff 1430 return 1431} 1432 1433// GetProcessPreferredUILanguages retrieves the process preferred UI languages. 1434func GetProcessPreferredUILanguages(flags uint32) ([]string, error) { 1435 return getUILanguages(flags, getProcessPreferredUILanguages) 1436} 1437 1438// GetThreadPreferredUILanguages retrieves the thread preferred UI languages for the current thread. 1439func GetThreadPreferredUILanguages(flags uint32) ([]string, error) { 1440 return getUILanguages(flags, getThreadPreferredUILanguages) 1441} 1442 1443// GetUserPreferredUILanguages retrieves information about the user preferred UI languages. 1444func GetUserPreferredUILanguages(flags uint32) ([]string, error) { 1445 return getUILanguages(flags, getUserPreferredUILanguages) 1446} 1447 1448// GetSystemPreferredUILanguages retrieves the system preferred UI languages. 1449func GetSystemPreferredUILanguages(flags uint32) ([]string, error) { 1450 return getUILanguages(flags, getSystemPreferredUILanguages) 1451} 1452 1453func getUILanguages(flags uint32, f func(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) error) ([]string, error) { 1454 size := uint32(128) 1455 for { 1456 var numLanguages uint32 1457 buf := make([]uint16, size) 1458 err := f(flags, &numLanguages, &buf[0], &size) 1459 if err == ERROR_INSUFFICIENT_BUFFER { 1460 continue 1461 } 1462 if err != nil { 1463 return nil, err 1464 } 1465 buf = buf[:size] 1466 if numLanguages == 0 || len(buf) == 0 { // GetProcessPreferredUILanguages may return numLanguages==0 with "\0\0" 1467 return []string{}, nil 1468 } 1469 if buf[len(buf)-1] == 0 { 1470 buf = buf[:len(buf)-1] // remove terminating null 1471 } 1472 languages := make([]string, 0, numLanguages) 1473 from := 0 1474 for i, c := range buf { 1475 if c == 0 { 1476 languages = append(languages, string(utf16.Decode(buf[from:i]))) 1477 from = i + 1 1478 } 1479 } 1480 return languages, nil 1481 } 1482} 1483 1484func SetConsoleCursorPosition(console Handle, position Coord) error { 1485 return setConsoleCursorPosition(console, *((*uint32)(unsafe.Pointer(&position)))) 1486} 1487