mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-03-28 12:54:59 -05:00
Boils down to: - Include headers - Reduce boiler plate with helpers - Swap out explicit usages with core API layer and ensure the right API is configured beforehand
121 lines
2.6 KiB
C
121 lines
2.6 KiB
C
#define LOG_MODULE "msg-thread"
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include "core/log.h"
|
|
#include "core/thread.h"
|
|
|
|
#include "util/msg-thread.h"
|
|
|
|
static bool msg_thread_step(HWND hwnd);
|
|
|
|
static const char msg_wndclass_name[] = "msg-thread";
|
|
|
|
static int msg_thread_id;
|
|
static HANDLE msg_thread_ready;
|
|
static HANDLE msg_thread_stop;
|
|
static HWND msg_window;
|
|
|
|
static int msg_thread_proc(void *param)
|
|
{
|
|
HWND hwnd;
|
|
HINSTANCE inst;
|
|
MSG msg;
|
|
WNDCLASSEX wcx;
|
|
|
|
inst = param;
|
|
|
|
memset(&wcx, 0, sizeof(wcx));
|
|
|
|
wcx.cbSize = sizeof(wcx);
|
|
wcx.lpfnWndProc = msg_window_proc; /* callback */
|
|
wcx.hInstance = inst;
|
|
wcx.lpszClassName = msg_wndclass_name;
|
|
|
|
RegisterClassEx(&wcx);
|
|
|
|
/* Message-only windows (children of HWND_MESSAGE) do not receive
|
|
broadcast events.
|
|
|
|
Because THAT totally makes sense. */
|
|
|
|
hwnd = CreateWindowEx(
|
|
0, msg_wndclass_name, NULL, 0, 0, 0, 0, 0, NULL, NULL, inst, NULL);
|
|
|
|
msg_window_setup(hwnd); /* callback */
|
|
|
|
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
|
|
SetEvent(msg_thread_ready);
|
|
|
|
while (msg_thread_step(hwnd))
|
|
;
|
|
|
|
msg_window_teardown(hwnd); /* callback */
|
|
|
|
DestroyWindow(hwnd);
|
|
UnregisterClass(msg_wndclass_name, inst);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool msg_thread_step(HWND hwnd)
|
|
{
|
|
MSG msg;
|
|
DWORD result;
|
|
|
|
result = MsgWaitForMultipleObjectsEx(
|
|
1, &msg_thread_stop, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
|
|
|
|
switch (result) {
|
|
case WAIT_OBJECT_0:
|
|
return false;
|
|
|
|
case WAIT_OBJECT_0 + 1:
|
|
while (PeekMessage(&msg, msg_window, 0, 0, PM_REMOVE)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return true;
|
|
|
|
case WAIT_IO_COMPLETION:
|
|
return true;
|
|
|
|
case WAIT_FAILED:
|
|
log_warning(
|
|
"MsgWaitForMultipleObjectsEx failed: %08x",
|
|
(unsigned int) GetLastError());
|
|
|
|
return false;
|
|
|
|
default:
|
|
log_warning(
|
|
"Spurious wakeup: result = %08x", (unsigned int) result);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void msg_thread_init(HINSTANCE inst)
|
|
{
|
|
msg_thread_ready = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
msg_thread_stop = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
msg_thread_id = core_thread_create(msg_thread_proc, inst, 0x4000, 0);
|
|
|
|
WaitForSingleObject(msg_thread_ready, INFINITE);
|
|
CloseHandle(msg_thread_ready);
|
|
}
|
|
|
|
void msg_thread_fini(void)
|
|
{
|
|
SetEvent(msg_thread_stop);
|
|
|
|
core_thread_join(msg_thread_id, NULL);
|
|
core_thread_destroy(msg_thread_id);
|
|
|
|
CloseHandle(msg_thread_stop);
|
|
}
|