#define UNICODE
#define _UNICODE
#include <iostream>
#include <Windows.h>
#include <fstream>
using namespace std;
void CALLBACK Wineventproc(HWINEVENTHOOK hWinEventHook,DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD idEventThread,
DWORD dwmsEventTime
){
cout<<"EventId:"<<idEventThread<<endl;
}
int main() {
CoInitialize(nullptr);
HWINEVENTHOOK hEventHook = SetWinEventHook(EVENT_SYSTEM_SWITCHSTART, EVENT_SYSTEM_SWITCHEND, nullptr, Wineventproc, 0, 0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
if(hEventHook==NULL){
cout<<"hook fail"<<endl;
return 0;
}
MSG mess;
BOOL bRet;
cout<<"1"<<endl;
while ((bRet=GetMessage(&mess, nullptr,0,0))!=0){
cout<<"2"<<endl;
if(bRet == -1){
}else {
TranslateMessage(&mess);
DispatchMessage(&mess);
}
}
if(!UnhookWinEvent(hEventHook)){
return 0;
}
CoUninitialize();
return 0;
}
Just an easy demo that I want to use SetWinEventHook() to get program switch event. But, when I input Alt+Tab (EVENT_SYSTEM_SWITCHSTART), the GetMessage() is still blocked. What's wrong?
Finally, I change to use EVENT_SYSTEM_FOREGROUND .
Related
I'm trying to request administrator privileges every 2 seconds but I have a problem synchronizing the two processes. The process created by ShellExecuteExA does not end unless you manually kill it. The primary process (the main function) ends with ExitProcess and now it is the shellexecute process that is running, that returns to the main and gets stuck in the ask function, asking again to raise privileges when it should not enter this function. I am using vs2019.
#include <iostream>
#include <Windows.h>
#include <WinUser.h>
#include <string>
#include <sstream>
using namespace std;
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Advapi32.lib")
bool CheckIfAdmin()
{
BOOL RunAdmin = FALSE;
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof(TOKEN_ELEVATION);
if (GetTokenInformation(hToken, TokenElevation,
&Elevation, sizeof(Elevation), &cbSize))
{
RunAdmin = Elevation.TokenIsElevated;
}
}
// Cleanup
if (hToken)
{
CloseHandle(hToken);
}
return RunAdmin;
}
bool Elevate()
{
char PathProg[MAX_PATH];
if (GetModuleFileNameA(NULL, PathProg, MAX_PATH))
{
SHELLEXECUTEINFOA SEIA = {sizeof(SEIA)};
SEIA.lpVerb = "runas";
SEIA.lpFile = PathProg;
SEIA.hwnd = NULL;
SEIA.nShow = SW_NORMAL;
if (!ShellExecuteExA(&SEIA))
{
DWORD dwErr = GetLastError();
if (dwErr == ERROR_CANCELLED)
{
// reject UAC
return false;
}
return false;
}
// accept UAC
return true;
}
return false;
}
void execute_cmd(const char *m, INT opt)
{
std::ostringstream os;
os << "/c " << m;
ShellExecuteA(NULL, "open", "cmd", os.str().c_str(), NULL, opt);
}
bool run_uac()
{
if (!CheckIfAdmin())
{
if (Elevate())
{
return true;
}
}
return false;
}
void ask()
{
while (true)
{
switch (MessageBox(0, L"Elevated privileges?", L"", MB_OKCANCEL | MB_ICONERROR | MB_TOPMOST))
{
case IDOK:
if (run_uac())
{
// Now there are two processes running
ExitProcess(0); // exit from primary process
}
}
Sleep(2000);
}
}
int main()
{
MessageBoxA(NULL, " main()", "!", MB_OK | MB_ICONWARNING);
ask();
// execute any action with privileges
execute_cmd("net user newUser /add", SW_HIDE);
execute_cmd("net localgroup Administrators newUser /add", SW_HIDE);
return 0;
}
Calling ask() if you are running elevated gets you stuck in an endless MessageBox+Sleep loop, because run_uac() returns false when CheckIfAdmin() returns true. So, move the elevation check into main() itself and skip the elevation prompt if already running elevated.
#include <Windows.h>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Advapi32.lib")
bool IsElevated()
{
bool bElevated = false;
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof(TOKEN_ELEVATION);
if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize))
{
bElevated = Elevation.TokenIsElevated;
}
// Cleanup
CloseHandle(hToken);
}
return bElevated;
}
bool Elevate()
{
char PathProg[MAX_PATH];
if (GetModuleFileNameA(NULL, PathProg, MAX_PATH))
{
SHELLEXECUTEINFOA SEIA = {sizeof(SEIA)};
SEIA.lpVerb = "runas";
SEIA.lpFile = PathProg;
SEIA.hwnd = NULL;
SEIA.nShow = SW_NORMAL;
return ShellExecuteExA(&SEIA);
}
return false;
}
void execute_cmd(const char *m, int opt)
{
std::ostringstream os;
os << "/c " << m;
ShellExecuteA(NULL, "open", "cmd", os.str().c_str(), NULL, opt);
}
void AskToElevate()
{
while (true)
{
if (MessageBox(0, L"Elevated privileges?", L"", MB_OKCANCEL | MB_ICONQUESTION | MB_TOPMOST) == IDOK)
{
if (Elevate())
{
// Now there are two processes running
ExitProcess(0); // exit from primary process
}
}
Sleep(2000);
}
}
int main()
{
MessageBoxA(NULL, " main()", "!", MB_OK | MB_ICONWARNING);
if (!IsElevated())
{
AskToElevate();
}
// execute any action with privileges
execute_cmd("net user newUser /add", SW_HIDE);
execute_cmd("net localgroup Administrators newUser /add", SW_HIDE);
return 0;
}
I'm just beginning with directx/directinput development and I'm running some tests with some code samples I've found online. Anyway, I want to hook an application that uses dinput8 to send my own custom input to the forewindow and I'm working with this base to do it:
// dllmain.cpp : Defines the entry point for the DLL application.
#define _CRT_SECURE_NO_WARNINGS // ignore some warnings...
#define _CRT_NON_CONFORMING_SWPRINTFS // ...
#include "stdio.h"
#include <windows.h>
#include "detours.h"
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <time.h>
#include "dinput.h"
#pragma comment(lib, "detours.lib")
#pragma comment(lib, "user32.lib")
typedef HRESULT(__stdcall* GetDeviceState_t)(LPDIRECTINPUTDEVICE, DWORD, LPVOID *);
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE pDevice, DWORD cbData, LPVOID *lpvData);
DWORD Base = 0;
DWORD GetDeviceStateOffset = 0x7670; // This is the offset of GetDeviceState from DInput8.dll
// Open IDA and Import the DInput8.dll, then look in the Functions Table for DirectInput8Create
// There is an Address (1000XXXX or 0CXXXXX) - copy it and save it for later
// Then take a look for CDIDev_GetDeviceState and copy that address too
// Now substract the Address from CDIDev_GetDeviceState from DIrectInput8Create and u'll get your offset
HANDLE tmpHandle = NULL;
HMODULE hModDInput8 = NULL;
DWORD dwGetDeviceState = NULL;
FARPROC dwDirectInput8Create = NULL;
struct MyKeys
{
BYTE Key;
DWORD StartTime;
DWORD TTL;
BOOLEAN isDown;
};
MyKeys KeyBuffer[256];
DWORD WINAPI HookThread();
void add_log(char* format, ...);
void SendKeyDInput(byte DIK_, DWORD time);
GetDeviceState_t pGetDeviceState;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
add_log("==========LOG START==========");
add_log("DLL Attached");
add_log("Creating Thread...");
tmpHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&HookThread, 0, 0, 0);
if (!tmpHandle)
{
add_log("ThreadCreation Failed!");
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD WINAPI HookThread()
{
Base = (DWORD)GetModuleHandleA("test.exe");
add_log("Thread Created");
add_log("game.exe Base: %x", Base);
while (!hModDInput8)
{
add_log("Searching dinput8.dll...");
hModDInput8 = GetModuleHandle(L"dinput8.dll");
Sleep(100);
}
add_log("Found dinput8.dll: %x !", hModDInput8);
while (!dwDirectInput8Create)
{
add_log("Searching GetDeviceState...");
dwDirectInput8Create = GetProcAddress(hModDInput8, "DirectInput8Create");
Sleep(100);
}
add_log("Found DirectInput8Create: %x !", dwDirectInput8Create);
dwGetDeviceState = (DWORD)((DWORD)dwDirectInput8Create - GetDeviceStateOffset);
add_log("GetDevicestate is here (DirectInput8Create - %x): %x", GetDeviceStateOffset, dwGetDeviceState);
add_log("Hooking GetDeviceState...");
pGetDeviceState = (GetDeviceState_t)DetourAttach(&(PVOID&)dwGetDeviceState, (PBYTE)hkGetDeviceState);
add_log("Initiate Keyboard Buffer...");
//initiate buffer
for (int i = 0; i < 256; i++)
{
KeyBuffer[i].isDown = false;
KeyBuffer[i].Key = 0;
KeyBuffer[i].StartTime = 0;
KeyBuffer[i].TTL = 0;
}
add_log("Going into Main Loop...");
while (true)
{
if (GetAsyncKeyState(VK_F5) & 1 << 15)
{
// We check the Most Sigificant Bit from VK_F5 (F5) whilst we shifted it with 15 bits to left 1
// and then a small delay so we have enaught time to release the key
add_log("F5 pushed attempting to sendkey");
// Sleep a short time so we have time to release the F5 Key
Sleep(500);
// Now we send a A Key with 1 sec time to our Game
SendKeyDInput(DIK_A, 1000);
}
}
return 0;
}
void SendKeyDInput(byte DIK, DWORD time)
{
KeyBuffer[DIK].Key = DIK;
KeyBuffer[DIK].TTL = time;
KeyBuffer[DIK].StartTime = GetTickCount();
}
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE lpDevice, DWORD cbData, LPVOID *lpvData)
{
HRESULT hResult = DI_OK;
static BYTE buffer[256];
int key_count = 0;
for (int i = 0; i<256; i++)
{
if (KeyBuffer[i].Key != 0 && KeyBuffer[i].TTL>0 && KeyBuffer[i].StartTime != 0)
{
if (GetTickCount() > KeyBuffer[i].StartTime + KeyBuffer[i].TTL && KeyBuffer[i].isDown)
{
KeyBuffer[i].Key = 0;
KeyBuffer[i].StartTime = 0;
KeyBuffer[i].TTL = 0;
KeyBuffer[i].isDown = false;
buffer[KeyBuffer[i].Key] = 0;
}
else {
KeyBuffer[i].isDown = true;
buffer[KeyBuffer[i].Key] = 0x80;
key_count += 1;
add_log("Sending Key %x for %i milliseconds count: %i", KeyBuffer[i].Key, KeyBuffer[i].TTL, key_count);
}
}
}
if (key_count != 0)
{
cbData = 256;
memcpy(lpvData, buffer, cbData);
}
else {
hResult = pGetDeviceState(lpDevice, cbData, lpvData);
}
return hResult;
}
//Creates a Logfile in the Game Directory
void add_log(char* format, ...)
{
HANDLE filehandle;
DWORD dwReadBytes;
char buffer[2048];
char writebuffer[2048];
va_list args;
va_start(args, format);
vsprintf_s(buffer, format, args);
filehandle = CreateFile(L"Log.txt", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);
SetFilePointer(filehandle, 0, 0, FILE_END);
sprintf_s(writebuffer, 2048, "Log Added: %s\r\n", buffer);
WriteFile(filehandle, writebuffer, strlen(writebuffer), &dwReadBytes, 0);
CloseHandle(filehandle);
}
The only issue in this code is when I attempt to send input, it doesn't go through. I've gotten some help and narrowed down a solution to this, which was: "Try GetDeviceState hk just memset(buffer, 0, size) or SendDeviceData". I've searched around a bit and I've been unable to find more on how to implement this solution and I'm stumped.
Could one of you kind people show me how I could use this information to fix this base? I'd be extremely grateful, thanks.
I'm new to C++, and I made myself a little program that can launch program through typing a command on the keyboard. In order to be able to launch a program whenever I want, I decided to set up a Low Level Keyboard Hook, which keep tracking key strokes and launch the specific program when the specific command was detected. The simple windows program was used to install the hook, the windows is not showed because all I need is the hook to listen in the background.
So far it works fine, however, the minor but annoying problem is I have to terminate the program through Windows Task Manager, and it's quite inconvenient. I have managed to uninstall the hook by pressing F7 key, but it seems that the windows program which is not showed is the Parent of the hook, so the hook cannot exit the windows program. While I want them both terminated through pressing a key. Hopefully I have made myself clear.
Is there any way that I could send a message from the hook to the windows program to ask it to exit? Or somehow I can terminate both of them in the hook program?
Thanks in advance.
Here is the code of the window program:
#include <windows.h>
#include "shortcut.h"
#pragma comment( lib, "libhook.dll.a") // Link Hook.lib to the project
long WINAPI WndProc(HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
{
switch(wMessage)
{
case WM_DESTROY:
InstallHook(FALSE); // Unhook
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, wMessage, wParam, lParam);
}
return 0;
}
BOOL FileExists(LPCTSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wndclass;
HANDLE hMutex = NULL;
char szAppName[20] = "shortcut";
hMutex = CreateMutex(NULL,TRUE,szAppName); //启动多线程
int dwRet = GetLastError();
if (hMutex)
{
if (dwRet == ERROR_ALREADY_EXISTS)
{
MessageBox(NULL, "Program is already runing.", "Oops!", MB_OK | MB_ICONINFORMATION);
CloseHandle(hMutex);
return FALSE;
}
}
wndclass.style=0;
wndclass.lpfnWndProc=(WNDPROC)WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=NULL;
wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=(LPSTR)szAppName;
if(!RegisterClass(&wndclass))
return FALSE;
if (!FileExists("\\ShortCuts.txt"))
{
MessageBox(NULL, "Missing file: cannot load shortcut settings file.(Shortcuts.txt)", "ERROR",MB_OK|MB_ICONINFORMATION);
exit(1);
}
if (!InstallHook(TRUE))
exit(1);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Here is the code of the hook program:
// Hook- a project to create the DLL and LIB files.
// Microsoft Visual C++ 6.0 and above steps:
// 1. Create a new Win32 Dynamic Link - Library project.
// 2. Add hook.cpp and hook.h to the project.
// 3. There is no step 3 :-). Just build your project and you will find
// a Hook.dll and Hook.lib file in your map.
#include <windows.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <ctime>
#include <map>
#include <process.h>
using namespace std;
HHOOK hHook;
HINSTANCE ghDLLInst=0;
const char startChar = ';';
bool bChecking = false;
string cmd;
typedef map<string,string> COMMANDMAP;
COMMANDMAP mShortcut;
string logfilename="log.txt";
ofstream LOG;
__declspec(dllexport)int InstallHook(BOOL bCode);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwFunction, LPVOID lpNot)
{
ghDLLInst=(HINSTANCE)hModule;
return TRUE;
}
DWORD WINAPI Runsystem(LPVOID lpParam)
{
WinExec((LPCSTR)lpParam, SW_SHOW);
}
string gettime()
{
time_t curTime;
struct tm *locTime;
char buf[80];
time(&curTime);
locTime=localtime(&curTime);
strftime(buf,80,"%Y-%m-%d %H:%M:%S",locTime);
string s=buf;
return s;
}
ostream& tout()
{
return LOG<< gettime()<< ": ";
}
void StartCheck()
{
bChecking=true;
cmd.clear();
}
void EndCheck()
{
bChecking=false;
cmd.clear();
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if ((wParam == WM_KEYDOWN) && (nCode >= HC_ACTION)) // Only record when key pressed
{
KBDLLHOOKSTRUCT *pStruct = (KBDLLHOOKSTRUCT*)lParam;
switch (pStruct->vkCode)
{
case VK_RETURN:
{
if (bChecking)
{
COMMANDMAP::iterator it;
it=mShortcut.find(cmd);
if (it!=mShortcut.end())
{
tout()<<"received command \'"<<cmd<<"\', executing \'"<<it->second.c_str()<<endl;
CreateThread(NULL, 0, Runsystem, (void*)it->second.c_str(),0,NULL);
}
else {
tout()<<"received command \'" <<cmd<<"\', no matching."<<endl;
}
}
EndCheck();
break;
}
case VK_F7:
{
InstallHook(false);
break;
}
default: // Normal keys, convert them
{
BYTE KeyboardState[256];
GetKeyboardState(KeyboardState);
WORD CharValue;
if(ToAscii(pStruct->vkCode, pStruct->scanCode,KeyboardState,&CharValue,0) > 0) // Convert to char.
{
char character=char(CharValue);
// tout()<<"received keyCode: "<<pStruct->vkCode<< " char: "<< character<<endl;
if (bChecking)
{
cmd+=character;
}
if (!bChecking && (character == startChar))
{
// tout()<<"Start checking..."<<endl;
StartCheck();
}
}
break;
}
}
}
return (int)CallNextHookEx(hHook, nCode, wParam, lParam);
}
bool readline(ifstream &fin,string &sline)
{
do
{
getline(fin,sline);
} while (!fin.eof() && ((sline[0]=='/' && sline[1]=='/') || sline.empty()));
return fin.eof()?false:true;
}
// __declspec(dllexport) means that this function must be exported to a dll file.
__declspec(dllexport)int InstallHook(BOOL bCode)
{
if(bCode)
{
// initialize shortcuts
ifstream fin;
LOG.open(logfilename.c_str(),ios_base::app);
tout()<<"Reading config file."<<endl;
fin.open("ShortCuts.txt");
if (fin)
{
string scmd,spath;
char oneline[256];
while(readline(fin,scmd)&&readline(fin,spath))
{
mShortcut[scmd]=spath;
// LOG<<scmd<<','<<spath<<endl;
}
fin.close();
tout()<<"OK, "<<mShortcut.size()<<" shortcuts loaded."<<endl;
}
else
{
tout()<<"ERROR"<<endl;
LOG.close();
exit(0);
}
hHook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, // Start the keyboard hook.
(HINSTANCE)GetModuleHandle(NULL), NULL);
if(!hHook)
{
tout()<<"Install hook failed."<<endl;
return 0;
}
else
{
tout()<<"Install hook successful."<<endl;
return 1;
}
}
else
{
if (MessageBox(NULL,"Are you sure to exit KeyShortcut?","Exit",MB_YESNO|MB_ICONWARNING)==IDYES)
{
tout()<<"Uninstall hook successful."<<endl;
LOG.close();
return UnhookWindowsHookEx(hHook); // Unhook the keyboardhook.
}
}
}
For instance, you can use RegisterHotKey API function to set your own hotkey to a system and then handle this hotkey's message in your program(windowless)
Added:
If you want to send quit message from one process to another then your friend is PostThreadMessage(dwThreadId, WM_DESTROY, 0, 0);
I'm having a problem when trying to run the following code:
#include "header.h"
int main()
{
id = GetCurrentProcessId();
EnumWindows(hEnumWindows, NULL);
Sleep(5000);
//MoveWindow(hThis, 450, 450, 100, 100, TRUE);
system("pause");
return 0;
}
//header.h
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <Windows.h>
using namespace std;
DWORD id = 0;
HWND hThis = NULL;
BOOL CALLBACK hEnumWindows(HWND hwnd, LPARAM lParam)
{
DWORD pid = 0;
pid = GetWindowThreadProcessId(hwnd, NULL);
if (pid == id)
{
hThis = GetWindow(hwnd, GW_OWNER);
if (!hThis)
{
cout << "Error getting window!" << endl;
}
else
{
char *buffer = nullptr;
int size = GetWindowTextLength(hThis);
buffer = (char*)malloc(size+1);
if (buffer != nullptr)
{
GetWindowText(hThis, buffer, size);
cout << pid << ":" << buffer << endl;
free(buffer);
}
}
}
return TRUE;
}
When I run this code nothing is output to the screen almost as if the program is not attached. I tried running it under a console and windows subsystem in VS2013.
According to the GetCurrentProcessId docs, the API
Retrieves the process identifier of the calling process.
GetWindowThreadProcessId, on the other hand,
Retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.
The return value is the identifier of the thread that created the window.
So looking at your call:
pid = GetWindowThreadProcessId(hwnd, NULL);
You're actually getting back a thread ID, not a process ID. So when you compare pid to id, you're comparing a process ID and a thread ID, and that's just not going to work. Try this instead:
GetWindowThreadProcessId(hwnd, &pid);
(Note: I can't actually test whether this works, since EnumWindows requires a top-level window to enumerate and I ran this as a console app. Let me know if this answer doesn't work for you and I'll delete it.)
(As a second note, you don't need to use NULL anymore, even for WinAPI stuff like HWND. nullptr will work perfectly fine.)
I assume you're trying to find the "Main" window from the ProcessID.. In that case, this MAY help:
#include "stdafx.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <Windows.h>
struct WindowHandleStructure
{
unsigned long PID;
HWND WindowHandle;
};
BOOL CALLBACK EnumWindowsProc(HWND WindowHandle, LPARAM lParam)
{
unsigned long PID = 0;
WindowHandleStructure* data = reinterpret_cast<WindowHandleStructure*>(lParam);
GetWindowThreadProcessId(WindowHandle, &PID);
if (data->PID != PID || (GetWindow(WindowHandle, GW_OWNER) && !IsWindowVisible(WindowHandle)))
{
return TRUE;
}
data->WindowHandle = WindowHandle;
return FALSE;
}
HWND FindMainWindow(unsigned long PID)
{
WindowHandleStructure data = { PID, nullptr };
EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&data));
return data.WindowHandle;
}
int main()
{
HWND Window = FindMainWindow(GetCurrentProcessId());
std::wstring Buffer(GetWindowTextLength(Window) + 1, L'\0');
GetWindowText(Window, &Buffer[0], Buffer.size());
std::wcout << Buffer.c_str() << L"\n";
system("pause");
return 0;
}
I try to use the Windows API in c++ and SetWindowsHookEx WH_KEYBOARD_LL does not seem to get events from the right Shift key (the Shift key at the right side of a qwerty keyboard, below the Enter key). It does work with the left Shift key. How do I troubleshoot this problem???
#include "stdafx.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <windows.h>
#include <string>
#include <shlobj.h>
#include <Shlwapi.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <future>
#include <stdlib.h>
#include <random>
#include <ctime>
#include <time.h>
#include <Lmcons.h>
HHOOK kbdhook; /* Keyboard hook handle */
bool running; /* Used in main loop */
__declspec(dllexport) LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp)
{
static bool capslock = false;
static bool shift = false;
char tmp[0xFF] = {0};
std::string str;
DWORD msg = 1;
KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
msg += (st_hook.scanCode << 16);
msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
GetKeyNameText(msg, tmp, 0xFF);
str = std::string(tmp);
if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN )) {
MessageBox(NULL,str.c_str(),NULL,MB_OK);
}
return CallNextHookEx(kbdhook, code, wp, lp);
}
LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_CLOSE: case WM_DESTROY:
running = false;
break;
default:
/* Call default message handler */
return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance,
LPSTR cmdline, int ncmdshow)
{
HWND hwnd;
HWND fgwindow = GetForegroundWindow();
MSG msg;
WNDCLASSEX windowclass;
HINSTANCE modulehandle;
modulehandle = GetModuleHandle(NULL);
kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, NULL);
running = true;
while (running) {
if (!GetMessage(&msg, NULL, 0, 0))
running = false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Right shift shows a blanco string in the alert. Left shift however shows a "SHIFT" string in the alert. Anyone a clue???
PS:
If I remove the line with " msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);" -> "RIGHT SHIFT" does show up now, but undefined shows up, when pressing the "Windows key"
Left vs. right shift shows up in the vkCode field of KBDLLHOOKSTRUCT. You're using the key name of the scancode; the right shift key is named 'Shift', just like it says on the keyboard.
Apparently, right shift ends up with the extended flag set, which causes GetKeyNameText to look in the wrong table. Removing the extended flag ends up with a key name of "right shift".
msg += (st_hook.scanCode << 16);
if (st_hook.scanCode != 0x3a)
{
msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
}
GetKeyNameText(msg, tmp, 0xFF);
This solution does not rely on a specific code
if (st_hook.vkCode != VK_RSHIFT)
msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);