Introduction
Windows uses kbd**.dll files to load keyboards. When loading a keyboard on a 32-bit application on a 64-bit system you'll get a corrupted array.
This little hack will handle keyboard-DLL loads for a 32-bit application, running on a 64-bit system.
Background
The problem was found during my creation of a on-screen keyboard that I wanted to be multilingual.
After searching several forums I didn't find any good solution for the problem. The DLL-import is the same on either systems, but after running init using
KbdLayerDescriptor()
, the array is actual corrupted. An element called
pVkToWcharTable
is always NULL
. This array shows the connection between Virtual Keys (VK) and characters, pretty essential for presenting a keyboard.
In the
kbd.h header-file, from Microsoft DDK, this pointer is defined:
#if defined(BUILD_WOW6432)
#define KBD_LONG_POINTER __ptr64
#else
#define KBD_LONG_POINTER
#endif
This works great on a 32-bit application running a 32-bit system, but not on a 64-bit system.
If you define BUILD_WOW6432
and compile the application as 64-bit, the program works as expected.
What caused this strange behavior?
After doing a little research of the topic I found the probably cause in MSDN.
A pointer defined as __ptr32
is coerced on a 64-bit system. If the
KbdLayerDescriptor()
actually uses sizeof()
and other functions to get the length, it probably goes out of range, in the array.
My solution is to create "my own" 64-bit variables using this define
#define KBD_LONG_POINTER64 __ptr64
Checkout the kbd64.h file for all variables/functions renamed around this 64-bit define.
Kbd64.h is just a renamed kbd.h to ensure own defines for the 64-bit pointer.
The demo
The included demonstration shows how to get the DLL initiated and array filled correctly. It does not show how to handle modifiers and dead-keys, that is not essential part of the subject.
If you are looking into handling dead-keys or wondering anything about these "strange" kbd**.dll files, check out Michael Kaplan Sorting it all Out and search for the KbdLayerDescriptor.
Using the code
The CKLL
class has four public functions + one helper (from
KLL.h).
BOOL LoadDLL(CString sKeyboardDll);
USHORT GetVKCount();
CString GetChar(USHORT iVK);
CString GetSC(USHORT iVK);
BOOL Is64BitWindows();
If you have already have written you're own functions based on the kbd.h header from Microsoft, then you can use the kbd64.h header and replace the variables and add 64 in the end; for example PKBDTABLES -> PKBDTABLES64. Then you use the
Is64BitWindows()
to check what type of system the application is running on.
Check out the
Fill32()
and Fill64()
function in the CKLL
class to get an idea on how it works.
Points of Interest
The keyboard-DLLs are created using the Microsoft Keyboard Layout Creator and by using the built-in functions you can easily create custom
DLLs without any hassle.
The connection between Scan Codes (SC) and physical layout is pretty interesting
Source - Compare the Scan Code value from the picture above, with the result from
KeyboardLayout
.
With this knowledge it is much easier to create an on-screen keyboard, and present a keyboard language you never used before.
The qwerty-range seems match every time, and you can also match it to Microsoft's own Keyboard Layouts, to ensure that it is right.
Feedback
If you have solved this problem differently, I would like to hear from you in the comment field!
History
v1.0 Init release to the public.