]> Cypherpunks repositories - gostls13.git/commitdiff
os: use GetConsoleCP() instead of GetACP()
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Wed, 24 Aug 2016 01:34:16 +0000 (10:34 +0900)
committerAlex Brainman <alex.brainman@gmail.com>
Wed, 21 Sep 2016 00:38:51 +0000 (00:38 +0000)
It is possible (and common) for Windows systems to use a different codepage
for console applications from that used on normal windowed application
(called ANSI codepage); for instance, most of the western Europe uses
CP850 for console (for backward compatibility with MS-DOS), while
windowed applications use a different codepage depending on the country
(eg: CP1252 aka Latin-1). The usage being changed with this commit is
specifically related to decoding input coming from the console, so the
previous usage of the ANSI codepage was wrong.

Also fixes an issue that previous did convert bytes as NFD. Go is
designed to handle single Unicode code point. This fix change behaivor
to NFC.

Fixes #16857.

Change-Id: I4f41ae83ece47321b6e9a79a2087ecbb8ac066dd
Reviewed-on: https://go-review.googlesource.com/27575
Reviewed-by: Hiroshi Ioka <hirochachacha@gmail.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
src/internal/syscall/windows/syscall_windows.go
src/internal/syscall/windows/zsyscall_windows.go
src/os/file_windows.go

index 47ca602ae1d17b2d3a5bca46b8c221c4fccccf73..015862d71336f480c8dd3e9e9ee202dc1765e08e 100644 (file)
@@ -138,4 +138,5 @@ func Rename(oldpath, newpath string) error {
 }
 
 //sys  GetACP() (acp uint32) = kernel32.GetACP
+//sys  GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
 //sys  MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
index 21fe12fe1b9c4cf7737155d56fb942b71800b58c..0b814e9b4a460986be41cd1887defef1fb44be6a 100644 (file)
@@ -43,6 +43,7 @@ var (
        procGetComputerNameExW   = modkernel32.NewProc("GetComputerNameExW")
        procMoveFileExW          = modkernel32.NewProc("MoveFileExW")
        procGetACP               = modkernel32.NewProc("GetACP")
+       procGetConsoleCP         = modkernel32.NewProc("GetConsoleCP")
        procMultiByteToWideChar  = modkernel32.NewProc("MultiByteToWideChar")
 )
 
@@ -84,6 +85,12 @@ func GetACP() (acp uint32) {
        return
 }
 
+func GetConsoleCP() (ccp uint32) {
+       r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0)
+       ccp = uint32(r0)
+       return
+}
+
 func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, 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 = int32(r0)
index e1f9f1c33dfe7a3fd5c6eb5c821cb25b62726917..efbf0e85fbbb21239a57f58fabb53042e7c5c661 100644 (file)
@@ -217,14 +217,16 @@ func (f *File) readConsole(b []byte) (n int, err error) {
                        if len(b) > 0 {
                                pmb = &mbytes[0]
                        }
-                       acp := windows.GetACP()
-                       nwc, err := windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), nil, 0)
+                       ccp := windows.GetConsoleCP()
+                       // Convert from 8-bit console encoding to UTF16.
+                       // MultiByteToWideChar defaults to Unicode NFC form, which is the expected one.
+                       nwc, err := windows.MultiByteToWideChar(ccp, 0, 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, nwc)
+                       nwc, err = windows.MultiByteToWideChar(ccp, 0, pmb, int32(nmb), pwc, nwc)
                        if err != nil {
                                return 0, err
                        }