Windows: Raw Console I/O


I am currently trying to write a console editor in Go. For this I need to be able to read every single keypress of the user into the console. Luckily, the new x/sys/windows package provides functionality to set raw console mode & read from the console. This is what I have so far:

in, _ :=  windows.Open("CONIN$", windows.O_RDWR, 0)
windows.SetConsoleMode(in, windows.ENABLE_WINDOW_INPUT)

buf := make([]byte, 1024)
windows.Read(in, buf)

However, this does only read characters but not special keys (think arrow keys, delete / erase, home / end, pgup / pgdown, f1-f12).

So I tried using windows.ReadConsole() instead, but this does not read special keys either:

buf := make([]uint16, 1024)
var iC byte = 0 // what does input control refer to?
windows.ReadConsole(in, &buf[0], uint32(1) &read, &iC)

After looking at some more docs, I found out about the ReadConsoleInput function and implemented it using syscalls, but this one is “too raw” - it also sends key release, and for some reason, I don’t get any usable keycodes, but only 0x0s and 0x1s.

I have an example on my GitHub in this folder:
I first reported this on the Go issue tracker: #44373 but was referred here because no one could help me there.

Thanks for any help in advance.

I did some more testing. The ReadConsoleInput method does exactly what I want. Here is a C example code that I can use:

However, if I call the same method as a syscall from Go, only 0x0s and 0x1s are returned. Any ideas?

EDIT: Found the problem. I am currently reading into a single byte, which does not really make sense here. I now created an InputRecord struct, just as mentioned in the Microsoft article

type InputRecord struct {
  Type  uint16
  _     [2]byte
  Event [16]byte

This does seem to provide me with a lot more usable data.

For future reference: