| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // Windows system calls. | |
| package syscall | |
| import ( | |
| "unsafe" | |
| "utf16" | |
| ) | |
| const OS = "mingw" | |
| /* | |
| small demo to detect version of windows you are running: | |
| package main | |
| import ( | |
| "syscall" | |
| ) | |
| func abort(funcname string, err int) { | |
| panic(funcname + " failed: " + syscall.Errstr(err)) | |
| } | |
| func print_version(v uint32) { | |
| major := byte(v) | |
| minor := uint8(v >> 8) | |
| build := uint16(v >> 16) | |
| print("windows version ", major, ".", minor, " (Build ", build, ")\n") | |
| } | |
| func main() { | |
| h, err := syscall.LoadLibrary("kernel32.dll") | |
| if err != 0 { | |
| abort("LoadLibrary", err) | |
| } | |
| defer syscall.FreeLibrary(h) | |
| proc, err := syscall.GetProcAddress(h, "GetVersion") | |
| if err != 0 { | |
| abort("GetProcAddress", err) | |
| } | |
| r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0) | |
| print_version(uint32(r)) | |
| } | |
| */ | |
| // StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s, | |
| // with a terminating NUL added. | |
| func StringToUTF16(s string) []uint16 { return utf16.Encode([]int(s + "\x00")) } | |
| // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, | |
| // with a terminating NUL removed. | |
| func UTF16ToString(s []uint16) string { | |
| if n := len(s); n > 0 && s[n-1] == 0 { | |
| s = s[0 : n-1] | |
| } | |
| return string(utf16.Decode(s)) | |
| } | |
| // StringToUTF16Ptr returns pointer to the UTF-16 encoding of | |
| // the UTF-8 string s, with a terminating NUL added. | |
| func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } | |
| // dll helpers | |
| // implemented in ../pkg/runtime/mingw/syscall.cgo | |
| func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, lasterr uintptr) | |
| func loadlibraryex(filename uintptr) (handle uint32) | |
| func getprocaddress(handle uint32, procname uintptr) (proc uintptr) | |
| func loadDll(fname string) uint32 { | |
| m := loadlibraryex(uintptr(unsafe.Pointer(StringBytePtr(fname)))) | |
| if m == 0 { | |
| panic("syscall: could not LoadLibraryEx " + fname) | |
| } | |
| return m | |
| } | |
| func getSysProcAddr(m uint32, pname string) uintptr { | |
| p := getprocaddress(m, uintptr(unsafe.Pointer(StringBytePtr(pname)))) | |
| if p == 0 { | |
| panic("syscall: could not GetProcAddress for " + pname) | |
| } | |
| return p | |
| } | |
| // windows api calls | |
| //sys GetLastError() (lasterrno int) | |
| //sys LoadLibrary(libname string) (handle uint32, errno int) = LoadLibraryW | |
| //sys FreeLibrary(handle uint32) (ok bool, errno int) | |
| //sys GetProcAddress(module uint32, procname string) (proc uint32, errno int) | |
| //sys GetVersion() (ver uint32, errno int) | |
| //sys FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) = FormatMessageW | |
| //sys ExitProcess(exitcode uint32) | |
| //sys CreateFile(name *uint16, access uint32, mode uint32, sa *byte, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) [failretval=-1] = CreateFileW | |
| //sys ReadFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int) | |
| //sys WriteFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int) | |
| //sys SetFilePointer(handle int32, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) [failretval=0xffffffff] | |
| //sys CloseHandle(handle int32) (ok bool, errno int) | |
| //sys GetStdHandle(stdhandle int32) (handle int32, errno int) [failretval=-1] | |
| // syscall interface implementation for other packages | |
| func Errstr(errno int) string { | |
| if errno == EMINGW { | |
| return "not supported by windows" | |
| } | |
| var b = make([]uint16, 300) | |
| n, err := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ARGUMENT_ARRAY, 0, uint32(errno), 0, b, nil) | |
| if err != 0 { | |
| return "error " + str(errno) + " (FormatMessage failed with err=" + str(err) + ")" | |
| } | |
| return UTF16ToString(b[0 : n-1]) | |
| } | |
| func Exit(code int) { ExitProcess(uint32(code)) } | |
| func Open(path string, mode int, perm int) (fd int, errno int) { | |
| if len(path) == 0 { | |
| return -1, ERROR_FILE_NOT_FOUND | |
| } | |
| var access, sharemode uint32 | |
| switch { | |
| case mode&O_CREAT != 0: | |
| access = GENERIC_READ | GENERIC_WRITE | |
| sharemode = 0 | |
| case mode&O_RDWR == O_RDONLY: | |
| access = GENERIC_READ | |
| sharemode = FILE_SHARE_READ | |
| case mode&O_RDWR == O_WRONLY: | |
| access = GENERIC_WRITE | |
| sharemode = FILE_SHARE_READ | |
| case mode&O_RDWR == O_RDWR: | |
| access = GENERIC_READ | GENERIC_WRITE | |
| sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE | |
| } | |
| var createmode uint32 | |
| switch { | |
| case mode&O_CREAT != 0: | |
| if mode&O_EXCL != 0 { | |
| createmode = CREATE_NEW | |
| } else { | |
| createmode = CREATE_ALWAYS | |
| } | |
| case mode&O_TRUNC != 0: | |
| createmode = TRUNCATE_EXISTING | |
| default: | |
| createmode = OPEN_EXISTING | |
| } | |
| h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, nil, createmode, FILE_ATTRIBUTE_NORMAL, 0) | |
| return int(h), int(e) | |
| } | |
| func Read(fd int, p []byte) (n int, errno int) { | |
| var done uint32 | |
| if ok, e := ReadFile(int32(fd), p, &done, nil); !ok { | |
| return 0, e | |
| } | |
| return int(done), 0 | |
| } | |
| // TODO(brainman): ReadFile/WriteFile change file offset, therefore | |
| // i use Seek here to preserve semantics of unix pread/pwrite, | |
| // not sure if I should do that | |
| func Pread(fd int, p []byte, offset int64) (n int, errno int) { | |
| var o Overlapped | |
| o.OffsetHigh = uint32(offset >> 32) | |
| o.Offset = uint32(offset) | |
| curoffset, e := Seek(fd, 0, 1) | |
| if e != 0 { | |
| return 0, e | |
| } | |
| var done uint32 | |
| if ok, e := ReadFile(int32(fd), p, &done, &o); !ok { | |
| return 0, e | |
| } | |
| _, e = Seek(fd, curoffset, 0) | |
| if e != 0 { | |
| return 0, e | |
| } | |
| return int(done), 0 | |
| } | |
| func Write(fd int, p []byte) (n int, errno int) { | |
| var done uint32 | |
| if ok, e := WriteFile(int32(fd), p, &done, nil); !ok { | |
| return 0, e | |
| } | |
| return int(done), 0 | |
| } | |
| func Pwrite(fd int, p []byte, offset int64) (n int, errno int) { | |
| var o Overlapped | |
| o.OffsetHigh = uint32(offset >> 32) | |
| o.Offset = uint32(offset) | |
| curoffset, e := Seek(fd, 0, 1) | |
| if e != 0 { | |
| return 0, e | |
| } | |
| var done uint32 | |
| if ok, e := WriteFile(int32(fd), p, &done, &o); !ok { | |
| return 0, e | |
| } | |
| _, e = Seek(fd, curoffset, 0) | |
| if e != 0 { | |
| return 0, e | |
| } | |
| return int(done), 0 | |
| } | |
| func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) { | |
| var w uint32 | |
| switch whence { | |
| case 0: | |
| w = FILE_BEGIN | |
| case 1: | |
| w = FILE_CURRENT | |
| case 2: | |
| w = FILE_END | |
| } | |
| hi := int32(offset >> 32) | |
| lo := int32(offset) | |
| rlo, e := SetFilePointer(int32(fd), lo, &hi, w) | |
| if e != 0 { | |
| return 0, e | |
| } | |
| return int64(hi)<<32 + int64(rlo), 0 | |
| } | |
| func Close(fd int) (errno int) { | |
| if ok, e := CloseHandle(int32(fd)); !ok { | |
| return e | |
| } | |
| return 0 | |
| } | |
| var ( | |
| Stdin = getStdHandle(STD_INPUT_HANDLE) | |
| Stdout = getStdHandle(STD_OUTPUT_HANDLE) | |
| Stderr = getStdHandle(STD_ERROR_HANDLE) | |
| ) | |
| func getStdHandle(h int32) (fd int) { | |
| r, _ := GetStdHandle(h) | |
| return int(r) | |
| } | |
| // TODO(brainman): fix all needed for os | |
| const ( | |
| SIGTRAP = 5 | |
| ) | |
| func Getdents(fd int, buf []byte) (n int, errno int) { return 0, EMINGW } | |
| func Getpid() (pid int) { return -1 } | |
| func Getppid() (ppid int) { return -1 } | |
| func Mkdir(path string, mode int) (errno int) { return EMINGW } | |
| func Lstat(path string, stat *Stat_t) (errno int) { return EMINGW } | |
| func Stat(path string, stat *Stat_t) (errno int) { return EMINGW } | |
| func Fstat(fd int, stat *Stat_t) (errno int) { return EMINGW } | |
| func Chdir(path string) (errno int) { return EMINGW } | |
| func Fchdir(fd int) (errno int) { return EMINGW } | |
| func Unlink(path string) (errno int) { return EMINGW } | |
| func Rmdir(path string) (errno int) { return EMINGW } | |
| func Link(oldpath, newpath string) (errno int) { return EMINGW } | |
| func Symlink(path, link string) (errno int) { return EMINGW } | |
| func Readlink(path string, buf []byte) (n int, errno int) { return 0, EMINGW } | |
| func Rename(oldpath, newpath string) (errno int) { return EMINGW } | |
| func Chmod(path string, mode int) (errno int) { return EMINGW } | |
| func Fchmod(fd int, mode int) (errno int) { return EMINGW } | |
| func Chown(path string, uid int, gid int) (errno int) { return EMINGW } | |
| func Lchown(path string, uid int, gid int) (errno int) { return EMINGW } | |
| func Fchown(fd int, uid int, gid int) (errno int) { return EMINGW } | |
| func Truncate(name string, size int64) (errno int) { return EMINGW } | |
| func Ftruncate(fd int, length int64) (errno int) { return EMINGW } | |
| const ImplementsGetwd = true | |
| func Getwd() (wd string, errno int) { return "", EMINGW } | |
| func Getuid() (uid int) { return -1 } | |
| func Geteuid() (euid int) { return -1 } | |
| func Getgid() (gid int) { return -1 } | |
| func Getegid() (egid int) { return -1 } | |
| func Getgroups() (gids []int, errno int) { return nil, EMINGW } | |
| func Gettimeofday(tv *Timeval) (errno int) { return EMINGW } | |
| // TODO(brainman): fix all this meaningless code, it is here to compile exec.go | |
| func Pipe(p []int) (errno int) { return EMINGW } | |
| func read(fd int, buf *byte, nbuf int) (n int, errno int) { | |
| return 0, EMINGW | |
| } | |
| func fcntl(fd, cmd, arg int) (val int, errno int) { | |
| return 0, EMINGW | |
| } | |
| const ( | |
| PTRACE_TRACEME = 1 + iota | |
| WNOHANG | |
| WSTOPPED | |
| SYS_CLOSE | |
| SYS_WRITE | |
| SYS_EXIT | |
| SYS_READ | |
| ) | |
| type Rusage struct { | |
| Utime Timeval | |
| Stime Timeval | |
| Maxrss int32 | |
| Ixrss int32 | |
| Idrss int32 | |
| Isrss int32 | |
| Minflt int32 | |
| Majflt int32 | |
| Nswap int32 | |
| Inblock int32 | |
| Oublock int32 | |
| Msgsnd int32 | |
| Msgrcv int32 | |
| Nsignals int32 | |
| Nvcsw int32 | |
| Nivcsw int32 | |
| } | |
| func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { | |
| return 0, EMINGW | |
| } | |
| type WaitStatus uint32 | |
| func (WaitStatus) Exited() bool { return false } | |
| func (WaitStatus) ExitStatus() int { return -1 } | |
| func (WaitStatus) Signal() int { return -1 } | |
| func (WaitStatus) CoreDump() bool { return false } | |
| func (WaitStatus) Stopped() bool { return false } | |
| func (WaitStatus) Continued() bool { return false } | |
| func (WaitStatus) StopSignal() int { return -1 } | |
| func (WaitStatus) Signaled() bool { return false } | |
| func (WaitStatus) TrapCause() int { return -1 } |