-
Notifications
You must be signed in to change notification settings - Fork 34
Description
Goal
For now, Kalamine is only able to generate drivers for Windows if launched from
Windows with wkalamine
and MSKLC installed (or with proprietary software
like KbdEdit).
The idea is to use the Zig toolchain, which is compatible with C and can
easily cross-compile.
I’ll put in this issue all informations I found and my attempts to do that.
Information search
Note: all tests are performed on a Windows 10 x86_64 installation.
Installation of a keyboard layout on Windows
The installation process has two parts:
- Copy the DLL layout to the right folder
- Make an entry in the registry (there is a dynamic part in that, done by the
EXE)
Keyboard DLL on Windows
When we produce an EXE with wkalamine
and MSKLC, the installation path of the
DLL is here (for Ergo‑L layout):
C:\Windows\System32\ergol.dll
KbdEdit it’s:
C:\Windows\System32\kbdXXXX.dll
And there is many more layout DLLs starting with kbd
in this folder.
- 64 bits DLL are in
System32/
(named like that to not break old 32 bits app
compatibility which has hardcoded the path) - 32 bits DLL are in
SysWOW64/
(System Windows 32 bits Over
Windows 64 bits)
I tried to change the DLL generated by wkalamine
for Bépolar. I switched
amd64\bepolar.dll
by ergol.dll
and kept the name bepolar.dll
. The EXE
installed it in C:\Windows\System32\bepolar.dll
as if it were Bépolar, no
warning. The layout and its name was Ergo‑L: they seem to be encoded inside the
DLL.
Useful links
- winkbdlayouts: an amazing source of informations on how keyboard layouts
work on Windows - MON NOM ACCENTUÉ (French): more explanations on Windows keyboard layouts
- sam.elborai blog: explains the C code of DLL
- Neo Layout: German layout source code
- Windows-driver-samples: an example of keyboard layout source code by
Microsoft - Keyboard scan codes image
Attempts to create the DLL using Zig on WSL (Linux)
With C files
I tried to compile the C and H of Bépolar layout on a Linux environment with
Zig 0.13.0 (latest stable release at the time), copying all the needed H files
from C:\Program Files (x86)\Microsoft Keyboard Layout Creator 1.4\inc
without
success (a lot of errors, I might be missing some Windows H files).
Most of the H files are copyrighted, not sure it will be possible to include
them in Kalamine anyway.
With Zig files
I tried to rewrite it in pure Zig and add only what I need from the H files.
The sources are here: zig-keyboard-layout-dll
Compilation command
I compared simple DLL output with the reel one from MSKLC with
Dependency Walker to see if I can have the same entrypoint and config.
The compilation command I ended up with is:
zig build-lib -O ReleaseFast -target x86_64-windows-msvc -dynamic bepolar.zig --subsystem native
Explanations:
-O ReleaseFast
: build in fast mode (unsafe), since the C is natively unsafe
too-target x86_64-windows-msvc
: Windows x86_64 target with MSVC ABI (not sure
for the usefulness of the MSVC ABI part)-dynamic
: to make a DLL--subsystem native
: in Dependency Walker, Subsystem at Native instead of GUI
We can add:
-fstrip
: remove debugger annotations (in Dependency Walker, Symbols at None
instead of CV) and do not generate a .pdb anymore--version 4.0.0
: in Dependency Walker, Image Ver at 4.0 instead of 0.0
I didn’t find how to not generate with the Zig compilation:
_DllMainCRTStartup
__xl_a
__xl_z
_tls_end
_tls_index
_tls_start
_tls_used
Source code translation
The code is coming from:
- the C and H output of
wkalamine
for Bépolar - the MSKLC installation folder
(C:\Program Files (x86)\Microsoft Keyboard Layout Creator 1.4\inc
)
It helps a lot to understand Windows coding conventions with:
- https://learn.microsoft.com/en-us/windows/win32/learnwin32/windows-coding-conventions
- https://learn.microsoft.com/en-us/windows/win32/learnwin32/working-with-strings
And guide to translate C to Zig.
Test
I installed a regular Bépolar layout and then replaced its DLL by my Zig one.
For now it crashes the start of Windows, don’t do that, it’s annoying to delete
the DLL with a prompt in safe mode.
I want to compare the resulting output of the DLL function KbdLayerDescriptor
of the good DLL and mine without actually loading it with Windows altoghether.
These commands output nothing:
rundll32 C:\Windows\System32\ergol.dll,KbdLayerDescriptor
rundll32 ergol.dll,KbdLayerDescriptor
rundll32 .\bepolar.dll,KbdLayerDescriptor
I have seen on the web:
dumpbin /EXPORTS ergol.dll
But I don’t know how to have that dumpbin
EXE, it might be useful though.
I might try to create a program that imports the DLL, or compare the assembler
code with Compiler Explorer.
I don’t know much of system programming (and C) and I’m stuck. Not sure what to
do from there to go forward with the test, so I share all I know here, just in
case someone wants to give it a try. I’ll update this issue if I find more
informations.