]> Cypherpunks repositories - gostls13.git/commitdiff
os,internal/syscall/windows: use ReadFile/MultiByteToWideChar to read from console
authormattn <mattn.jp@gmail.com>
Tue, 10 Feb 2015 02:06:02 +0000 (11:06 +0900)
committerRuss Cox <rsc@golang.org>
Thu, 17 Dec 2015 16:23:39 +0000 (16:23 +0000)
Fixes #6303

Change-Id: Ib2cd15ac6106ef8e6b975943db8efc8d8ab21052
Reviewed-on: https://go-review.googlesource.com/4310
Reviewed-by: Russ Cox <rsc@golang.org>
src/internal/syscall/windows/syscall_windows.go
src/internal/syscall/windows/zsyscall_windows.go
src/os/file_windows.go

index 67bb6c96fee500393d1f4205ba2a292d26cf5e4e..e5c1cd600c3d94329ff97a5bcab848331ff1ab52 100644 (file)
@@ -138,3 +138,6 @@ func Rename(oldpath, newpath string) error {
        }
        return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
 }
+
+//sys  GetACP() (acp uint, err error) = kernel32.GetACP
+//sys  MultiByteToWideChar(codePage uint, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int, err error) = kernel32.MultiByteToWideChar
index c8b494a535f7f16aeb80136ad8abcd599ca19fc0..fd614f88976a4d7e2ac152aaf3643cf0040439a4 100644 (file)
@@ -14,6 +14,8 @@ var (
        procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
        procGetComputerNameExW   = modkernel32.NewProc("GetComputerNameExW")
        procMoveFileExW          = modkernel32.NewProc("MoveFileExW")
+       procGetACP               = modkernel32.NewProc("GetACP")
+       procMultiByteToWideChar  = modkernel32.NewProc("MultiByteToWideChar")
 )
 
 func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
@@ -47,3 +49,29 @@ func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
        }
        return
 }
+
+func MultiByteToWideChar(codePage uint, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int, err error) {
+       r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar))
+       nwrite = int(r0)
+       if nwrite == 0 {
+               if e1 != 0 {
+                       err = error(e1)
+               } else {
+                       err = syscall.EINVAL
+               }
+       }
+       return
+}
+
+func GetACP() (acp uint, err error) {
+       r0, _, e1 := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0)
+       acp = uint(r0)
+       if acp == 0 {
+               if e1 != 0 {
+                       err = error(e1)
+               } else {
+                       err = syscall.EINVAL
+               }
+       }
+       return
+}
index 89b1d27fceea7f9debaa68a734de1deb54343d6b..b74c8f06313d75f789b1f4f646558d99f50f9239 100644 (file)
@@ -257,24 +257,38 @@ func (f *File) readConsole(b []byte) (n int, err error) {
                return 0, nil
        }
        if len(f.readbuf) == 0 {
-               // syscall.ReadConsole seems to fail, if given large buffer.
-               // So limit the buffer to 16000 characters.
                numBytes := len(b)
-               if numBytes > 16000 {
-                       numBytes = 16000
+               // Windows  can't read bytes over max of int16.
+               if numBytes > 32767 {
+                       numBytes = 32767
                }
-               // get more input data from os
-               wchars := make([]uint16, numBytes)
-               var p *uint16
-               if len(b) > 0 {
-                       p = &wchars[0]
-               }
-               var nw uint32
-               err := syscall.ReadConsole(f.fd, p, uint32(len(wchars)), &nw, nil)
+               mbytes := make([]byte, numBytes)
+               var nmb uint32
+               err := syscall.ReadFile(f.fd, mbytes, &nmb, nil)
                if err != nil {
                        return 0, err
                }
-               f.readbuf = utf16.Decode(wchars[:nw])
+               if nmb > 0 {
+                       var pmb *byte
+                       if len(b) > 0 {
+                               pmb = &mbytes[0]
+                       }
+                       acp, err := windows.GetACP()
+                       if err != nil {
+                               return 0, err
+                       }
+                       nwc, err := windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), nil, 0)
+                       if err != nil {
+                               return 0, err
+                       }
+                       wchars := make([]uint16, nwc)
+                       pwc := &wchars[0]
+                       nwc, err = windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), pwc, int32(nwc))
+                       if err != nil {
+                               return 0, err
+                       }
+                       f.readbuf = utf16.Decode(wchars[:nwc])
+               }
        }
        for i, r := range f.readbuf {
                if utf8.RuneLen(r) > len(b) {