Skip to content
New issue

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

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

Already on GitHub? # 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.