From dc63ed4c4d844a61c67cdbfbfbb8f04b74f4cf4d Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Wed, 27 Mar 2024 12:57:08 -0400 Subject: [PATCH 1/7] windows: add GetKeyboardLayout & ToUnicodeEx These are used along with GetForegroundWindow and GetWindowThreadProcessId to determine the current user layout and translate the base key the user has pressed. --- windows/syscall_windows.go | 20 ++++++++++++++++++-- windows/zsyscall_windows.go | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index 6525c62f3c..22ea75052d 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -17,8 +17,10 @@ import ( "unsafe" ) -type Handle uintptr -type HWND uintptr +type ( + Handle uintptr + HWND uintptr +) const ( InvalidHandle = ^Handle(0) @@ -211,6 +213,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) //sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW //sys GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId +//sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout +//sys toUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx //sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow //sys MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW //sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx @@ -1368,9 +1372,11 @@ func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) } + func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) } + func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return syscall.EWINDOWS } @@ -1916,3 +1922,13 @@ const ( EV_ERR = 0x0080 EV_RING = 0x0100 ) + +// ToUnicodeEx Translates the specified virtual-key code and keyboard state to +// the corresponding Unicode character or characters. +func ToUnicodeEx(virtualKey, scanCode uint32, buf []uint16, flags uint32, layout Handle) int32 { + if len(buf) == 0 { + return 0 + } + var keyState [256]byte + return toUnicodeEx(virtualKey, scanCode, &keyState[0], &buf[0], int32(len(buf)), flags, layout) +} diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 9f73df75b5..6dc596825f 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -477,12 +477,14 @@ var ( procGetDesktopWindow = moduser32.NewProc("GetDesktopWindow") procGetForegroundWindow = moduser32.NewProc("GetForegroundWindow") procGetGUIThreadInfo = moduser32.NewProc("GetGUIThreadInfo") + procGetKeyboardLayout = moduser32.NewProc("GetKeyboardLayout") procGetShellWindow = moduser32.NewProc("GetShellWindow") procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId") procIsWindow = moduser32.NewProc("IsWindow") procIsWindowUnicode = moduser32.NewProc("IsWindowUnicode") procIsWindowVisible = moduser32.NewProc("IsWindowVisible") procMessageBoxW = moduser32.NewProc("MessageBoxW") + procToUnicodeEx = moduser32.NewProc("ToUnicodeEx") procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") @@ -4073,6 +4075,12 @@ func GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) { return } +func GetKeyboardLayout(tid uint32) (hkl Handle) { + r0, _, _ := syscall.Syscall(procGetKeyboardLayout.Addr(), 1, uintptr(tid), 0, 0) + hkl = Handle(r0) + return +} + func GetShellWindow() (shellWindow HWND) { r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0) shellWindow = HWND(r0) @@ -4115,6 +4123,12 @@ func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret i return } +func toUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { + r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl), 0, 0) + ret = int32(r0) + return +} + func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { var _p0 uint32 if inheritExisting { From 3aa85da655c62258ad4e687b30377fd00bda0b72 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 14 May 2024 14:15:05 -0400 Subject: [PATCH 2/7] windows: add GetKeyboardLayout and ToUnicodeEx tests --- windows/syscall_windows_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index 6658379070..9b1241734b 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -1275,3 +1275,32 @@ uintptr_t beep(void) { t.Fatal("LoadLibraryEx unexpectedly found beep.dll") } } + +func TestGetKeyboardLayout(t *testing.T) { + fg := windows.GetForegroundWindow() + tid, err := windows.GetWindowThreadProcessId(fg, nil) + if err != nil { + t.Fatalf("GetWindowThreadProcessId failed: %v", err) + } + + _ = windows.GetKeyboardLayout(tid) +} + +func TestToUnicodeEx(t *testing.T) { + var utf16Buf [16]uint16 + const araLayout = windows.Handle(0x401) + ret := windows.ToUnicodeEx( + 0x41, // 'A' vkCode + 0x1e, // 'A' scanCode + utf16Buf[:], + 0, + araLayout, + ) + + if ret != 1 { + t.Errorf("ToUnicodeEx failed, wanted 1, got %d", ret) + } + if utf16Buf[0] != 'ش' { + t.Errorf("ToUnicodeEx failed, wanted 'ش', got %q", utf16Buf[0]) + } +} From d4d009aecf406c67e24f20f92ea35a731b72c7aa Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Fri, 17 May 2024 15:35:16 -0400 Subject: [PATCH 3/7] windows: change exported ToUnicodeEx signature + fix tests --- windows/syscall_windows.go | 3 +-- windows/syscall_windows_test.go | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index 22ea75052d..e5462a5c30 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -1925,10 +1925,9 @@ const ( // ToUnicodeEx Translates the specified virtual-key code and keyboard state to // the corresponding Unicode character or characters. -func ToUnicodeEx(virtualKey, scanCode uint32, buf []uint16, flags uint32, layout Handle) int32 { +func ToUnicodeEx(virtualKey, scanCode uint32, keyState [256]byte, buf []uint16, flags uint32, layout Handle) int32 { if len(buf) == 0 { return 0 } - var keyState [256]byte return toUnicodeEx(virtualKey, scanCode, &keyState[0], &buf[0], int32(len(buf)), flags, layout) } diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index 9b1241734b..e9c4de026a 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -1283,17 +1283,20 @@ func TestGetKeyboardLayout(t *testing.T) { t.Fatalf("GetWindowThreadProcessId failed: %v", err) } + // We don't care about the result, just that it doesn't crash. _ = windows.GetKeyboardLayout(tid) } func TestToUnicodeEx(t *testing.T) { var utf16Buf [16]uint16 const araLayout = windows.Handle(0x401) + var keyState [256]byte ret := windows.ToUnicodeEx( 0x41, // 'A' vkCode 0x1e, // 'A' scanCode + keyState, utf16Buf[:], - 0, + 0x4, // don't change keyboard state araLayout, ) From 728fe3833f7578d7a48f2c5e1432c857b73d38b1 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Fri, 31 May 2024 11:51:37 -0700 Subject: [PATCH 4/7] windows: add LoadKeyboardLayout and UnloadKeyboardLayout --- windows/syscall_windows.go | 2 ++ windows/types_windows.go | 11 +++++++++++ windows/zsyscall_windows.go | 14 ++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index e5462a5c30..47701eed01 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -213,6 +213,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) //sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW //sys GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId +//sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle) = user32.LoadKeyboardLayoutW +//sys UnloadKeyboardLayout(hkl Handle) (v bool) = user32.UnloadKeyboardLayout //sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout //sys toUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx //sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow diff --git a/windows/types_windows.go b/windows/types_windows.go index d8cb71db0a..250ad67f68 100644 --- a/windows/types_windows.go +++ b/windows/types_windows.go @@ -3404,3 +3404,14 @@ type DCB struct { EvtChar byte wReserved1 uint16 } + +// Keyboard Layout Flags. +// See https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadkeyboardlayoutw +const ( + KLF_ACTIVATE = 0x00000001 + KLF_SUBSTITUTE_OK = 0x00000002 + KLF_REORDER = 0x00000008 + KLF_REPLACELANG = 0x00000010 + KLF_NOTELLSHELL = 0x00000080 + KLF_SETFORPROCESS = 0x00000100 +) diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 6dc596825f..794f8a99c6 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -483,8 +483,10 @@ var ( procIsWindow = moduser32.NewProc("IsWindow") procIsWindowUnicode = moduser32.NewProc("IsWindowUnicode") procIsWindowVisible = moduser32.NewProc("IsWindowVisible") + procLoadKeyboardLayoutW = moduser32.NewProc("LoadKeyboardLayoutW") procMessageBoxW = moduser32.NewProc("MessageBoxW") procToUnicodeEx = moduser32.NewProc("ToUnicodeEx") + procUnloadKeyboardLayout = moduser32.NewProc("UnloadKeyboardLayout") procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") @@ -4114,6 +4116,12 @@ func IsWindowVisible(hwnd HWND) (isVisible bool) { return } +func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle) { + r0, _, _ := syscall.Syscall(procLoadKeyboardLayoutW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0) + hkl = Handle(r0) + return +} + func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) ret = int32(r0) @@ -4129,6 +4137,12 @@ func toUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, return } +func UnloadKeyboardLayout(hkl Handle) (v bool) { + r0, _, _ := syscall.Syscall(procUnloadKeyboardLayout.Addr(), 1, uintptr(hkl), 0, 0) + v = r0 != 0 + return +} + func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { var _p0 uint32 if inheritExisting { From d949424c56303171c8d68b6058b479cf3f8c2d89 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Fri, 31 May 2024 11:52:03 -0700 Subject: [PATCH 5/7] windows: use original ToUnicodeEx signature and update tests --- windows/syscall_windows.go | 11 +---------- windows/syscall_windows_test.go | 14 +++++++++++--- windows/zsyscall_windows.go | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index 47701eed01..e26da2bb40 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -216,7 +216,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle) = user32.LoadKeyboardLayoutW //sys UnloadKeyboardLayout(hkl Handle) (v bool) = user32.UnloadKeyboardLayout //sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout -//sys toUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx +//sys ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx //sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow //sys MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW //sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx @@ -1924,12 +1924,3 @@ const ( EV_ERR = 0x0080 EV_RING = 0x0100 ) - -// ToUnicodeEx Translates the specified virtual-key code and keyboard state to -// the corresponding Unicode character or characters. -func ToUnicodeEx(virtualKey, scanCode uint32, keyState [256]byte, buf []uint16, flags uint32, layout Handle) int32 { - if len(buf) == 0 { - return 0 - } - return toUnicodeEx(virtualKey, scanCode, &keyState[0], &buf[0], int32(len(buf)), flags, layout) -} diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index e9c4de026a..be60a5a44c 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -1289,13 +1289,18 @@ func TestGetKeyboardLayout(t *testing.T) { func TestToUnicodeEx(t *testing.T) { var utf16Buf [16]uint16 - const araLayout = windows.Handle(0x401) + ara, err := windows.UTF16PtrFromString("00000401") // ara layout 0x401 + if err != nil { + t.Fatalf("UTF16PtrFromString failed: %v", err) + } + araLayout := windows.LoadKeyboardLayout(ara, 0) var keyState [256]byte ret := windows.ToUnicodeEx( 0x41, // 'A' vkCode 0x1e, // 'A' scanCode - keyState, - utf16Buf[:], + &keyState[0], + &utf16Buf[0], + int32(len(utf16Buf)), 0x4, // don't change keyboard state araLayout, ) @@ -1306,4 +1311,7 @@ func TestToUnicodeEx(t *testing.T) { if utf16Buf[0] != 'ش' { t.Errorf("ToUnicodeEx failed, wanted 'ش', got %q", utf16Buf[0]) } + if !windows.UnloadKeyboardLayout(araLayout) { + t.Errorf("UnloadKeyboardLayout failed") + } } diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 794f8a99c6..38cf9de2c6 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -4131,7 +4131,7 @@ func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret i return } -func toUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { +func ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl), 0, 0) ret = int32(r0) return From fc5dda07f4d8215b233d1a7fa7042667d904bedc Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Fri, 31 May 2024 11:59:09 -0700 Subject: [PATCH 6/7] windows: TestToUnicodeEx: always activate the layout --- windows/syscall_windows_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index be60a5a44c..025e23538a 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -1293,7 +1293,7 @@ func TestToUnicodeEx(t *testing.T) { if err != nil { t.Fatalf("UTF16PtrFromString failed: %v", err) } - araLayout := windows.LoadKeyboardLayout(ara, 0) + araLayout := windows.LoadKeyboardLayout(ara, windows.KLF_ACTIVATE) var keyState [256]byte ret := windows.ToUnicodeEx( 0x41, // 'A' vkCode From 2afe9976a2d1f6a8dda9bd74cf07b207246bfcc6 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Sat, 13 Jul 2024 18:26:00 -0700 Subject: [PATCH 7/7] windows: return error on LoadKeyboardLayout/UnloadKeyboardLayout --- windows/syscall_windows.go | 4 ++-- windows/syscall_windows_test.go | 15 +++++++++++---- windows/zsyscall_windows.go | 15 ++++++++++----- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index e26da2bb40..1fa34fd17c 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -213,8 +213,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) //sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW //sys GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId -//sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle) = user32.LoadKeyboardLayoutW -//sys UnloadKeyboardLayout(hkl Handle) (v bool) = user32.UnloadKeyboardLayout +//sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) [failretval==0] = user32.LoadKeyboardLayoutW +//sys UnloadKeyboardLayout(hkl Handle) (err error) = user32.UnloadKeyboardLayout //sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout //sys ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx //sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go index 025e23538a..cb80af62f2 100644 --- a/windows/syscall_windows_test.go +++ b/windows/syscall_windows_test.go @@ -1289,11 +1289,18 @@ func TestGetKeyboardLayout(t *testing.T) { func TestToUnicodeEx(t *testing.T) { var utf16Buf [16]uint16 - ara, err := windows.UTF16PtrFromString("00000401") // ara layout 0x401 + + // Arabic (101) Keyboard Identifier + // See https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values + ara, err := windows.UTF16PtrFromString("00000401") if err != nil { t.Fatalf("UTF16PtrFromString failed: %v", err) } - araLayout := windows.LoadKeyboardLayout(ara, windows.KLF_ACTIVATE) + araLayout, err := windows.LoadKeyboardLayout(ara, windows.KLF_ACTIVATE) + if err != nil { + t.Fatalf("LoadKeyboardLayout failed: %v", err) + } + var keyState [256]byte ret := windows.ToUnicodeEx( 0x41, // 'A' vkCode @@ -1311,7 +1318,7 @@ func TestToUnicodeEx(t *testing.T) { if utf16Buf[0] != 'ش' { t.Errorf("ToUnicodeEx failed, wanted 'ش', got %q", utf16Buf[0]) } - if !windows.UnloadKeyboardLayout(araLayout) { - t.Errorf("UnloadKeyboardLayout failed") + if err := windows.UnloadKeyboardLayout(araLayout); err != nil { + t.Errorf("UnloadKeyboardLayout failed: %v", err) } } diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 38cf9de2c6..4f8448cc56 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -4116,9 +4116,12 @@ func IsWindowVisible(hwnd HWND) (isVisible bool) { return } -func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle) { - r0, _, _ := syscall.Syscall(procLoadKeyboardLayoutW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0) +func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadKeyboardLayoutW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0) hkl = Handle(r0) + if hkl == 0 { + err = errnoErr(e1) + } return } @@ -4137,9 +4140,11 @@ func ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, return } -func UnloadKeyboardLayout(hkl Handle) (v bool) { - r0, _, _ := syscall.Syscall(procUnloadKeyboardLayout.Addr(), 1, uintptr(hkl), 0, 0) - v = r0 != 0 +func UnloadKeyboardLayout(hkl Handle) (err error) { + r1, _, e1 := syscall.Syscall(procUnloadKeyboardLayout.Addr(), 1, uintptr(hkl), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } return }