Black Lives Matter. Support the Equal Justice Initiative.

Source file src/syscall/syscall_windows.go

Documentation: syscall

     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  
     7  package syscall
     8  
     9  import (
    10  	errorspkg "errors"
    11  	"internal/itoa"
    12  	"internal/oserror"
    13  	"internal/race"
    14  	"internal/unsafeheader"
    15  	"runtime"
    16  	"sync"
    17  	"unicode/utf16"
    18  	"unsafe"
    19  )
    20  
    21  type Handle uintptr
    22  
    23  const InvalidHandle = ^Handle(0)
    24  
    25  // StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s,
    26  // with a terminating NUL added. If s contains a NUL byte this
    27  // function panics instead of returning an error.
    28  //
    29  // Deprecated: Use UTF16FromString instead.
    30  func StringToUTF16(s string) []uint16 {
    31  	a, err := UTF16FromString(s)
    32  	if err != nil {
    33  		panic("syscall: string with NUL passed to StringToUTF16")
    34  	}
    35  	return a
    36  }
    37  
    38  // UTF16FromString returns the UTF-16 encoding of the UTF-8 string
    39  // s, with a terminating NUL added. If s contains a NUL byte at any
    40  // location, it returns (nil, EINVAL).
    41  func UTF16FromString(s string) ([]uint16, error) {
    42  	for i := 0; i < len(s); i++ {
    43  		if s[i] == 0 {
    44  			return nil, EINVAL
    45  		}
    46  	}
    47  	return utf16.Encode([]rune(s + "\x00")), nil
    48  }
    49  
    50  // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
    51  // with a terminating NUL removed.
    52  func UTF16ToString(s []uint16) string {
    53  	for i, v := range s {
    54  		if v == 0 {
    55  			s = s[0:i]
    56  			break
    57  		}
    58  	}
    59  	return string(utf16.Decode(s))
    60  }
    61  
    62  // utf16PtrToString is like UTF16ToString, but takes *uint16
    63  // as a parameter instead of []uint16.
    64  func utf16PtrToString(p *uint16) string {
    65  	if p == nil {
    66  		return ""
    67  	}
    68  	// Find NUL terminator.
    69  	end := unsafe.Pointer(p)
    70  	n := 0
    71  	for *(*uint16)(end) != 0 {
    72  		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
    73  		n++
    74  	}
    75  	// Turn *uint16 into []uint16.
    76  	var s []uint16
    77  	hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
    78  	hdr.Data = unsafe.Pointer(p)
    79  	hdr.Cap = n
    80  	hdr.Len = n
    81  	// Decode []uint16 into string.
    82  	return string(utf16.Decode(s))
    83  }
    84  
    85  // StringToUTF16Ptr returns pointer to the UTF-16 encoding of
    86  // the UTF-8 string s, with a terminating NUL added. If s
    87  // contains a NUL byte this function panics instead of
    88  // returning an error.
    89  //
    90  // Deprecated: Use UTF16PtrFromString instead.
    91  func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
    92  
    93  // UTF16PtrFromString returns pointer to the UTF-16 encoding of
    94  // the UTF-8 string s, with a terminating NUL added. If s
    95  // contains a NUL byte at any location, it returns (nil, EINVAL).
    96  func UTF16PtrFromString(s string) (*uint16, error) {
    97  	a, err := UTF16FromString(s)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	return &a[0], nil
   102  }
   103  
   104  // Errno is the Windows error number.
   105  //
   106  // Errno values can be tested against error values from the os package
   107  // using errors.Is. For example:
   108  //
   109  //	_, _, err := syscall.Syscall(...)
   110  //	if errors.Is(err, fs.ErrNotExist) ...
   111  type Errno uintptr
   112  
   113  func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) }
   114  
   115  // FormatMessage is deprecated (msgsrc should be uintptr, not uint32, but can
   116  // not be changed due to the Go 1 compatibility guarantee).
   117  //
   118  // Deprecated: Use FormatMessage from golang.org/x/sys/windows instead.
   119  func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
   120  	return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args)
   121  }
   122  
   123  func (e Errno) Error() string {
   124  	// deal with special go errors
   125  	idx := int(e - APPLICATION_ERROR)
   126  	if 0 <= idx && idx < len(errors) {
   127  		return errors[idx]
   128  	}
   129  	// ask windows for the remaining errors
   130  	var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
   131  	b := make([]uint16, 300)
   132  	n, err := formatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil)
   133  	if err != nil {
   134  		n, err = formatMessage(flags, 0, uint32(e), 0, b, nil)
   135  		if err != nil {
   136  			return "winapi error #" + itoa.Itoa(int(e))
   137  		}
   138  	}
   139  	// trim terminating \r and \n
   140  	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
   141  	}
   142  	return string(utf16.Decode(b[:n]))
   143  }
   144  
   145  const _ERROR_BAD_NETPATH = Errno(53)
   146  
   147  func (e Errno) Is(target error) bool {
   148  	switch target {
   149  	case oserror.ErrPermission:
   150  		return e == ERROR_ACCESS_DENIED
   151  	case oserror.ErrExist:
   152  		return e == ERROR_ALREADY_EXISTS ||
   153  			e == ERROR_DIR_NOT_EMPTY ||
   154  			e == ERROR_FILE_EXISTS
   155  	case oserror.ErrNotExist:
   156  		return e == ERROR_FILE_NOT_FOUND ||
   157  			e == _ERROR_BAD_NETPATH ||
   158  			e == ERROR_PATH_NOT_FOUND
   159  	}
   160  	return false
   161  }
   162  
   163  func (e Errno) Temporary() bool {
   164  	return e == EINTR || e == EMFILE || e.Timeout()
   165  }
   166  
   167  func (e Errno) Timeout() bool {
   168  	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
   169  }
   170  
   171  // Implemented in runtime/syscall_windows.go.
   172  func compileCallback(fn interface{}, cleanstack bool) uintptr
   173  
   174  // NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
   175  // This is useful when interoperating with Windows code requiring callbacks.
   176  // The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
   177  // Only a limited number of callbacks may be created in a single Go process, and any memory allocated
   178  // for these callbacks is never released.
   179  // Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created.
   180  func NewCallback(fn interface{}) uintptr {
   181  	return compileCallback(fn, true)
   182  }
   183  
   184  // NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention.
   185  // This is useful when interoperating with Windows code requiring callbacks.
   186  // The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
   187  // Only a limited number of callbacks may be created in a single Go process, and any memory allocated
   188  // for these callbacks is never released.
   189  // Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created.
   190  func NewCallbackCDecl(fn interface{}) uintptr {
   191  	return compileCallback(fn, false)
   192  }
   193  
   194  // windows api calls
   195  
   196  //sys	GetLastError() (lasterr error)
   197  //sys	LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW
   198  //sys	FreeLibrary(handle Handle) (err error)
   199  //sys	GetProcAddress(module Handle, procname string) (proc uintptr, err error)
   200  //sys	GetVersion() (ver uint32, err error)
   201  //sys	rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
   202  //sys	formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
   203  //sys	ExitProcess(exitcode uint32)
   204  //sys	CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
   205  //sys	ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
   206  //sys	WriteFile(