Всегда думал, что ББ работает в одном потоке Windows. Однако это не так
Обработка клавиатуры сделана в отдельном потоке.
Код:
(* -------------------- keyboard interrupt handling --------------------- *)
PROCEDURE KeyboardWatcher (main: INTEGER): INTEGER; (* runs in a thread *)
TYPE P = PROCEDURE(w: INTEGER): INTEGER;
VAR res, a: INTEGER; top, h: WinApi.HANDLE; done: BOOLEAN;
context: WinApi.CONTEXT; mod: Module; isHungAppWindow: P;
BEGIN
done := FALSE;
isHungAppWindow := NIL;
h := WinApi.LoadLibraryA("user32.dll");
IF h # 0 THEN
isHungAppWindow := S.VAL(P, WinApi.GetProcAddress(h, "IsHungAppWindow"))
END;
LOOP
res := WinApi.GetAsyncKeyState(WinApi.VK_CANCEL);
IF res >= 0 THEN (* key released *)
done := FALSE;
WinApi.Sleep(10);
ELSIF ~done THEN (* key pressed *)
top := WinApi.GetForegroundWindow();
IF (mainWnd # top) & (isHungAppWindow # NIL)
& (top # 0) & (isHungAppWindow(top) # 0)
& (mainWnd # 0) & (isHungAppWindow(mainWnd) # 0) THEN
(* main window replaced by ghost window *)
(* check if application window is topmost nonresponding window *)
REPEAT
top := WinApi.GetWindow(top, WinApi.GW_HWNDNEXT)
UNTIL (top = 0) OR (isHungAppWindow(top) # 0) & (WinApi.IsWindowVisible(top) # 0)
END;
IF mainWnd = top THEN
res := WinApi.SuspendThread(main);
context.ContextFlags := {0, 16};
res := WinApi.GetThreadContext(main, context);
mod := modList; a := context.Eip;
WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO
mod := mod.next
END;
IF (mod # NIL) & (mod.name = "Kernel") THEN mod := NIL END;
IF mod # NIL THEN
interrupted := TRUE;
INCL(S.VAL(SET, context.EFlags), 8); (* set trap flag *)
res := WinApi.SetThreadContext(main, context);
done := TRUE
END;
res := WinApi.ResumeThread(main);
WinApi.Sleep(1);
interrupted := FALSE
END
END
END;
RETURN 0
END KeyboardWatcher;
PROCEDURE InstallKeyboardInt;
VAR res, id: INTEGER; t, main: WinApi.HANDLE;
BEGIN
res := WinApi.DuplicateHandle(WinApi.GetCurrentProcess(), WinApi.GetCurrentThread(),
WinApi.GetCurrentProcess(), main, {1, 3, 4, 16..19}, 0, {});
t := WinApi.CreateThread(NIL, 4096, KeyboardWatcher, main, {}, id);
END InstallKeyboardInt;