keystroke util, keyboard callback problem - winapi

I got this idea a long time ago when i saw an app do this for a game.
i want to catch certain keystrokes. Something like /s myCommand. I had ppl msg me and mess me up through msn so my first command would be something like killmsn. I looked up the resource on msdn and got this far. This doesnt work, why doesnt it? is it BC of sleep? how else should i do this, note i dont have a window and i want this to be a console app. my KeyboardProc is NEVER called
#include <windows.h>
#include <stdio.h>
HHOOK hook;
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
printf("%c", wParam);
return CallNextHookEx(hook, code, wParam, lParam);
}
int main()
{
hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(0), 0);
Sleep(10000);
UnhookWindowsHookEx(hook);
return 0;
}

Solution
//Sleep(10000);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hook);

Related

Is WM_CHAR message possible with a DialogBox() modal dialog?

I've been searching for the answer for hours, and a common solution is to respond to a WM_GETDLGCODE message, but I never get that message to respond to.
My example code is:
#include <windows.h>
#include "resource.h"
static LRESULT CALLBACK DlgProc(HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (wParam) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
return TRUE;
}
break;
case WM_GETDLGCODE:
MessageBox(hDlg, "Got WM_GETDLGCODE", "DlgProc", MB_OK);
return DLGC_WANTCHARS;
case WM_CHAR:
MessageBox(hDlg, "Got WM_CHAR", "DlgProc", MB_OK);
break;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szcmdline, int iCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1),
NULL, DlgProc);
return 0;
}
The dialog is a single edit box (1st tab stop) with the Ok and Cancel buttons. The problem is, I get neither the WM_GETDLGCODE nor the WM_CHAR message. Before I continue down this path, I just want to know if this should work or not. Hooks is my next choice, but if WM_CHAR is available, it seemed like a less complicated solution if I want to keep the dialog modal.

SetWindowsHookEx to determine when a window is deactivated

I have a global WH_CBT 32bit hook that I am using to determine when a window is about to be activated using HCBT_ACTIVATE.
How can I determine when the window is about to be deactivated?
There is the CBTACTIVATESTRUCT which has hWndActive, but that is sometimes 0x0and it wont work when switching to a 64bit window.
There is no HCBT_DEACTIVATE.
As#Remy Lebeau mentioned, you can use WM_ACTIVATE message. This message is sent both when the window is activated or deactivated.
Set a WH_CALLWNDPROC hook to capture the deactivated message, it will get the messages before the system sends them to the destination window procedure.
For more detail:
Use a function in a DLL for a non-local hook:
#include <Windows.h>
#include <stdio.h>
LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
HWND hwnd;
//...
DWORD threadID = GetWindowThreadProcessId(hwnd, NULL);
HINSTANCE hinstDLL = LoadLibrary(TEXT("..\\Debug\\ProcHookDLL.dll"));
void (*AttachHookProc)(DWORD);
AttachHookProc = (void (*)(DWORD)) GetProcAddress(hinstDLL, "AttachHook");
AttachHookProc(threadID);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
//...
};
Here is the code for the DLL:
#include <Windows.h>
#include <stdio.h>
HMODULE thisModule;
HHOOK hook;
LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam);
#ifdef __cplusplus // If used by C++ code,
extern "C" { // we need to export the C interface
#endif
__declspec(dllexport) void AttachHook(DWORD threadID) {
hook = SetWindowsHookEx(WH_CALLWNDPROC, LaunchListener, thisModule, threadID);
}
#ifdef __cplusplus
}
#endif
LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam) {
// process event here
if (nCode >= 0) {
CWPSTRUCT* cwp = (CWPSTRUCT*)lParam;
if (cwp->message == WM_ACTIVATE) {
if (LOWORD(cwp->wParam) == WA_INACTIVE)
{
//the window being deactivated
}
else
{
//the window being activated
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

SetWindowsHookEx to monitor Windows open and close

I took this example code from here that hooks a function to intercept keyboard events, and it works:
#include <Windows.h>
// variable to store the HANDLE to the hook. Don't declare it anywhere else then globally
// or you will get problems since every function uses this variable.
HHOOK _hook;
// This struct contains the data received by the hook callback. As you see in the callback function
// it contains the thing you will need: vkCode = virtual key code.
KBDLLHOOKSTRUCT kbdStruct;
// This is the callback function. Consider it the event that is raised when, in this case,
// a key is pressed.
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
if (wParam == WM_KEYDOWN)
{
// lParam is the pointer to the struct containing the data needed, so cast and assign it to kdbStruct.
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
// a key (non-system) is pressed.
if (kbdStruct.vkCode == VK_F1)
{
// F1 is pressed!
MessageBox(NULL, "F1 is pressed!", "key pressed", MB_ICONINFORMATION);
}
}
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook()
{
// Set the hook and set it to use the callback function above
// WH_KEYBOARD_LL means it will set a low level keyboard hook. More information about it at MSDN.
// The last 2 parameters are NULL, 0 because the callback function is in the same thread and window as the
// function that sets and releases the hook. If you create a hack you will not need the callback function
// in another place then your own code file anyway. Read more about it at MSDN.
if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)))
{
MessageBox(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
}
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
void main()
{
// Set the hook
SetHook();
// Don't mind this, it is a meaningless loop to keep a console application running.
// I used this to test the keyboard hook functionality. If you want to test it, keep it in ;)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
}
}
I am trying to make the similar code works for WH_GETMESSAGE to intercept WH_CREATE and WH_DESTROY messages, but it didn't work:
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
HHOOK _hook;
LRESULT CALLBACK GetMsgProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
std::cout << "Enter hook\n";
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
std::cout << "HC_ACtION\n";
if (wParam != PM_REMOVE) return NULL;
MSG m = *((MSG*)lParam);
std::cout << "Message received\n";
TCHAR Buffer[MAX_PATH];
if (GetModuleFileNameEx(m.hwnd, 0, Buffer, MAX_PATH))
{
// At this point, buffer contains the full path to the executable
MessageBox(NULL, Buffer, L"key pressed", MB_ICONINFORMATION);
}
else
{
// You better call GetLastError() here
}
//CloseHandle(Hand);
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook()
{
if (!(_hook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, 0)))
{
MessageBox(NULL, L"Failed to install hook!", L"Error", MB_ICONERROR);
}
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
void main()
{
// Set the hook
SetHook();
// Don't mind this, it is a meaningless loop to keep a console application running.
// I used this to test the keyboard hook functionality. If you want to test it, keep it in ;)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
}
}
MSDN specifies to use the function GetMsgProc with a predefined signature, but I don't see it does anything.

Making console window invisible ruins the program

I am hooking the keys and writing them down to a file, everything works fine but when I make the console window hidden, I can not hook the keys and print to a file, how to get rid of this problem? Down below when I removed ShowWindow() function I am able to hook the keys but otherwise I am not. I see the process is still running on task manager by the way.
See my example code here:
KBDLLHOOKSTRUCT kbdSTRUCT;
int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevious, LPSTR cmdline, int cmdshow ) {
HWND wnd;
wnd = GetConsoleWindow();
ShowWindow(wnd, FALSE);
HHOOK kbdHOOK;
kbdHOOK = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
MSG msgg;
while(GetMessage(&msgg, NULL, 0, 0) > 0){
TranslateMessage(&msgg);
DispatchMessage(&msgg);
}
}
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar){
if(nCode >= 0){
if(wPar == 256){
kbdSTRUCT = *(KBDLLHOOKSTRUCT *)lPar;
if(kbdSTRUCT.vkCode == 0x90){
//fprintf function here to write to a file
return CallNextHookEx(NULL, nCode, wPar, lPar);
}
}
}
}
Thank you so much
When using gcc, -mwindows will set the Windows subsystem, this way no console window will appear when entry point is WinMain
gcc myfile.c -mwindows -o myfile.exe
Use a global variable to store SetWindowsHookEx result and pass it kbdProc, use that in CallNextHookEx
#include <Windows.h>
#include <stdio.h>
HHOOK hhook = NULL;
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar)
{
if(nCode >= 0) {
if(wPar == WM_KEYDOWN) { //or WM_KEYUP!
KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT*)lPar;
int c = kb->vkCode;
FILE *file = fopen("test", "a");
switch(c) {
case VK_NUMLOCK: fprintf(file, "VK_NUMLOCK\n"); break;
case VK_RETURN: fprintf(file, "\n"); break;
default: fprintf(file, "%c", c); break;
}
fclose(file);
}
}
return CallNextHookEx(hhook, nCode, wPar, lPar);
}
int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int show)
{
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhook);
return 0;
}
Make sure to use the correct windows constants. For example ShowWindow(wnd, SW_HIDE) instead of ShowWindow(wnd, FALSE). WM_KEYUP instead of 256. Otherwise the code will be too confusing when you look at the next day. Other people will not understand it.
You need to examine the shift key in addition to VK_NUMLOCK to find upper/lower case letters ...

How to handle the message-only window to get the messages from the console window?

I'm trying to know when a console window has moved so I created a new message-only window to get the messages of the console but I don't know if it is working because the message is apparently never being received.
#define WINVER 0x0501
#include <windows.h>
#include <iostream>
WNDPROC glpfnConsoleWindow; // NEW
using namespace std;
LRESULT APIENTRY MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
cout<<"Window moved"<<endl;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
// NEW
return CallWindowProc(glpfnConsoleWindow, hwnd, uMsg, wParam, lParam);
//return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
MSG Msg;
const char lpcszClassName[] = "messageClass";
WNDCLASSEX WindowClassEx;
// == NEW
HWND consHwnd;
consHwnd = GetConsoleWindow();
glpfnConsoleWindow = (WNDPROC)SetWindowLong(consHwnd, GWL_WNDPROC, (LONG)MainWndProc);
// ==
ZeroMemory(&WindowClassEx, sizeof(WNDCLASSEX));
WindowClassEx.cbSize = sizeof(WNDCLASSEX);
WindowClassEx.lpfnWndProc = MainWndProc;
WindowClassEx.hInstance = hInstance;
WindowClassEx.lpszClassName = lpcszClassName;
if (RegisterClassEx(&WindowClassEx) != 0)
{
// Create a message-only window
hwnd = CreateWindowEx(0, lpcszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
if (hwnd != NULL)
cout<<"Window created"<<endl;
else
UnregisterClass(lpcszClassName, hInstance);
}
ShowWindow(hwnd,nCmdShow);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
Perhaps you should process WM_MOVE, which, according to the documentation, is sent after the window has been moved. WM_SIZE is sent when the size changes.
I think your problem is that the WM_MOVE and WM_SIZE messages are going to the console window rather than to your hidden window.
I suspect you'll have to call GetConsoleWindow to get the console window handle, and then call SetWindowLong to attach your window proc to the console window. Be sure to pass messages on to the original window proc.

Resources