Processing All Keyboard Inputs (Hooks) - c++

I'm making a program that records all the keyboard actions, and stores this information into a log file (Keylogger). I just can't seem to find a good way of doing this.
What I have so far: A LowLevelKeyboardProc, The Virtual Key Code + the Scan Code of the Key being pressed.
What I would like: Using these codes, I will process and write information about the keyboard action being done. For invisible keys I would like the format: "[SHIFT], [ENTER], [ESC], etc. And for visible keys I would simply like their Ascii value (both Upper Case, and Lower Case), including if they enter: !##$%,etc..
I have a few ideas, but I don't know how I could capture everything. I have the information, I just don't know how to process it efficiently.

Refer to my post from here: Other Post
I've got example code for how to install a low-level keyboard hook and how to process the keystrokes.

Since you already have the hook working, all you need is a mapping from key codes to names for special keys. Just pre-populate an array of strings indexed by the key code:
const char *map[256];
map[VK_SHIFT] = "[SHIFT]";
map[VK_ENTER] = "[ENTER]";
...
Then in your hook function, check if the key is a printable character, if so, print it directly, otherwise lookup the name of the key and print that:
if (isprint(vkCode))
yourFile << char(vkCode);
else
yourFile << map[vkCode];

Related

How to retrieve audio session name similar to one in Windows' built-in mixer app?

I'm building a mixer app and need to get the user-friendly names for each audio session.
I tried:
IAudioSessionControl::GetDisplayName() method, but it returned empty string for each session.
Calling QueryFullProcessImageName() and GetModuleFileNameEx(), but they only output C:\Users\ since I have Cyrillic letters in the path. But even if they did output the full path, I assume it would end with something like ...\brave.exe (correct me if I'm wrong), which is not a user-friendly name like Brave Browser in Windows' built-in mixer.
I also tried getting all process names and PIDs like this, and later match them to session process IDs, which successfully gave me names like chrome.exe or steam.exe, but they are still, again, not quite what I want:
std::vector<std::pair<DWORD, wchar_t*>> processes;
HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
Process32First(handle, &entry);
do {
processes.emplace_back(entry.th32ProcessID, entry.szExeFile);
} while (Process32Next(handle, &entry));
CloseHandle(handle);
What I want is to retrieve names like in the built-in mixer app, ie Steam, Chrome Browser, Zoom Meetings, etc.
Is there a way to achieve this? Or does Microsoft use some kind of black magic here?
Calling QueryFullProcessImageName() and GetModuleFileNameEx(), but they only output C:\Users\ since I have Cyrillic letters in the path.
Then you are simply not displaying the path correctly. The presence of Cyrillic characters is not a problem.
I also tried getting all process names and PIDs like this, and later match them to session process IDs, which successfully gave me names like chrome.exe or steam.exe, but they are still, again, not quite what I want
That code doesn't work properly. You are storing pointers in your std::vector that point to a single wchar_t[] buffer which is modified on each loop iteration. You should instead store std::wstring instead of wchar_t* so each path is copied.
What I want is to retrieve names like in the built-in mixer app, ie Steam, Chrome Browser, Zoom Meetings, etc.
Once you have the path to the EXE, you can use GetFileVersionInfo() and VerQueryValue() to retrieve the app's human-readable FileDescription. See Retrieve File Description for an Application using VerQueryValue.

Get any key from keyboard in C++ including keys like control

I'm programming in C++ and have run into a wall.
I need to get input from the keyboard. The problem is that I also need to get input from keys like control, scroll lock, windows key, etc. I also need to be able to differentiate between the numpad and regular numbers 0-9.
I tried using _getch(). While it can get keys like arrow keys and the numpad, I can't get keys like control, shift and scroll lock.
Does anyone have any suggestions?
There is no standard way to do this because C++ does not assume the system even has all those things.
A good solution for what you are trying to do is the SDL library. Look here:
https://www.libsdl.org/
I see the word "windows key" so I'm assuming you're programming for Windows
Use WinAPI ReadConsoleInput
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD read;
if (!ReadConsoleInput(hInput, &ir, 1, &read) || read == 0) {
// Something went wrong
}
if (ir.EventType == KEY_EVENT) {
// Do stuff here
}
Refer to KEY_EVENT_RECORD for more information. You can get control keys states from
ir.Event.KeyEvent.dwControlKeyState
This is an example provided by Microsoft.

Unicode and Text Controls Not Converting to UTF8 correctly

there. I am trying to pass a Text Field contents into a database call (mysql). When I look at the field that gets returned from Text->getvalue.(funct) call - I simply do not get the text that was entered into the field - via any of the UTF functions in WXWidgets. I have tried the following:
wxChar buffer = ((wxTextCtrl*)FindWindow(wxID_TITLE))->GetValue().mb_str(wxConvUTF8);
//GooglyGook for whole thing
wxChar buffer = ((wxTextCtrl*)FindWindow(wxID_TITLE))->GetValue().mb_str();
//NULL it fails completely
wxChar buffer = ((wxTextCtrl*)FindWindow(wxID_TITLE))->GetValue().ToUTF8();
//More GOoblygook
wxChar buffer = ((wxTextCtrl*)FindWindow(wxID_TITLE))->GetValue().utf8_str();
//More Gooblygook
message.Printf(_T("The title saved as wxCharBuffer =%s"),buffer.data());
wxMessageBox(message,_("Rivendell"), wxICON_ERROR|wxOK);
The message box is how I am trying to display what is in the wxChar buffer,
but I am running in debug so I can simply look at it during the run and confirm that it is incorrect. Please note that I have tried these wxChar buffer lines one at a time separately (not like they are listed here). Just wanted to show things I had tried.
What is the correct way to do this? The type of characters I am attempting to save in the db looks like:"check Todd 1 乞: 乞丐 qǐgài, 乞求 qǐqiú, 乞讨 qǐtǎo."
The gooblygook output looks like Chineese characters etc.. even in the English part of the field (Check Todd)...
Anyone who has an idea of how to do this please let me know. Thanks...
Tb
I appreciate the help provided, and after trying some things I found an answer.
The correct way to do this seems to be the following: Put the TextCtrl field into a wxString using wx_str(). Then put the wxString into a wxCHarBuffer via toUTF8() function. Then use the data() function of the wxCHarBuffer to pass a char pointer.
Part of my problem stemmed from trying to display what was in those fields via Visual Studio Debugger, and/or wxMessage boxes - so sometimes my conversions were wrong (as noted by the previous poster).
I was able to set the wxString (s) to Unicode characters and have it be handled correctly by the mysql call (i.e. Call would crash before). The chk_title variable returned seems to be correctly encoded into UTF8 and escaped.
Thanks.

Handling keyboard input in win32, WM_CHAR or WM_KEYDOWN/WM_KEYUP?

So in the text editor program that i've been working on, I've used WM_CHAR to process input from the keyboard. However, I found that some of the character mesages are not recorded. For example, if I use [shift]+ number key to type a symbol such as % or &, some re recorded while others such as [shift]+9 (which results in ')'), are not recorded. So, I'm wondering if I should use WM_KEYDOWN/WMKEYUP pair to handle keyboard input. I once wrote a keylogger in assembly(actually it was just a tutorial that i was trying out) and had used WM_KEYDOWN/WM_KEYUP pairs and that worked out quite good. So, should I move on to this, or is it something unusual that is happening with my program?
Thanks,
Devjeet
This is really a long reply to your comment above, but putting it in an answer because it's too long for a comment :)
The core issue to understand here is that keys and characters are not quite the same thing. Some (but not all) keys generate characters; some keys generate different characters depending on shift or other keyboard state. And to implement an editor, you need to handle both textual input and also non-textual keyboard input like arrow keys. Now the long-winded version, picking off from what seems to be an incorrect assumption:
Apparently, windows works in really strange ways. [...] It seems that when you press [shift]+9, windows sends a VK_LEFT in the wParam of message WM_CHAR
Sounds like you might be mixing two things up here. The thing with WM_CHAR is that it gives you character codes for textual characters: so if someone presses the 9 key, you'll get '9'. If someone presses SHIFT+9, Windows will take the shift state into account - and you get '(' (if using US keyboard). But you won't ever get a WM_CHAR for arrow keys, HOME, END, and so on, since they are not textual characters. WM_KEYDOWN, on the other hand, does not deal in characters, but in VK_ codes; so pressing 9 gives you VK_9 regardless of shift state; and left arrow gives you VK_LEFT - again regardles of shift state.
The things is that WM_CHAR and WM_KEYDOWN both give you two parts to the overall input picture - but you really have to handle both to get the full picture. And have to be aware that the wParam is a very different thing in both cases. It's a character code for WM_CHAR, but a VK_ code for WM_KEYDOWN. Don't mix the two.
And to make things more confusing, VK_ values share the same values as valid characters. Open up WinUser.h (it's in the include dir under the compiler installation dir), and look for VK_LEFT:
#define VK_LEFT 0x25
Turns out that 0x25 is also the code for the '%' character (see any ascii/unicode table for details). So if WM_CHAR gets 0x25, it means shift-5 was pressed (assuming US keyboard) to create a '%'; but if WM_KEYDOWN gets 0x25, it means left arrow (VK_LEFT) was pressed. And to add a bit more confusion, the Virtual Key codes for the A-Z keys and 0-9 keys happen to be the same as the 'A'-'Z' and '0'-'9' characters - which makes it seem like chars and VK_'s are interchangable. But they're not: the code for lower case 'a', 0x61, is VK_NUMPAD1! (So getting 0x61 in WM_CHAR does mean 'a', getting it in WM_KEYDOWN means NUMPAD1. And if a user does hit the 'A' key in unshifted state, what you actually get is first a VK_A (same value as 'A') in WM_KEYDOWN, which gets translated to WM_CHAR of 'a'.)
So tying all this together, the typical way to handle keyboard is to use all of the following:
Use WM_CHAR to handle textual input: actual text keys. wParam is the character that you want to append to your string, or do whatever else with. This does all the shift- processing for you.
Use WM_KEYDOWN to handle 'meta' keys - like arrow keys, home, end, page up, and so on. Pass all the A-Z/0-9 values through, the default handling will turn them into WM_CHARs that you can handle in your WM_CHAR handler. (You can also handle numpad keys here if you want to use them for special functionality; otherwise they 'fall through' to end up as numeric WM_CHARs, depending on numlock state. Windows takes care of this, just as it handles shift state for the alphabetic keys.)
If you want to handle ALT- combos explicitly (rather than using an accelerator table), you'll get those via WM_SYSKEYDOWN.
I think there are some keys that might show up in both - Enter might show up as both a WM_KEYDOWN of VK_RETURN and as either \r or \n WM_CHAR - but my preference would be to handle it in WM_KEYDOWN, to keep editing key handling separate from text keys.
Spy++ will show you the messages being sent to a window, so you can experiment and see what messages are appropriate for your application.
If you have Visual Studio installed, it should be in your Start menu, under Programs -> Microsoft Visual Studio -> Visual Studio Tools -> Spy++.
WM_CHAR
WM_KEYDOWN
The helpful message above inspired me to create this snippet, which gives you a human-readable indication of what key was pressed from any WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP independent of the state of the modifier keys.
// get the keyboard state
BYTE keyState[256];
GetKeyboardState(keyState);
// clear all of the modifier keys so ToUnicode will ignore them
keyState[VK_CONTROL] = keyState[VK_SHIFT] = keyState[VK_MENU] = 0;
keyState[VK_LCONTROL] = keyState[VK_LSHIFT] = keyState[VK_LMENU] = 0;
keyState[VK_RCONTROL] = keyState[VK_RSHIFT] = keyState[VK_RMENU] = 0;
// convert the WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP to characters
UINT scanCode = (inLParam >> 16) & 0xFF;
int i = ToUnicode(inWParam, scanCode, keyState, outBuf, inOutBufLenCharacters, 0);
outBuf[i] = 0;
By modifying the keyState array so that all the modifier keys are clear, ToUnicode will always output the unshifted key you pressed. (So, on the English keyboard you'll never get '%' but always '5') as long as it's a human readable key. You still have to do the VK_XXX checking to sense the arrow and other non-human readable keys however.
(I was trying to rig up a user editable "hot key" system in my app, and the distinction between WM_KEYXXX and WM_CHAR was making me nuts. The code above solved that problem.)

Does there exist an "unput" for std::ostream like there exists "unget" for std::istream?

I have some parsing code that allows for escape sequences to be entered into a string of text:
// In a file or large, multi-line string ...
my_parameter="A setting for the parameter\nthat contains \"escape sequence\" characters"
When I parse it, I handle the backslashes and add the appropriate character to the string that I am building using a std::ostringstream instance. Line feeds, quotes, backslashes and such all work fine. However, I was contemplating whether or not to allow the \b sequence, and went looking to see if I can "unput" the last character from my ostringstream like you can "unget" from any std::istream. Can you do such a thing? If the function does not exist, is there a simple way to push the write position back one character and simply have the next character read overwrite it?
This is not mission-critical or anything like that, but I was curious if anyone else has come across this before.
Streams are an awful lot like the mail. each message sent on a stream is like a letter, and messages can be queued into buffers, which are like mailboxes.
If you were responsible for both putting messages into and taking messages out of a mail-box, then you could certainly know that a letter you just put there is still there for you to take back. Of course, you probably wouldn't go to the trouble of putting it in a mailbox at all, since you own both ends.
If instead, you are putting a letter in your girlfriends mailbox, you don't really have much control of when she will check her mailbox and take out all of the letters. it could be that she's sitting by the door and will snatch the letter right up and read it as soon as it passes through the slot.
More likely, you're actually delivering the letter to a box owned by the post-office (the operating system). Although many such receptacles are just bins, and mail carrier checks it once per day, It could be that the slot is connected directly to a sorting machine, and the letter gets delivered the instant you drop it.
In a streaming interface with concurrency, there is no general way to retake ownership of a write once written. If you need that, you should place an intermediate buffer between you and the stream, and flush it out to the stream only when you know for sure that you are ready.
You may use seekp to set the position of cursor in the stream (see: http://cplusplus.com/reference/iostream/ostream/seekp/).
If you may want to take back a character, don't send it until you're sure you won't want to take it back. You could implement your own "allow takebacks" logic thus:
int pending_ch = -1;
void output_char(int ch)
{
if (pending_ch >= 0)
putch(F, ch);
pending_ch = ch;
}
void unput_char(void)
{
pending_ch = -1;
}
void force_put_char(void)
{
output_char(-1);
}
A bit clunky, but that general approach can be useful for delaying output to a stream.
You could simply input a backspace character yourself. I've done it in the Windows Console, at least. This should ensure that the correct behaviour is observed regardless of the destination.