1

Scenario

I've written a simple keylogger using the modern RawInput technique registering the desired device for event/data interception.

Then, I'm using basically all these Windows API member definitions:


Problem/Question

I'm using a non-English keyboard with a non-English O.S, then, my problem begins when I try to parse an special key of this keyboard like a ñ/Ñ character which is recognized as an System.Windows.Forms.Keys.OemTilde key, or a ç/Ç character which is recognized as an System.Windows.Forms.Keys.OemQuestion key.

I would like to make my keylogger lenguage-specific aware (or at least, with proper character recognition for my current culture, es-ES), but I'm stuck because lack of knowledges to start retrieving properlly those characters.

Please, note that my intention is to learn how I can do it in an efficient/automated way like the O.S does with my keyboard when I press an Ñ character it types that Ñ, what I mean is that I'm totally aware of a solution that implies to perform a manual parsing of special characters like for example this:

Select Case MyKey

    Case Keys.OemTilde
        char = "ñ"c

End Select

That is not the behavior that I'm looking for, but I can understand that maybe I need additional "things" to reproduce a good recognition/translation of those chars for each kind of keayborad, but what "things" I need?.


Research

I'm not sure how to proceed, because as I said, I don't have the knowledges to know the answer to this problem (that's why I'm asking), but I imagine that the knowledge of the current keyboard layout will be involved, then, I know that I can retrieve the current keyboard layout with the CultureInfo.CurrentCulture.KeyboardLayoutId property.

I know that the keyboard layout for culture en-US is 1033, and for culture es-ES is 3082.

Also, note the documentation of the the MakeCode member of the RAWKEYBOARD structure, maybe it seems to be a hint for what I pretend to do, I don't know:

MakeCode

Type: USHORT

The scan code from the key depression. The scan code for keyboard overrun is KEYBOARD_OVERRUN_MAKE_CODE.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • I am not sure, but this link may give help http://stackoverflow.com/questions/6929275/how-to-convert-a-virtual-key-code-to-a-character-according-to-the-current-keyboa – Sreejith Jul 03 '15 at 09:07
  • @Sreejith AWESOME!! I was trying to find the answer for this much months in the past. Please feel free to post an answer to give you the bounty reward. `ToUnicode` function is the answer!, tested and it works perfect. Thanks. – ElektroStudios Jul 03 '15 at 10:23
  • [OFFTOPIC] The guy of the downvotes has come back to StackOverflow. [/OFFTOPIC] – ElektroStudios Jul 03 '15 at 10:27

1 Answers1

2

but actually it is a guess work Here is the code I found.

The correct solution is the ToUnicode WinAPI function:

[DllImport("user32.dll")]
public static extern int ToUnicode(uint virtualKeyCode, uint scanCode,
    byte[] keyboardState,
    [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
    StringBuilder receivingBuffer,
    int bufferSize, uint flags);



static string GetCharsFromKeys(Keys keys, bool shift, bool altGr)
{
    var buf = new StringBuilder(256);
    var keyboardState = new byte[256];
    if (shift)
        keyboardState[(int) Keys.ShiftKey] = 0xff;
    if (altGr)
    {
        keyboardState[(int) Keys.ControlKey] = 0xff;
        keyboardState[(int) Keys.Menu] = 0xff;
    }
    WinAPI.ToUnicode((uint) keys, 0, keyboardState, buf, 256, 0);
    return buf.ToString();
}


Console.WriteLine(GetCharsFromKeys(Keys.E, false, false));    // prints e
Console.WriteLine(GetCharsFromKeys(Keys.E, true, false));     // prints E

// Assuming British keyboard layout:
Console.WriteLine(GetCharsFromKeys(Keys.E, false, true));     // prints é
Console.WriteLine(GetCharsFromKeys(Keys.E, true, true));      // prints É
Sreejith
  • 166
  • 8