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.
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.
kbd.h header-file, from Microsoft DDK, this pointer is defined:
#define KBD_LONG_POINTER __ptr64
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 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
CKLL class has four public functions + one helper (from
BOOL LoadDLL(CString sKeyboardDll);
CString GetChar(USHORT iVK);
CString GetSC(USHORT iVK);
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
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
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.
If you have solved this problem differently, I would like to hear from you in the comment field!
v1.0 Init release to the public.