Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

windows: add GetKeyboardLayout & ToUnicodeEx #188

Closed
12 changes: 10 additions & 2 deletions windows/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import (
"unsafe"
)

type Handle uintptr
type HWND uintptr
type (
Handle uintptr
HWND uintptr
)

const (
InvalidHandle = ^Handle(0)
Expand Down Expand Up @@ -211,6 +213,10 @@ 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, 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
//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
Expand Down Expand Up @@ -1368,9 +1374,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
}
Expand Down
47 changes: 47 additions & 0 deletions windows/syscall_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1275,3 +1275,50 @@ 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)
}

// 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

// 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, 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
0x1e, // 'A' scanCode
&keyState[0],
&utf16Buf[0],
int32(len(utf16Buf)),
0x4, // don't change keyboard state
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])
}
if err := windows.UnloadKeyboardLayout(araLayout); err != nil {
t.Errorf("UnloadKeyboardLayout failed: %v", err)
}
}
11 changes: 11 additions & 0 deletions windows/types_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
33 changes: 33 additions & 0 deletions windows/zsyscall_windows.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.