kalamine icon indicating copy to clipboard operation
kalamine copied to clipboard

Generate Windows drivers from any OS

Open trilowy opened this issue 1 year ago • 0 comments

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

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.

trilowy avatar Jan 05 '25 17:01 trilowy