github.com/gaukas/wazerofs@v0.1.0/sysfs/file_windows.go (about) 1 package sysfs 2 3 import ( 4 "errors" 5 "syscall" 6 "unsafe" 7 8 "github.com/tetratelabs/wazero/experimental/sys" 9 ) 10 11 const ( 12 nonBlockingFileReadSupported = true 13 nonBlockingFileWriteSupported = false 14 15 _ERROR_IO_INCOMPLETE = syscall.Errno(996) 16 ) 17 18 var kernel32 = syscall.NewLazyDLL("kernel32.dll") 19 20 // procPeekNamedPipe is the syscall.LazyProc in kernel32 for PeekNamedPipe 21 var ( 22 // procPeekNamedPipe is the syscall.LazyProc in kernel32 for PeekNamedPipe 23 procPeekNamedPipe = kernel32.NewProc("PeekNamedPipe") 24 // procGetOverlappedResult is the syscall.LazyProc in kernel32 for GetOverlappedResult 25 procGetOverlappedResult = kernel32.NewProc("GetOverlappedResult") 26 // procCreateEventW is the syscall.LazyProc in kernel32 for CreateEventW 27 procCreateEventW = kernel32.NewProc("CreateEventW") 28 ) 29 30 // readFd returns ENOSYS on unsupported platforms. 31 // 32 // PeekNamedPipe: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe 33 // "GetFileType can assist in determining what device type the handle refers to. A console handle presents as FILE_TYPE_CHAR." 34 // https://learn.microsoft.com/en-us/windows/console/console-handles 35 func readFd(fd uintptr, buf []byte) (int, sys.Errno) { 36 handle := syscall.Handle(fd) 37 fileType, err := syscall.GetFileType(handle) 38 if err != nil { 39 return 0, sys.UnwrapOSError(err) 40 } 41 if fileType&syscall.FILE_TYPE_CHAR == 0 { 42 return -1, sys.ENOSYS 43 } 44 n, errno := peekNamedPipe(handle) 45 if errno == syscall.ERROR_BROKEN_PIPE { 46 return 0, 0 47 } 48 if n == 0 { 49 return -1, sys.EAGAIN 50 } 51 un, err := syscall.Read(handle, buf[0:n]) 52 return un, sys.UnwrapOSError(err) 53 } 54 55 func writeFd(fd uintptr, buf []byte) (int, sys.Errno) { 56 return -1, sys.ENOSYS 57 } 58 59 func writeSocket(fd uintptr, buf []byte) (int, sys.Errno) { 60 var done uint32 61 var overlapped syscall.Overlapped 62 errno := syscall.WriteFile(syscall.Handle(fd), buf, &done, &overlapped) 63 if errors.Is(errno, syscall.ERROR_IO_PENDING) { 64 errno = syscall.EAGAIN 65 } 66 return int(done), sys.UnwrapOSError(errno) 67 } 68 69 // peekNamedPipe partially exposes PeekNamedPipe from the Win32 API 70 // see https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe 71 func peekNamedPipe(handle syscall.Handle) (uint32, syscall.Errno) { 72 var totalBytesAvail uint32 73 totalBytesPtr := unsafe.Pointer(&totalBytesAvail) 74 _, _, errno := syscall.SyscallN( 75 procPeekNamedPipe.Addr(), 76 uintptr(handle), // [in] HANDLE hNamedPipe, 77 0, // [out, optional] LPVOID lpBuffer, 78 0, // [in] DWORD nBufferSize, 79 0, // [out, optional] LPDWORD lpBytesRead 80 uintptr(totalBytesPtr), // [out, optional] LPDWORD lpTotalBytesAvail, 81 0) // [out, optional] LPDWORD lpBytesLeftThisMessage 82 return totalBytesAvail, errno 83 } 84 85 func rmdir(path string) sys.Errno { 86 err := syscall.Rmdir(path) 87 return sys.UnwrapOSError(err) 88 } 89 90 func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, wait bool) (uint32, syscall.Errno) { 91 var totalBytesAvail uint32 92 var bwait uintptr 93 if wait { 94 bwait = 0xFFFFFFFF 95 } 96 totalBytesPtr := unsafe.Pointer(&totalBytesAvail) 97 _, _, errno := syscall.SyscallN( 98 procGetOverlappedResult.Addr(), 99 uintptr(handle), // [in] HANDLE hFile, 100 uintptr(unsafe.Pointer(overlapped)), // [in] LPOVERLAPPED lpOverlapped, 101 uintptr(totalBytesPtr), // [out] LPDWORD lpNumberOfBytesTransferred, 102 bwait) // [in] BOOL bWait 103 return totalBytesAvail, errno 104 } 105 106 func createEventW(lpEventAttributes *syscall.SecurityAttributes, bManualReset bool, bInitialState bool, lpName *uint16) (uintptr, syscall.Errno) { 107 var manualReset uintptr 108 var initialState uintptr 109 if bManualReset { 110 manualReset = 1 111 } 112 if bInitialState { 113 initialState = 1 114 } 115 handle, _, errno := syscall.SyscallN( 116 procCreateEventW.Addr(), 117 uintptr(unsafe.Pointer(lpEventAttributes)), // [in] LPSECURITY_ATTRIBUTES lpEventAttributes, 118 manualReset, // [in] BOOL bManualReset, 119 initialState, // [in] BOOL bInitialState, 120 uintptr(unsafe.Pointer(lpName)), // [in, opt]LPCWSTR lpName, 121 ) 122 123 return handle, errno 124 }