windows: define and use syscall.Handle
Fixes #1487.

R=rsc, alex.brainman, go.peter.90, mikioh.mikioh, mattn.jp
CC=golang-dev
https://golang.org/cl/4600042
diff --git a/src/pkg/os/env_windows.go b/src/pkg/os/env_windows.go
index a45d79b..e6ddc40 100644
--- a/src/pkg/os/env_windows.go
+++ b/src/pkg/os/env_windows.go
@@ -119,7 +119,7 @@
 	if e != 0 {
 		return
 	}
-	defer syscall.LocalFree(uint32(uintptr(unsafe.Pointer(argv))))
+	defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
 	Args = make([]string, argc)
 	for i, v := range (*argv)[:argc] {
 		Args[i] = string(syscall.UTF16ToString((*v)[:]))
diff --git a/src/pkg/os/exec_posix.go b/src/pkg/os/exec_posix.go
index 7dfcdd4..e209770 100644
--- a/src/pkg/os/exec_posix.go
+++ b/src/pkg/os/exec_posix.go
@@ -35,16 +35,9 @@
 	if sysattr.Env == nil {
 		sysattr.Env = Environ()
 	}
-	// Create array of integer (system) fds.
-	intfd := make([]int, len(attr.Files))
-	for i, f := range attr.Files {
-		if f == nil {
-			intfd[i] = -1
-		} else {
-			intfd[i] = f.Fd()
-		}
+	for _, f := range attr.Files {
+		sysattr.Files = append(sysattr.Files, f.Fd())
 	}
-	sysattr.Files = intfd
 
 	pid, h, e := syscall.StartProcess(name, argv, sysattr)
 	if iserror(e) {
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
index 991099d..5b432d3 100644
--- a/src/pkg/os/exec_windows.go
+++ b/src/pkg/os/exec_windows.go
@@ -10,7 +10,7 @@
 )
 
 func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
-	s, e := syscall.WaitForSingleObject(int32(p.handle), syscall.INFINITE)
+	s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE)
 	switch s {
 	case syscall.WAIT_OBJECT_0:
 		break
@@ -20,7 +20,7 @@
 		return nil, NewError("os: unexpected result from WaitForSingleObject")
 	}
 	var ec uint32
-	e = syscall.GetExitCodeProcess(int32(p.handle), &ec)
+	e = syscall.GetExitCodeProcess(syscall.Handle(p.handle), &ec)
 	if e != 0 {
 		return nil, NewSyscallError("GetExitCodeProcess", e)
 	}
@@ -31,7 +31,7 @@
 func (p *Process) Signal(sig Signal) Error {
 	switch sig.(UnixSignal) {
 	case SIGKILL:
-		e := syscall.TerminateProcess(int32(p.handle), 1)
+		e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)
 		return NewSyscallError("TerminateProcess", e)
 	}
 	return Errno(syscall.EWINDOWS)
@@ -41,7 +41,7 @@
 	if p.handle == -1 {
 		return EINVAL
 	}
-	e := syscall.CloseHandle(int32(p.handle))
+	e := syscall.CloseHandle(syscall.Handle(p.handle))
 	if e != 0 {
 		return NewSyscallError("CloseHandle", e)
 	}
diff --git a/src/pkg/os/file.go b/src/pkg/os/file.go
index 1b8faec..4335d45 100644
--- a/src/pkg/os/file.go
+++ b/src/pkg/os/file.go
@@ -9,36 +9,12 @@
 package os
 
 import (
-	"runtime"
-	"sync"
 	"syscall"
 )
 
-// File represents an open file descriptor.
-type File struct {
-	fd      int
-	name    string
-	dirinfo *dirInfo   // nil unless directory being read
-	nepipe  int        // number of consecutive EPIPE in Write
-	l       sync.Mutex // used to implement windows pread/pwrite
-}
-
-// Fd returns the integer Unix file descriptor referencing the open file.
-func (file *File) Fd() int { return file.fd }
-
 // Name returns the name of the file as presented to Open.
 func (file *File) Name() string { return file.name }
 
-// NewFile returns a new File with the given file descriptor and name.
-func NewFile(fd int, name string) *File {
-	if fd < 0 {
-		return nil
-	}
-	f := &File{fd: fd, name: name}
-	runtime.SetFinalizer(f, (*File).Close)
-	return f
-}
-
 // Stdin, Stdout, and Stderr are open Files pointing to the standard input,
 // standard output, and standard error file descriptors.
 var (
diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go
index 05db6bc..0791a0d 100644
--- a/src/pkg/os/file_posix.go
+++ b/src/pkg/os/file_posix.go
@@ -21,26 +21,6 @@
 	}
 }
 
-
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
-	var p [2]int
-
-	// See ../syscall/exec.go for description of lock.
-	syscall.ForkLock.RLock()
-	e := syscall.Pipe(p[0:])
-	if iserror(e) {
-		syscall.ForkLock.RUnlock()
-		return nil, nil, NewSyscallError("pipe", e)
-	}
-	syscall.CloseOnExec(p[0])
-	syscall.CloseOnExec(p[1])
-	syscall.ForkLock.RUnlock()
-
-	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
-}
-
 // Stat returns a FileInfo structure describing the named file and an error, if any.
 // If name names a valid symbolic link, the returned FileInfo describes
 // the file pointed at by the link and has fi.FollowedSymlink set to true.
diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go
index def9b3b..bda6a1e 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/pkg/os/file_unix.go
@@ -6,9 +6,37 @@
 
 import (
 	"runtime"
+	"sync"
 	"syscall"
 )
 
+// File represents an open file descriptor.
+type File struct {
+	fd      int
+	name    string
+	dirinfo *dirInfo   // nil unless directory being read
+	nepipe  int        // number of consecutive EPIPE in Write
+	l       sync.Mutex // used to implement windows pread/pwrite
+}
+
+// Fd returns the integer Unix file descriptor referencing the open file.
+func (file *File) Fd() int {
+	if file == nil {
+		return -1
+	}
+	return file.fd
+}
+
+// NewFile returns a new File with the given file descriptor and name.
+func NewFile(fd int, name string) *File {
+	if fd < 0 {
+		return nil
+	}
+	f := &File{fd: fd, name: name}
+	runtime.SetFinalizer(f, (*File).Close)
+	return f
+}
+
 // Auxiliary information if the File describes a directory
 type dirInfo struct {
 	buf  []byte // buffer for directory I/O
@@ -161,3 +189,22 @@
 
 	return name
 }
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err Error) {
+	var p [2]int
+
+	// See ../syscall/exec.go for description of lock.
+	syscall.ForkLock.RLock()
+	e := syscall.Pipe(p[0:])
+	if iserror(e) {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+	syscall.CloseOnExec(p[0])
+	syscall.CloseOnExec(p[1])
+	syscall.ForkLock.RUnlock()
+
+	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go
index 80886f6..70dd6e2 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/pkg/os/file_windows.go
@@ -6,9 +6,37 @@
 
 import (
 	"runtime"
+	"sync"
 	"syscall"
 )
 
+// File represents an open file descriptor.
+type File struct {
+	fd      syscall.Handle
+	name    string
+	dirinfo *dirInfo   // nil unless directory being read
+	nepipe  int        // number of consecutive EPIPE in Write
+	l       sync.Mutex // used to implement windows pread/pwrite
+}
+
+// Fd returns the Windows handle referencing the open file.
+func (file *File) Fd() syscall.Handle {
+	if file == nil {
+		return syscall.InvalidHandle
+	}
+	return file.fd
+}
+
+// NewFile returns a new File with the given file descriptor and name.
+func NewFile(fd syscall.Handle, name string) *File {
+	if fd < 0 {
+		return nil
+	}
+	f := &File{fd: fd, name: name}
+	runtime.SetFinalizer(f, (*File).Close)
+	return f
+}
+
 // Auxiliary information if the File describes a directory
 type dirInfo struct {
 	stat         syscall.Stat_t
@@ -40,7 +68,7 @@
 	if e != 0 {
 		return nil, &PathError{"open", name, Errno(e)}
 	}
-	f := NewFile(int(r), name)
+	f := NewFile(r, name)
 	d.usefirststat = true
 	f.dirinfo = d
 	return f, nil
@@ -85,15 +113,15 @@
 	}
 	var e int
 	if file.isdir() {
-		e = syscall.FindClose(int32(file.fd))
+		e = syscall.FindClose(syscall.Handle(file.fd))
 	} else {
-		e = syscall.CloseHandle(int32(file.fd))
+		e = syscall.CloseHandle(syscall.Handle(file.fd))
 	}
 	var err Error
 	if e != 0 {
 		err = &PathError{"close", file.name, Errno(e)}
 	}
-	file.fd = -1 // so it can't be closed again
+	file.fd = syscall.InvalidHandle // so it can't be closed again
 
 	// no need for a finalizer anymore
 	runtime.SetFinalizer(file, nil)
@@ -102,7 +130,7 @@
 
 func (file *File) statFile(name string) (fi *FileInfo, err Error) {
 	var stat syscall.ByHandleFileInformation
-	e := syscall.GetFileInformationByHandle(int32(file.fd), &stat)
+	e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &stat)
 	if e != 0 {
 		return nil, &PathError{"stat", file.name, Errno(e)}
 	}
@@ -156,7 +184,7 @@
 		if di.usefirststat {
 			di.usefirststat = false
 		} else {
-			e := syscall.FindNextFile(int32(file.fd), &di.stat.Windata)
+			e := syscall.FindNextFile(syscall.Handle(file.fd), &di.stat.Windata)
 			if e != 0 {
 				if e == syscall.ERROR_NO_MORE_FILES {
 					break
@@ -207,7 +235,7 @@
 		Offset:     uint32(off),
 	}
 	var done uint32
-	e = syscall.ReadFile(int32(f.fd), b, &done, &o)
+	e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o)
 	if e != 0 {
 		return 0, e
 	}
@@ -237,7 +265,7 @@
 		Offset:     uint32(off),
 	}
 	var done uint32
-	e = syscall.WriteFile(int32(f.fd), b, &done, &o)
+	e = syscall.WriteFile(syscall.Handle(f.fd), b, &done, &o)
 	if e != 0 {
 		return 0, e
 	}
@@ -268,3 +296,22 @@
 	}
 	return nil
 }
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err Error) {
+	var p [2]syscall.Handle
+
+	// See ../syscall/exec.go for description of lock.
+	syscall.ForkLock.RLock()
+	e := syscall.Pipe(p[0:])
+	if iserror(e) {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+	syscall.CloseOnExec(p[0])
+	syscall.CloseOnExec(p[1])
+	syscall.ForkLock.RUnlock()
+
+	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}