diff --git a/AppleWinExpress2008.sln b/AppleWinExpress2008.sln index aa8e1d14..0c04ea20 100644 --- a/AppleWinExpress2008.sln +++ b/AppleWinExpress2008.sln @@ -20,6 +20,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml", "libyaml\win32\yaml2 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestDebugger", "test\TestDebugger\TestDebugger.vcproj", "{0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HookFilter", "HookFilter\HookFilter.vcproj", "{AA5854AD-2BC7-4EFD-9790-349ADB35E35A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -50,6 +52,10 @@ Global {0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Debug|Win32.Build.0 = Debug|Win32 {0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Release|Win32.ActiveCfg = Release|Win32 {0AE28CF0-15B0-4DDF-B6D2-4562D8E456BB}.Release|Win32.Build.0 = Release|Win32 + {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Debug|Win32.Build.0 = Debug|Win32 + {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Release|Win32.ActiveCfg = Release|Win32 + {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp new file mode 100644 index 00000000..c7cc3841 --- /dev/null +++ b/HookFilter/HookFilter.cpp @@ -0,0 +1,41 @@ +#include + +// https://stackoverflow.com/questions/2490577/suppress-task-switch-keys-winkey-alt-tab-alt-esc-ctrl-esc-using-low-level-k + +// NB. __stdcall (or WINAPI) and extern "C": +// . symbol is decorated as _@bytes +// . so use the #pragma to create an undecorated alias for our symbol +extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam +) +{ + #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__) + + if (nCode >= 0) + { + bool suppress = false; + + PKBDLLHOOKSTRUCT pKbdLlHookStruct = (PKBDLLHOOKSTRUCT) lParam; + + // Suppress alt-tab. + if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + suppress = true; + + // Suppress alt-escape. + if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN)) + suppress = true; + + // Suppress ctrl-escape. + bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0; + if (pKbdLlHookStruct->vkCode == VK_ESCAPE && ControlDown) + suppress = true; + + // Suppress keys by returning 1. + if (suppress) + return 1; + } + + return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam); +} diff --git a/HookFilter/HookFilter.vcproj b/HookFilter/HookFilter.vcproj new file mode 100644 index 00000000..df4e8951 --- /dev/null +++ b/HookFilter/HookFilter.vcproj @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/help/card-ssc.html b/help/card-ssc.html index 4c6ee7a8..c2c4471b 100644 --- a/help/card-ssc.html +++ b/help/card-ssc.html @@ -37,7 +37,7 @@
  • For the TCP mode it doesn't matter what baud rate, stop-bit, byte size and parity are set to.
    • It always uses an unthrottled data-rate of 8-bit bytes (no stop-bit, no parity). -
    • When there's an active TCP connection, then the 6551's Status register has DCD,DSR bits clear (active low), and DIPSW2 has CTS bit clear (active low). When there's no TCP connection, then all these bits are set (inactive). +
    • When there's an active TCP connection, then the 6551's Status register has DCD,DSR bits clear (active low), and DIPSW2 has CTS bit clear (active low). When there's no TCP connection, then all these bits are set (inactive).
  • The TCP mode can expose buggy Rx interrupt handling code where the 6551's Status register is read more than once in the Interrupt Service Routine (ISR).
      @@ -58,7 +58,7 @@
    • 6551 ACIA Status register's error bits: overrun, framing and parity (these are all hardcoded to 0).
    • 6551 ACIA Status register's DCD bit (Data Carrier Detect). This is just set the same as DSR.
        -
      • NB. Use command line -dcd to force AppleWin to use the state of the MS_RLSD_ON bit from GetCommModemStatus(). +
      • NB. For COM mode, use command line -dcd to force AppleWin to use the state of the MS_RLSD_ON bit from GetCommModemStatus().
    • NMOS 6551 ACIA CTS bug: transmission of an already-started frame will stop immediately when CTS is taken false, the byte will be lost, and the TxD line will go to marking.
        diff --git a/source/Applewin.cpp b/source/Applewin.cpp index 7505d533..f54adca0 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -1012,6 +1012,40 @@ static void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBo //--------------------------------------------------------------------------- +static HINSTANCE g_hinstDLL = 0; +static HHOOK g_hhook = 0; + +void HookFilterForKeyboard() +{ + g_hinstDLL = LoadLibrary(TEXT("AppleWinHookFilter.dll")); + HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc"); + + g_hhook = SetWindowsHookEx( + WH_KEYBOARD_LL, + hkprcLowLevelKeyboardProc, + g_hinstDLL, + 0); + + if (g_hhook == NULL) + { + std::string msg("Failed to install hook filter for system keys"); + + DWORD dwErr = GetLastError(); + MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK); // NB. g_hFrameWindow is not yet valid + + msg += "\n"; + LogFileOutput(msg.c_str()); + } +} + +void UnhookFilterForKeyboard() +{ + UnhookWindowsHookEx(g_hhook); + FreeLibrary(g_hinstDLL); +} + +//--------------------------------------------------------------------------- + int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) { bool bShutdown = false; @@ -1310,6 +1344,8 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) DiskInitialize(); LogFileOutput("Init: DiskInitialize()\n"); + HookFilterForKeyboard(); + // do @@ -1475,6 +1511,8 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) } while (g_bRestart); + UnhookFilterForKeyboard(); + if (bChangedDisplayResolution) ChangeDisplaySettings(NULL, 0); // restore default