After some trial and error I found out why. Not sure about other keys, but for R/L shift and CapsLock, Win 11 seems to change the 1st byte of their scan codes to 0xe0
. Previously it was 0x00
.
My previous solution is this:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,05,00,00,00,3a,00,2a,00,2a,00,3a,00,36,00,1c,00,1c,00,36,00,00,00,00,00
Formatted with each 2 bytes on a line:
00,00,00,00,
00,00,00,00,
05,00,00,00,
3a,00,2a,00,
2a,00,3a,00,
36,00,1c,00,
1c,00,36,00,
00,00,00,00
Reading MS doc for mouse and keyboard driver, we know that this is interpreted like this:
So, we need to put scan code in two bytes, lower bytes first(little-endian), and byte 1 and 2 represent the new scan code, the old scan code to replace on bytes 3 and 4.
For example 3a,00,2a,00
means, find out the key who had 0x00 0x2a
as scan code, and replace with new scan code 0x00 0x3a
. The result is that the key L Shift works as CapsLock. 3a
is CapsLock
, and 2a
is L Shift
. And because I want to swap the two, so next line is 2a,00,3a,00
, which means the opposite.
The next two lines are similar, swap 36
(R SHIFT) and 1c
(Enter).
Then, how do we find out the scan codes? In MS scan code specification, Appendix A: Windows Standard PS/2 Scan Codes, there is a table showing all scan codes:
, where you can find exactly the same scan codes as I said:
BUT, when we talk about the scan code, there are 2 bytes. 0036
means the higher byte is 0x00
, and lower byte is 0x36
. But in the table you also can see there are 2 values on 2 lines, first with higher byte 00
(null), second line starts with E0
, meaning 0xe0
. Why?
I am not expert so I can only guess from what I read in the same file:
Prefixed Scan Codes
Some keys on standard 101/102-key keyboards (and the Microsoft Natural keyboard amongst others) emit a sequence of two bytes, where the 1st byte is either 0xE0 or 0xE1. This method is used primarily to distinguish between left and right versions of the same key, e.g., Left Alt is 0x38 while Right Alt is 0xE0 0x38. The 0xE0 prefix is indicated as the “extended bit” (bit 24) in the lParam of messages such as WM_KEYDOWN. The 0xE1 prefix is much rarer, but operates similarly to the 0xE0 prefix. It’s presence or absence is not indicated through the API in any way.
So maybe the second value could be used but previously in Win 10 it is not. I am using the same keyboard for my Win 10 and Win 11, so it cannot be that the same keyboard suddenly starts to emit different higher byte; it can only be Win 11 changed something.
How did I find out? Well, along my investigation I found that SharpKey could detect the scan code, and while it is reading my previous solution in registry, it also thinks I am mapping right mostly correct; however, it shows one key(Enter) is unknown. When I remap in SharpKey, it tells me Enter is 0xe0 0x1c
and gives me a .reg
file like:
3a,00,2a,00, <<< SharpKey still thinks 0x00 is correct value for higher byte
2a,00,3a,00, <<< ditto
36,00,1c,e0, <<< set Enter to use scan code 0x00 0x36
1c,e0,36,00, <<< set R Shift to use scan code 0xe0 0x1c
But, only the last line works! R shift will do Enter's job but Enter does not switch case!
That leads me to think that, is it possible that now Win 11 only accepts 0xe0
as first byte? So I changed all first byte 00
to be e0
and all starts to work...
Is this a bug in Win 11 that it starts to take only 0xe0
as first byte????