diff --git a/common/forth_namespace_tests.fs b/common/forth_namespace_tests.fs index dbc4f27..8f249cd 100644 --- a/common/forth_namespace_tests.fs +++ b/common/forth_namespace_tests.fs @@ -553,9 +553,6 @@ e: test-windows-forth-namespace out: ms out: windows check-phase1 - out: GetProcAddress - out: LoadLibraryA - out: WindowProcShim check-opcodes out: forth-builtins ;e diff --git a/windows/interp.h b/windows/interp.h index 9abc6f4..2566098 100644 --- a/windows/interp.h +++ b/windows/interp.h @@ -25,15 +25,6 @@ enum { #undef Z }; -static BOOL WINAPI forth_ctrl_handler(DWORD fdwCtrlType) { - if (fdwCtrlType == CTRL_C_EVENT || - fdwCtrlType == CTRL_BREAK_EVENT) { -// RaiseException(EXCEPTION_BREAKPOINT, 0, 0, 0); - return TRUE; - } - return FALSE; -} - static cell_t *forth_run(cell_t *init_rp) { static const BUILTIN_WORD builtins[] = { #define Z(flags, name, op, code) \ @@ -54,7 +45,6 @@ static cell_t *forth_run(cell_t *init_rp) { } register cell_t *ip, *rp, *sp, tos, w; register float *fp, ft; - SetConsoleCtrlHandler(forth_ctrl_handler, TRUE); rp = init_rp; UNPARK; for (;;) { __try { diff --git a/windows/main.c b/windows/main.c index 1fd6eed..f65fdad 100644 --- a/windows/main.c +++ b/windows/main.c @@ -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( diff --git a/windows/windows_console.fs b/windows/windows_console.fs index 99be5b9..1431a4e 100644 --- a/windows/windows_console.fs +++ b/windows/windows_console.fs @@ -58,6 +58,7 @@ variable console-mode ENABLE_WINDOW_INPUT or invert and SetConsoleMode drop stdout console-mode GetConsoleMode drop stdout console-mode @ ENABLE_VIRTUAL_TERMINAL_PROCESSING or SetConsoleMode drop + SetupCtrlBreakHandler ; : win-type ( a n -- ) init-console stdout -rot NULL NULL WriteFile drop ; diff --git a/windows/windows_core.fs b/windows/windows_core.fs index 4361fa8..43dfc91 100644 --- a/windows/windows_core.fs +++ b/windows/windows_core.fs @@ -21,6 +21,7 @@ internals ' call5 , ' call6 , ' call7 , ' call8 , ' call9 , ' call10 , ' call11 , ' call12 , ' call13 , ' call14 , ' call15 , windows +transfer windows-builtins : sofunc ( z n a "name" -- ) >r dup 15 > throw r> ( Check there aren't too many args ) swap >r swap GetProcAddress dup 0= throw create , r> cells calls + @ ,