I'm trying to keyboard-hook Notepad.exe by using SetWindowsHookEx.
As you see, the working thread is sending its ASCII code, which is wParam, to the designated server.
UINT WINAPI SendToServer(LPVOID lpParam)
{
CSocket Client;
Client.Create();
Client.Connect("localhost", 6677);
Client.Send(lpParam, 2); // sending its ASICI code to Server
Client.Close();
return 0;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
TCHAR szPath[MAX_PATH] = {0,};
TCHAR* p = nullptr;
if( nCode >= 0 )
{
// bit 31 : 0 => press, 1 => release
if( !(lParam & 0x80000000) )
{
GetModuleFileName(NULL, szPath, MAX_PATH);
p = strrchr(szPath, '\\');
if( !_stricmp(p + 1, "Notepad.exe") )
{
unsigned ThreadID;
g_hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SendToServer, &wParam, 0, &ThreadID)); // a new working thread
return 0;
}
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
The problem is, for some reason related to the new working thread, Notepad occurs a critical error(if I click the 'ignore' button several times, it kinda works though.)
I deleted this line below,
g_hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, SendToServer, &wParam, 0, &ThreadID)); // a new working thread
Then no error occurs from Notepad.exe
Any help would be very appreciated.
Thanks in advance.
Will this work for you..? Hard coded paths are used only for test purposes
change the path to match where your NotePad.exe resides
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
ofstream fout;
fout.open("c:\\NotePad.exe",ios::app);
if (nCode < 0 || nCode != HC_ACTION)
return CallNextHookEx(hkb, nCode, wParam, lParam);
if ( (((DWORD)lParam & 0x80000000) == 0) && (HC_ACTION == nCode))
{
if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||((wParam>=0x2f ) &&(wParam<=0x100)))
{
if(GetAsyncKeyState(wParam) == -32767) //this solve it i got it on google but how ??
{
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
UINT scan=0;
ToAscii(wParam,scan,ks,&w,0);
fout<<char(w);
}
}
}
fout.close();
return CallNextHookEx(hkb, nCode, wParam, lParam);
}
Related
I'm trying to hook WH_GETMESSAGE from my class to determine the moment when specific window is resizing. However, looks like the hook isn't set.
Class from where I try to hook:
class WindowDisplayHelper : // public ...
{
public:
// some other public methods here
void SetMsgHook();
protected:
LRESULT CALLBACK GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam);
private:
// some other private members there
HWND m_windowHandle;
bool m_isWindowResizing = false;
static HHOOK m_msgHook;
static WindowsDisplayHelperMasterWindow* m_pThis;
};
.cpp file:
WindowDisplayHelper* WindowDisplayHelper ::m_pThis = nullptr;
HHOOK WindowDisplayHelper ::m_msgHook = NULL;
void WindowDisplayHelper ::SetMsgHook()
{
m_pThis = this;
m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
}
LRESULT CALLBACK WindowDisplayHelper::MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
if (m_pThis != nullptr)
{
return m_pThis->GetMsgProcHook(code, wParam, lParam);
}
return CallNextHookEx(0, code, wParam, lParam);
}
LRESULT CALLBACK WindowDisplayHelper::GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam)
{
DUMPER_INFO("Hooked");
if (code < 0)
{
return CallNextHookEx(0, code, wParam, lParam);
}
MSG* lpmsg = (MSG*)lParam;
DUMPER_INFO("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle);
if (lpmsg->hwnd != m_windowHandle)
{
return CallNextHookEx(0, code, wParam, lParam);
}
if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
{
DUMPER_INFO("Start window resizing");
m_isWindowResizing = true;
}
else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
{
DUMPER_INFO("Stop window resizing");
m_isWindowResizing = false;
}
return CallNextHookEx(0, code, wParam, lParam);
}
Here is how I create WindowDisplayHelper object:
bool DisplayManager::CreateWindowDisplay(TDisplayId displayId, void * windowHandle)
{
auto helper = boost::make_shared<WindowDisplayHelper>(windowHandle);
helper->SetMsgHook();
AddDisplayHelper(displayId, helper);
return true;
}
Though I call SetMsgHook() after the object is created, looks like hook isn't set, because I don't see any debug outputs in my log file and m_isWindowResizing variable always == false. So the question is why my hook doesn't work?
Thanks.
m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
This line produce a ERROR_HOOK_NEEDS_HMOD (1428) system error. It means that Cannot set nonlocal hook without a module handle. If you set dwThreadId parameter to zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread. It is a nonload hook you need specified a valid hmod parameter. You need put the hook code in a DLL as #Remy Lebeau pointed out.
Or set a valid dwThreadId parameter using GetCurrentThreadId() as #rudolfninja pointed out.
I test based on a Windows Desktop Application Template with the following code. It works. You can have a try.
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// ...
HHOOK m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, GetCurrentThreadId());
DWORD errCode = GetLastError();
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
OutputDebugString(L"Hooked");
if (code < 0)
{
return CallNextHookEx(0, code, wParam, lParam);
}
MSG* lpmsg = (MSG*)lParam;
//OutputDebugString("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle);
if (lpmsg->hwnd != m_windowHandle)
{
return CallNextHookEx(0, code, wParam, lParam);
}
if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
{
OutputDebugString(L"Start window resizing");
m_isWindowResizing = true;
}
else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
{
OutputDebugString(L"Stop window resizing");
m_isWindowResizing = false;
}
return CallNextHookEx(0, code, wParam, lParam);
}
I'm having some issues about exiting "while" loops while using keyboard hook. Here is my code:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
if (wParam == WM_KEYDOWN && nCode == HC_ACTION)
{
}
if (wParam == WM_KEYUP)
{
if (key->vkCode == VK_CAPITAL) {
capslockState = GetKeyState(VK_CAPITAL) & 0x0001;
myLoop(capslockState);
}
}
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
}
And here is my function:
int myLoop(int a) {
while (a == 1) {
for (i = 0; i < n; i++) {
// do some stuff
}
if (a == 0) {
break;
return 0;
}
else {
i = 0;
}
}
}
I tried couple more ways to achieve my goal but I couldn't do it. My goal is: I want to open the program, doesn't matter if Caps Lock is on or off, if I hit Caps Lock, it'll start my loop and if I hit it again, it'll stop. I was, somehow, able to make it using lots of "while" loops and threads but it was using almost all my CPU power. How can I create a performance friendly, dynamic loop while using keyboard inputs?
Thank you.
My goal is: I want to open the program, doesn't matter if Caps Lock is
on or off, if I hit Caps Lock, it'll start my loop and if I hit it
again, it'll stop.
You can check the following code to see if it works.
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) // do not process message
return CallNextHookEx(NULL, nCode,
wParam, lParam);
if (wParam == VK_CAPITAL) {
if(hThread == NULL)
hThread = CreateThread( NULL, 0, myLoop, NULL, 0, NULL);
if (capslockState)
capslockState = 0;
else
capslockState = 1;
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
DWORD WINAPI myLoop(LPVOID lpParam)
{
while (1) {
for (UINT16 i = 0; (i < n && capslockState == 1); i++) {
// do some stuff
}
Sleep(100);
}
return 0;
}
What I made main edits on your code:
To make main thread can response to messages and keep your for loop, you need create a new thread(CreateThread) for running your for loop.
Since you "doesn't matter if Caps Lock is on or off" so no need check if the capslock is on or off state.
To check the which key is hit use wParam to compare with virtual-key code.
Problems have pointed by others.
More reference "Using Hooks"
I have posted here entier code cuz myb I made bad struct or put some functions on wrong place . But It doesnt make sens for me why I am getting Error on LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) ,and it doesnt make sens to put ; after it. If someone have time to check code and give me advice how to fix this or realize this on easier way ,I will be very thankful.
error
int main()
{
int togler;
int g;
HHOOK MouseHook;
HHOOK hhkLowLevelKybd;
bool SupressMouseHook = false;
bool click = false;
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL eatMouseStroke2 = false;
if (!SupressMouseHook) {
BOOL eatMouseStroke = false;
if (togler == 1) {
if (wParam == WM_LBUTTONDOWN) {
click = true;
}
else if (wParam == WM_LBUTTONUP) {
click = false;
}
}
return(eatMouseStroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
else {
BOOL eatMouseStroke = false;
return(eatMouseStroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
return(eatMouseStroke2 ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, GetModuleHandle(NULL), 0);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)clicker, NULL, NULL, NULL);
}
You should move MouseHookProc definition outside of main. C++ does not allow function definitions inside of other functions.
Among other things, (LPTHREAD_START_ROUTINE)clicker is also wrong, there is no need to perform cast here, instead clicker function must have correct signature, void down(); is actually a function declaration, not invocation.
I can't seem to find what I am looking for which is a way to alter the OS's mouse clicks. To specify this would be on Windows.
The goal is to limit the number of mouse clicks a user can register within a period of time.
I think the function that you are looking for is SetWindowsHookEx. Here is a quick example.
#include <windows.h>
const DWORD desireddelay = 10;
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static DWORD previoustimestamp = 0;
if ((nCode == 0) && (wParam == WM_RBUTTONDOWN))
{
if ((((MSLLHOOKSTRUCT*)lParam)->time - previoustimestamp) < desireddelay)
{
return 1; //Non-Zero Swallows the keystroke. 0 Allows it. Always CallNextHookEx if you are not swallowing it.
}
else
{
previoustimestamp = ((MSLLHOOKSTRUCT*)lParam)->time;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main()
{
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), NULL);
MSG msg;
bool done = false;
while (GetMessage(&msg, NULL, NULL, NULL)) {}
UnhookWindowsHookEx(hook);
return 0;
}
I created a DLL to hook some events using a CBT hook. It seems to work only for the windows created by the process launching the hook...
My system is Windows 7 x64, but the behaviour is the same also on the x32.
This is the code (sorry but I'm no C++ expert):
#include "windows.h"
extern "C"
{
static LRESULT CALLBACK CbtProcCb(int nCode, WPARAM wParam, LPARAM lParam);
HINSTANCE g_hDll = NULL;
HWND g_hNotifyWin = NULL;
DWORD g_uNotifyMsg = NULL;
HHOOK g_hHook = NULL;
__declspec(dllexport) HHOOK SetCbtHook(HWND hWnd, LPCWSTR lStrMsg, DWORD threadId)
{
g_hNotifyWin = hWnd;
g_uNotifyMsg = RegisterWindowMessage(lStrMsg);
g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CbtProcCb, g_hDll, threadId);
return g_hHook;
}
__declspec(dllexport) int UnsetCbtHook()
{
if ( !g_hHook )
return 0;
return UnhookWindowsHookEx(g_hHook);
}
}
static LRESULT CALLBACK CbtProcCb(int nCode, WPARAM wParam, LPARAM lParam)
{
SendNotifyMessage(g_hNotifyWin, g_uNotifyMsg, nCode, wParam); // Send nCode to check the received event
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if ( fdwReason == DLL_PROCESS_ATTACH )
g_hDll = hinstDLL;
return true;
}
Any hints?
When Windows installs globals hook, the DLL implementing the hook function is often loaded in other processes. In those processes, the g_hNotifyWin and g_uNotifyMsg global variables are NULL. That global variables are only not NULL in the context of the process in which the SetCbtHook call took place.
You must have a way to retrieve the correct value for g_hNotifyWin and 'g_uNotifyMsg', in an arbitrary process.
Add:
const char * g_pszClassName = "MyClassName";
const char * g_pszRegisteredMsg = "MyMessage";
to your DLL, and replace "MyClassName" by the class name of the g_hNotifyWin window. See the RegisterClass call in your EXE. Update also "MyMessage".
Then, use the following CbtProcCb function:
static LRESULT CALLBACK CbtProcCb(int nCode, WPARAM wParam, LPARAM lParam)
{
if ( nCode >= 0 ) {
if ( g_hNotifyWin == NULL ) g_hNotifyWin = FindWindow( g_pszClassName, NULL );
if ( g_uNotifyMsg == 0) g_uNotifyMsg = RegisterWindowMessage(g_pszRegisteredMsg);
if ( g_hNotifyWin && g_uNotifyMsg )
SendNotifyMessage(g_hNotifyWin, g_uNotifyMsg, nCode, wParam); // Send nCode to check the received event
}
return CallNextHookEx(NULL, nCode, wParam, lParam); // first arg useless see MSDN
}
EDIT:
As you noted in comment, same problem for g_uNotifyMsg See updated function. You could set up those variables in DllMain, indeed.
The first argument to CallNextHookEx may be NULL.
I guess your ThreadId is not zero, so hook is attached only to the calling process / thread respectively. Read documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx