WinAPI: repeatable check in a separate thread that notifies UI thread when check fails - c++

My application has a separate thread that repeatably performs some check. If the check fails, the UI thread is notified (a MessageBox is displayed that requires user action what to do next).
Unfortunately, I have to use C++03 compiler (Visual Studio 2010 SP1) and boost library usage is prohibited. Therefore, I cannot use <thread>, <atomic>, <chrono>, etc. Thats why I have to use CreateThread, PostMessage and other WinAPI functions.
Here is my UI thread code (simplified). My main window is CMDIFrameWnd (from MFC):
//a struct with all parameters that is needed for a repeatable check
struct RepeatFunctionParameters
{
unsigned int repeatDelayInMilliseconds;
HWND checkIsFailedPostMessageWindowHandler;
UINT checkIsFailedPostMessageMessageId;
HANDLE checkIsPausedMutexHandle;
RepeatFunctionParameters(unsigned int _repeatDelayInMilliseconds, HWND _checkIsFailedPostMessageWindowHandler,
UINT _checkIsFailedPostMessageMessageId, HANDLE _haspSerialCheckIsPausedMutexHandle)
: repeatDelayInMilliseconds(_repeatDelayInMilliseconds), checkIsFailedPostMessageWindowHandler(_checkIsFailedPostMessageWindowHandler),
checkIsFailedPostMessageMessageId(_checkIsFailedPostMessageMessageId), haspSerialCheckIsPausedMutexHandle(_haspSerialCheckIsPausedMutexHandle)
{}
};
----------------------------
//creating a mutex to pause repeatable checks (whe Messagebox is displayed in UI thread)
HANDLE haspSerialCheckIsPausedMutexHandle = CreateMutex(NULL, FALSE, NULL);
//starting a separate thread with a check that repeats every 5000 milliseconds
auto params = new RepeatFunctionParameters(5000, myApp_hWnd, WM_USER_HASP_CHECK_FAILED, haspSerialCheckIsPausedMutexHandle);
CreateThread(NULL, 0, RepeatFunction, params, 0, NULL);
----------------------------
//special message that is sended when check is failed
#define WM_USER_HASP_CHECK_FAILED (WM_USER+0x150)
//mapping message handling function to that message
ON_MESSAGE( WM_USER_HASP_CHECK_FAILED, OnUserHaspCheckFailed)
//message handling function definition
afx_msg LRESULT OnUserHaspCheckFailed(WPARAM wParam, LPARAM lParam);
//message handling function body
LRESULT CMainWnd::OnUserHaspCheckFailed(WPARAM wParam, LPARAM lParam)
{
//capturing a mutex that signals to pause repeatable checks
WaitForSingleObject(haspSerialCheckIsPausedMutexHandle, INFINITE);
//show a messagebox that requires user action what to do next
if (::MessageBox(myApp_hWnd, ("Check is failed! Retry or cancel?").c_str(),
myApp_name, MB_RETRYCANCEL | MB_ICONERROR | MB_SYSTEMMODAL) == IDCANCEL)
//closing main windows if user clicks Cancel
pWnd->SendMessage(WM_CLOSE, 0x00010000, 0);
//releasing a mutex that signals to pause repeatable checks
ReleaseMutex(haspSerialCheckIsPausedMutexHandle);
return 0;
}
//WM_CLOSE handling function body
LRESULT CMainWnd::OnClose( WPARAM wParam, LPARAM lParam)
{
----------------------------
if( haspSerialCheckIsPausedMutexHandle != NULL)
CloseHandle( haspSerialCheckIsPausedMutexHandle);
----------------------------
CMDIFrameWnd::OnClose();
return NULL;
}
Here is my separate thread with repeatable check code (simplified):
DWORD WINAPI RepeatFunction(LPVOID parameters)
{
//getting parameters struct from a pointer
auto temp = static_cast<RepeatFunctionParameters*>(parameters);
//make a struct local copy (Further, all work goes only with it, regardless of the
state of the object, the pointer to which came as a function parameter)
auto params = *temp;
//deleting the structure, the pointer to which came as a function parameter
delete temp;
//repeatable check
while (true)
{
//checking a mutex that signals to pause repeatable checks. if it is free
//then there is no messagebox in UI thread and we can perform a check.
//if it is captured - wait until user clicks some button in that messagebox
WaitForSingleObject(params.haspSerialCheckIsPausedMutexHandle, INFINITE);
//and releasing it immediately
ReleaseMutex(params.haspSerialCheckIsPausedMutexHandle);
auto startMilliseconds = GetTickCount();
//performing a check
BOOL success = PerformACheck();
unsigned long defaultSleepDelay = 1000;
//if PerformACheck() will last longer than params.repeatDelayInMilliseconds,
//then check will be repeated after 1000 milliseconds, otherwise -
//after params.repeatDelayInMilliseconds minus PerformACheck() call time
auto endMilliseconds = GetTickCount();
if ((endMilliseconds - startMilliseconds) < params.repeatDelayInMilliseconds)
sleepDelay = params.repeatDelayInMilliseconds - (endMilliseconds - startMilliseconds);
//if check is failed
if (!success)
{
//sending a message with an identifier params.checkIsFailedPostMessageMessageId
//to a HWND params.checkIsFailedPostMessageWindowHandler so in it's
//handling function a messagebox with will be displayed and a mutex
//params.haspSerialCheckCanRunMutexHandle will be captured until
//user click some button in that messagebox
PostMessage(params.checkIsFailedPostMessageWindowHandler, params.checkIsFailedPostMessageMessageId, 0, 0);
//if check is failed then next check always repeats after 1000 milliseconds
sleepDelay = 1000;
}
Sleep(sleepDelay);
}
}
The result is that the main window becomes unresponsive after some time. It looks like my code has some logical mistake, or a memory leak.
I'm a newbie to C++ (and especially to outdated standards).

Related

Cannot exit message loop from thread using Windows API and C++

I'm trying to implement the following scenario:
Requirement
Write a C++ program to capture all the keyboard inputs on Windows OS. The program should start capturing keystrokes and after about 3 seconds (the specific amount time is not very relevant, it could be 4/5/etc.), the program should stop capturing keystrokes and continue its execution.
Before I proceed with the actual implementation details, I want to clarify that I preferred tο write the requirements in a form of exercise, rather than providing a long description. I'm not trying to gather solutions for homework. (I'm actually very supportive to such questions when its done properly, but this is not the case here).
My solution
After working on different implementations the past few days, the following is the most complete one yet:
#include <iostream>
#include <chrono>
#include <windows.h>
#include <thread>
// Event, used to signal our thread to stop executing.
HANDLE ghStopEvent;
HHOOK keyboardHook;
DWORD StaticThreadStart(void *)
{
// Install low-level keyboard hook
keyboardHook = SetWindowsHookEx(
// monitor for keyboard input events about to be posted in a thread input queue.
WH_KEYBOARD_LL,
// Callback function.
[](int nCode, WPARAM wparam, LPARAM lparam) -> LRESULT {
KBDLLHOOKSTRUCT *kbs = (KBDLLHOOKSTRUCT *)lparam;
if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
{
// -- PRINT 2 --
// print a message every time a key is pressed.
std::cout << "key was pressed " << std::endl;
}
else if (wparam == WM_DESTROY)
{
// return from message queue???
PostQuitMessage(0);
}
// Passes the keystrokes
// hook information to the next hook procedure in the current hook chain.
// That way we do not consume the input and prevent other threads from accessing it.
return CallNextHookEx(keyboardHook, nCode, wparam, lparam);
},
// install as global hook
GetModuleHandle(NULL), 0);
MSG msg;
// While thread was not signaled to temirnate...
while (WaitForSingleObject(ghStopEvent, 1) == WAIT_TIMEOUT)
{
// Retrieve the current messaged from message queue.
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Before exit the thread, remove the installed hook.
UnhookWindowsHookEx(keyboardHook);
// -- PRINT 3 --
std::cout << "thread is about to exit" << std::endl;
return 0;
}
int main(void)
{
// Create a signal event, used to terminate the thread responsible
// for captuting keyboard inputs.
ghStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD ThreadID;
HANDLE hThreadArray[1];
// -- PRINT 1 --
std::cout << "start capturing keystrokes" << std::endl;
// Create a thread to capture keystrokes.
hThreadArray[0] = CreateThread(
NULL, // default security attributes
0, // use default stack size
StaticThreadStart, // thread function name
NULL, // argument to thread function
0, // use default creation flags
&ThreadID); // returns the thread identifier
// Stop main thread for 3 seconds.
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
// -- PRINT 4 --
std::cout << "signal thread to terminate gracefully" << std::endl;
// Stop gathering keystrokes after 3 seconds.
SetEvent(ghStopEvent);
// -- PRINT 5 --
std::cout << "from this point onwards, we should not capture any keystrokes" << std::endl;
// Waits until one or all of the specified objects are
// in the signaled state or the time-out interval elapses.
WaitForMultipleObjects(1, hThreadArray, TRUE, INFINITE);
// Closes the open objects handle.
CloseHandle(hThreadArray[0]);
CloseHandle(ghStopEvent);
// ---
// DO OTHER CALCULATIONS
// ---
// -- PRINT 6 --
std::cout << "exit main thread" << std::endl;
return 0;
}
Implementation details
The main requirement is the capturing of keystrokes for a certain amount of time. After that time, we should NOT exit the main program. What I thought would be suitable in this case, is to create a separate thread that will be responsible for the capturing procedure and using a event to signal the thread. I've used windows threads, rather than c++0x threads, to be more close to the target platform.
The main function starts by creating the event, followed by the creation of the thread responsible for capturing keystrokes. To fulfill the requirement of time, the laziest implementation I could think of was to stop the main thread for a certain amount of time and then signaling the secondary one to exit. After that we clean up the handlers and continue with any desired calculations.
In the secondary thread, we start by creating a low-level global keyboard hook. The callback is a lambda function, which is responsible for capturing the actual keystrokes. We also want to call CallNextHookEx so that we can promote the message to the next hook on the chain and do not disrupt any other program from running correctly. After the initialization of the hook, we consume any global message using the GetMessage function provided by the Windows API. This repeats until our signal is emitted to stop the thread. Before exiting the thread, we unhook the callback.
We also output certain debug messages throughout the execution of the program.
Expected behavior
Running the above code, should output similar messages like the ones bellow:
start capturing keystrokes
key was pressed
key was pressed
key was pressed
key was pressed
signal thread to terminate gracefully
thread is about to exit
from this point onwards, we should not capture any keystrokes
exit main thread
Your output might differ depending on the number of keystrokes that were captured.
Actual behavior
This is the output I'm getting:
start capturing keystrokes
key was pressed
key was pressed
key was pressed
key was pressed
signal thread to terminate gracefully
from this point onwards, we should not capture any keystrokes
key was pressed
key was pressed
key was pressed
A first glance into the output reveals that:
The unhook function was not called
The program keeps capturing keystrokes, which might indicate that something is wrong with the way I process the message queue
There is something wrong regarding the way I'm reading the messages from the message queue, but after hours of different approaches, I could not find any solution for the specific implementation. It might also be something wrong with the way I'm handling the terminate signal.
Notes
The closer I could get on finding an answer, here in SO, was this question. However the solution did not helped me as much as I wanted.
The provided implementation is a minimum reproducible example and can be compiled without the need to import any external libraries.
A proposed solution will be to implement the capturing-keystrokes functionality as a separate child process, where will be able to start and stop whenever we like. However, I'm more interested in finding a solution using threads. I'm not sure if this is even possible (it might be).
The above code does not contain any error handling. This was on purpose to prevent possible over bloated of the code.
For any questions you might have, feel free to comment! Thank you in advance for your time to read this question and possibly post an answer (it will be amazing!).
I think this is your problem:
while (WaitForSingleObject(ghStopEvent, 1) == WAIT_TIMEOUT)
{
// Retrieve the current messaged from message queue.
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The reason is that currently your loop can get stuck on the GetMessage() step forever and never again look at the manual-reset event.
The fix is simply to replace the combination of WaitForSingleObject + GetMessage with MsgWaitForMultipleObjects + PeekMessage.
The reason you've made this mistake is that you didn't know GetMessage only returns posted messages to the message loop. If it finds a sent message, it calls the handler from inside GetMessage, and continues looking for posted message. Since you haven't created any windows that can receive messages, and you aren't calling PostThreadMessage1, GetMessage never returns.
while (MsgWaitForMultipleObjects(1, &ghStopEvent, FALSE, INFINITE, QS_ALLINPUT) > WAIT_OBJECT_0) {
// check if there's a posted message
// sent messages will be processed internally by PeekMessage and return false
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
1 You've got logic to post WM_QUIT but it is conditioned on receiving WM_DESTROY in a low-level keyboard hook, and WM_DESTROY is not a keyboard message. Some hook types could see a WM_DESTROY but WH_KEYBOARD_LL can't.
What I thought would be suitable in this case, is to create a separate
thread that will be responsible for the capturing procedure
it's not necessary to do this if another thread will just wait for this thread and nothing to do all this time
you can use code like this.
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if (HC_ACTION == code)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
DbgPrint("%x %x %x %x\n", wParam, p->scanCode, p->vkCode, p->flags);
}
return CallNextHookEx(0, code, wParam, lParam);
}
void DoCapture(DWORD dwMilliseconds)
{
if (HHOOK hhk = SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0))
{
ULONG time, endTime = GetTickCount() + dwMilliseconds;
while ((time = GetTickCount()) < endTime)
{
MSG msg;
switch (MsgWaitForMultipleObjectsEx(0, 0, endTime - time, QS_ALLINPUT, MWMO_INPUTAVAILABLE))
{
case WAIT_OBJECT_0:
while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
break;
case WAIT_FAILED:
__debugbreak();
goto __0;
break;
case WAIT_TIMEOUT:
DbgPrint("WAIT_TIMEOUT\n");
goto __0;
break;
}
}
__0:
UnhookWindowsHookEx(hhk);
}
}
also in real code - usual not need write separate DoCapture with separate message loop. if your program before and after this anyway run message loop - posiible all this do in common message loop,

C Windows API determine if user inactive for certain period

So I've created a basic program with a blocking message event loop (to use little to no CPU while waiting) and waits for a user to change the foreground window, then executes some code:
#include <Windows.h>
VOID ExitFunction()
{
// Do Something
}
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
switch (dwCtrlType)
{
case CTRL_SHUTDOWN_EVENT:
ExitFunction();
return TRUE;
case CTRL_LOGOFF_EVENT:
ExitFunction();
return TRUE;
//default:
//We don't care about this event
//Default handler is used
}
return FALSE;
}
VOID CALLBACK WinEventProcCallback(HWINEVENTHOOK hWinEventHook, DWORD dwEvent, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
if (dwEvent == EVENT_SYSTEM_FOREGROUND)
{
// Do Stuff
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWINEVENTHOOK WindowChangeEvent;
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
WindowChangeEvent = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, WinEventProcCallback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
while (GetMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ExitFunction();
return 0;
}
I also want to incorporate checking if the user has been inactive for a certain amount of time (no mouse/keyboard input) but keep resource usage low. There are a couple of ways to approach this that I can think of:
Have the blocking event loop check if there has been mouse or keyboard input which resets some kind of timer back to zero and also checks within the same loop if the mouse input resulted in a foreground window change (which may cause issues if there is a delay between the mouse click event and the foreground window change (meaning the foreground window change won't be captured). Have an event triggered when the user input timer has completed the specified time.
Run the mouse & keyboard activity event timer on a separate thread or asynchronously to the foreground window change event. When the timer has completed fire off an event (run on separate thread or asynchronously to make sure a foreground window change event isn't missed).
On a separate thread or asynchronously, check every couple seconds the GetLastInputInfo() function to see if the inactivity threshold time has elapsed.
It can be called like so:
LASTINPUTINFO li;
li.cbSize = sizeof(LASTINPUTINFO);
GetLastInputInfo(&li);
Keeping in mind lowest resource usage, what way is best to implement the mouse/keyboard inactivity checking while also checking for foreground window changes.
You can set up a timer (see SetTimer) to have a user-defined callback called when an arbitrary timeout expires. This allows you to break out of the blocking GetMessage loop.
The callback can check the timestamp of the last input, and compare it to the current timestamp. If that time interval exceeds the desired inactivity timeout, it can perform the necessary steps. Otherwise it restarts the timer with the remainder of the timeout.
The following code illustrates this:
#include <Windows.h>
#include <iostream>
static const DWORD timeout_in_ms { 5 * 1000 };
void TimeoutExpired() { std::wcout << L"Timeout elapsed" << std::endl; }
void CALLBACK TimerProc(HWND, UINT, UINT_PTR id, DWORD current_time)
{
// Timers are periodic, but we want it to fire only once.
KillTimer(nullptr, id);
LASTINPUTINFO lii { sizeof(lii) };
GetLastInputInfo(&lii);
auto const time_since_input { current_time - lii.dwTime };
if (time_since_input < timeout_in_ms)
{
// User input was recorded inside the timeout interval -> restart timer.
auto const remaining_time { timeout_in_ms - time_since_input };
SetTimer(nullptr, 0, remaining_time, &TimerProc);
}
else
{
TimeoutExpired();
}
}
void StartInactivityTimer()
{
// Start a timer that expires immediately;
// the TimerProc will do the required adjustments and
// restart the timer if necessary.
SetTimer(nullptr, 0, 0, &TimerProc);
}
int wmain()
{
StartInactivityTimer();
MSG msg {};
while (GetMessageW(&msg, nullptr, 0, 0) > 0)
{
DispatchMessageW(&msg);
}
}
The entire logic is contained within TimerProc. To trigger the inactivity timer, StartInactivityTimer starts a timer that expires immediately. When TimerProc takes control it does the required calculations, and either restarts the timer, or calls the timeout procedure, TimeoutExpired.
This implementation has two advantages: For one, the entire timer restart logic is in a single place. More importantly, the inactivity condition is evaluated on first call. If StartInactivityTimer is called without any user input in the inactivity interval, it instantly executes TimeoutExpired.
Also note that the interval calculations use unsigned integer arithmetic, specifically subtraction. With unsigned integer 'underflow' being well defined in both C and C++, this solution is immune to GetTickCount's return value wrapping around to 0 after approximately 49.7 days.

SendNotifyMessage do not send correct messages

From one thread I send the message to main thread in window procedure.
But it is unsuccessful. When I send messages from the same thread - all is ok
include "stdafx.h"
#include <Windows.h>
#include <atlbase.h>
#define MAX_THREADS 1
HWND m_wnd;
enum
{
EVENT_CALL = (WM_APP + 0x30),
};
static LRESULT CALLBACK function_call()
{
//some code
int test = 0;
return 0;
}
static LRESULT CALLBACK http_message_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case EVENT_CALL:
function_call();
return 0;
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void CreateNotifyWnd()
{
WNDCLASSEX w = { 0 };
w.cbSize = sizeof(w);
w.hInstance = (HINSTANCE)&__ImageBase;
w.lpszClassName = L"uistone_http_event_wnd";
w.lpfnWndProc = http_message_proc;
::RegisterClassEx(&w);
int error = GetLastError();
m_wnd = ::CreateWindowEx(0, w.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, w.hInstance, 0);
error = GetLastError();
}
DWORD WINAPI SendThread(void* request_param)
{
::SendNotifyMessage(m_wnd, EVENT_CALL, 11, 12);
int error = GetLastError();
return 0;
}
int main()
{
CreateNotifyWnd();
HANDLE hThreadArray[MAX_THREADS];
hThreadArray[0] = CreateThread(nullptr, 0, SendThread, nullptr, 0, nullptr);
//::SendNotifyMessage(m_wnd, EVENT_CALL, 11, 12);
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
return 0;
}
Why I can not catch messages from another thread?
Thanks.
This is documented behavior. This is the relevant part from the SendNotifyMessage documentation:
If the window was created by the calling thread, SendNotifyMessage calls the window procedure for the window and does not return until the window procedure has processed the message. If the window was created by a different thread, SendNotifyMessage passes the message to the window procedure and returns immediately; it does not wait for the window procedure to finish processing the message.
This appears to work when used with a window created on the same thread, because when you call SendNotifyMessage, the function synchronously calls into the window procedure associated with the target window before returning.
If the call crosses threads, on the other hand, you'd have to run a message loop for the - now queued - message to get picked up and passed to the window procedure1). Your application doesn't run a message loop, and it exits before the message ever reaches the target window.
To fix this you'd have to run a message loop. This may or may not be the right approach to your problem. Since we don't know, what problem you are trying to solve, we cannot suggest potentially superior approaches and solutions.
1) See About Messages and Message Queues: Message Routing.

SetWindowsHookEx(WH_KEYBOARD) not working with thread ID

I have a dll that gets called by a process and now I would like to implement an input check in the dll to react on certain inputs that occur in the application.
SetWindowsHookEx() with a KeyboardProc function seemed like a possible solution so I implemented it.
This is roughly how the code in the dll looks like:
static HHOOK hhk = NULL;
LRESULT CALLBACK keyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code == HC_ACTION && ((DWORD)lParam & 0x80000000) == 0) // if there is an incoming action and a key was pressed
{
switch(wParam)
{
case VK_SPACE:
printf("Space was pressed\n");
break;
}
}
return CallNextHookEx(hhk, code, wParam, lParam);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if(AllocConsole()){
freopen("CONOUT$", "w", stdout); // redirect output to console for debugging
}
printf("Dll loaded, lastError = %i\n", GetLastError());
printf("lastError = %i\n", GetLastError());
// sidenote: for some reason the first GetLastError() returns 0 while the second one returns 6 (invalid handle)
hhk = SetWindowsHookEx(WH_KEYBOARD, keyboardProc, hModule, GetCurrentThreadId());
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
printf("\nCleaning up...");
FreeConsole();
UnhookWindowsHookEx(hhk);
}
return TRUE;
}
However nothing happens (or gets printed) in the Console window when I press any key. It doesn't even seem like the keyboardProc function is accessed at any time.
It does work though when I pass NULL instead of GetCurrentThreadId() to SetWindowsHookEx().
But this causes the hook to work globally meaning that whenever I press a key in another application, a Console window pops up (because the dll gets called again) and he checks for key inputs there.
Obviously this is not desired and I would like to make this work with only the process that originally called the dll.
I already checked if GetCurrentThreadId() returns a valid ID and it seems to be indeed the main thread ID of the process that initially called the dll (checked with Process Explorer).
So now my question is what could be the problem and more importantly, what can I do to make it working?
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
uint process_id;
uint thread_id = GetWindowThreadProcessId(windowHandle, out process_id);
hhook = SetWindowsHookEx(WH_KEYBOARD, a_KeyboardProc, hInstance, 0);
I have used the code above to get the main thread_ID for a certain process. The good part is, the SetWindowsHookEx function gives a logical output. Unfortunately, the bad part is, if a key is pressed in the thread that has been hooked, the thread stops working.
In specific, the idHook parameter of SetWindowsHoookEx function was set to 2 (instead of 13) in my case for non-low-level keyboard events. It seems, at least to me, that LL corresponds to low-level, where keyboardProc should come with a WH_KEYBOARD instead of WH_KEYBOARD_LL.
I am not sure at this point how my response would be related to your question. Hopefully, we get what we need through discussion.

Properly closing window created on a separate thread using ATL

I have a multithreaded application and on certain threads, I'm creating windows using ATL's CWindowImpl<>. I have a static method that I'm using as the thread procedure. I need to create a window on the thread, because I need some of my communication with the thread to be synchronous, and PostThreadMessage() is expressly asynchronous. When my window receives the WM_DESTROY message (handler defined by the MESSAGE_HANDLER macro), it calls PostQuitMessage(), as shown in this method:
LRESULT MyATLWindowClass::OnDestroy(UINT uMsg,
WPARAM wParam,
LPARAM lParam,
BOOL& bHandled) {
::PostQuitMessage(0);
return 0;
}
I'm using a custom message to the thread using PostThreadMessage() to indicate to the thread that it's time to terminate itself. Handling that custom message, I call the CWindowImpl::DestroyWindow() method, which does appear to properly destroy the window, as my OnDestroy message handler is getting called. However, it doesn't appear that the owning thread ever receives a WM_QUIT message for processing. Included below is a simplified version of my thread procedure.
unsigned int WINAPI MyATLWindowClass::ThreadProc(LPVOID lpParameter) {
// Initialize COM on the thread
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Create the window using ATL
MyATLWindowClass new_window;
HWND session_window_handle = new_window.Create(
/* HWND hWndParent */ HWND_MESSAGE,
/* _U_RECT rect */ CWindow::rcDefault,
/* LPCTSTR szWindowName */ NULL,
/* DWORD dwStyle */ NULL,
/* DWORD dwExStyle */ NULL,
/* _U_MENUorID MenuOrID */ 0U,
/* LPVOID lpCreateParam */ NULL);
// Initialize the message pump on the thread.
MSG msg;
::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Run the message loop
BOOL get_message_return_value;
while ((get_message_return_value = ::GetMessage(&msg, NULL, 0, 0)) != 0) {
if (get_message_return_value == -1) {
// GetMessage handling logic taken from MSDN documentation
break;
} else {
if (msg.message == WD_SIGNAL_THREAD_SHUTDOWN) {
// Requested thread shutdown, so destroy the window
new_window.DestroyWindow();
} else if (msg.message == WM_QUIT) {
// Process the quit message and exit the message loop
// to terminate the thread
break;
} else {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
// Uninitialize COM on the thread before exiting
::CoUninitialize();
return 0;
}
Note that it doesn't seem to matter if I call DestroyWindow() or if I send a WM_CLOSE message to the window. The thread's message pump is not receiving WM_QUIT in either case. Should the owning thread's message pump be receiving such a message? Where is my misunderstanding about how the thread's message pump and the window's message pump interact? Or what am I missing about how ATL's window classes create and manage windows?
GetMessage() never returns WM_QUIT. That message forces it to return 0 instead, designed to terminate your message loop.
Beware of the considerable hazards of using PostThreadMessage(). It should never be used on a thread that also displays windows, like the one you are using. The issue is that it doesn't take a HWND argument. So only your message loop can see the message, it won't be delivered to any window with DispatchMessage(). This goes wrong when a modal message loop is entered, the kind that are outside of your control. Like the modal loop that makes MessageBox work. Or the one that Windows uses to allow the user to resize a window. Or the one that DialogBox() uses. Etcetera. Always use PostMessage(), use your own message number.
Some late additional thoughts. You could probably safely terminate your message loop as soon as you have discovered WD_SIGNAL_THREAD_SHUTDOWN:
if (msg.message == WD_SIGNAL_THREAD_SHUTDOWN) {
// Requested thread shutdown, so destroy the window
new_window.DestroyWindow();
break; // exit the message loop
}
DestroyWindow is a synchronous call, the window will be fully destroyed before it returns and you can exit the loop. So, posting WM_QUIT would be redundant.
Also, you could use message-only window, if the windows is invisible and its only purpose is to process messages.