Windows Ctrl-C working.

This commit is contained in:
Brad Nelson
2023-01-14 17:38:58 -08:00
parent fc6c771d86
commit 3dcd421576
5 changed files with 59 additions and 17 deletions

View File

@ -38,16 +38,18 @@
#define STACK_CELLS (8 * 1024)
static LRESULT WindowProcShim(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static void SetupCtrlBreakHandler(void);
#define PLATFORM_OPCODE_LIST \
Y(GetProcAddress, \
YV(windows, GetProcAddress, \
tos = (cell_t) GetProcAddress((HMODULE) *sp, (LPCSTR) tos); --sp) \
Y(LoadLibraryA, tos = (cell_t) LoadLibraryA((LPCSTR) tos)) \
Y(WindowProcShim, DUP; tos = (cell_t) &WindowProcShim) \
YV(windows, LoadLibraryA, tos = (cell_t) LoadLibraryA((LPCSTR) tos)) \
YV(windows, WindowProcShim, DUP; tos = (cell_t) &WindowProcShim) \
YV(windows, SetupCtrlBreakHandler, SetupCtrlBreakHandler()) \
CALLING_OPCODE_LIST \
FLOATING_POINT_LIST
#define VOCABULARY_LIST V(forth) V(internals)
#define VOCABULARY_LIST V(forth) V(internals) V(windows)
#include "common/bits.h"
#include "common/core.h"
@ -55,6 +57,57 @@ static LRESULT WindowProcShim(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
#include "gen/windows_boot.h"
static DWORD forth_main_thread_id;
static uintptr_t forth_main_thread_resume_sp;
static uintptr_t forth_main_thread_resume_bp;
static BOOL WINAPI forth_ctrl_handler(DWORD fdwCtrlType) {
HANDLE main_thread;
CONTEXT context = { 0 };
if (fdwCtrlType == CTRL_C_EVENT ||
fdwCtrlType == CTRL_BREAK_EVENT) {
// Using explicit instead of THREAD_ALL_ACCESS to be explicit as per docs.
// THREAD_QUERY_INFORMATION seems to be required for reasons unknown on x64.
main_thread = OpenThread(THREAD_QUERY_INFORMATION |
THREAD_SET_CONTEXT |
THREAD_GET_CONTEXT |
THREAD_SUSPEND_RESUME, FALSE, forth_main_thread_id);
SuspendThread(main_thread);
context.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(main_thread, &context);
#ifdef _WIN64
context.Rip = 0;
context.Rsp = forth_main_thread_resume_sp;
context.Rbp = forth_main_thread_resume_bp;
#else
context.Eip = 0;
context.Esp = forth_main_thread_resume_sp;
context.Ebp = forth_main_thread_resume_bp;
#endif
SetThreadContext(main_thread, &context);
ResumeThread(main_thread);
CloseHandle(main_thread);
return TRUE;
}
return FALSE;
}
static void SetupCtrlBreakHandler(void) {
forth_main_thread_id = GetCurrentThreadId();
SetConsoleCtrlHandler(forth_ctrl_handler, TRUE);
CONTEXT context = { 0 };
context.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(GetCurrentThread(), &context);
#ifdef _WIN64
forth_main_thread_resume_sp = context.Rsp;
forth_main_thread_resume_bp = context.Rbp;
#else
forth_main_thread_resume_sp = context.Esp;
forth_main_thread_resume_bp = context.Ebp;
#endif
}
static LRESULT WindowProcShim(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_NCCREATE) {
SetWindowLongPtr(