diff --git a/AppleWinExpress2019.sln b/AppleWinExpress2019.sln
index 31f25485..dc75082e 100644
--- a/AppleWinExpress2019.sln
+++ b/AppleWinExpress2019.sln
@@ -5,7 +5,6 @@ VisualStudioVersion = 16.0.29201.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppleWin", "AppleWinExpress2019.vcxproj", "{0A960136-A00A-4D4B-805F-664D9950D2CA}"
ProjectSection(ProjectDependencies) = postProject
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A} = {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}
{CF5A49BF-62A5-41BB-B10C-F34D556A7A45} = {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}
{0212E0DF-06DA-4080-BD1D-F3B01599F70F} = {0212E0DF-06DA-4080-BD1D-F3B01599F70F}
{509739E7-0AF3-4C09-A1A9-F0B1BC31B39D} = {509739E7-0AF3-4C09-A1A9-F0B1BC31B39D}
@@ -20,8 +19,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml", "libyaml\win32\yaml2
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCPU6502", "test\TestCPU6502\TestCPU6502-vs2019.vcxproj", "{CF5A49BF-62A5-41BB-B10C-F34D556A7A45}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HookFilter", "HookFilter\HookFilter-vs2019.vcxproj", "{AA5854AD-2BC7-4EFD-9790-349ADB35E35A}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug NoDX|Win32 = Debug NoDX|Win32
@@ -92,18 +89,6 @@ Global
{CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release v141_xp|Win32.Build.0 = Release v141_xp|Win32
{CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release|Win32.ActiveCfg = Release|Win32
{CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release|Win32.Build.0 = Release|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Debug NoDX|Win32.ActiveCfg = Debug|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Debug NoDX|Win32.Build.0 = Debug|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Debug v141_xp|Win32.ActiveCfg = Debug v141_xp|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Debug v141_xp|Win32.Build.0 = Debug v141_xp|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 NoDX|Win32.ActiveCfg = Release|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Release NoDX|Win32.Build.0 = Release|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Release v141_xp|Win32.ActiveCfg = Release v141_xp|Win32
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}.Release v141_xp|Win32.Build.0 = Release v141_xp|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/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj
index c066e8a2..e99f20a7 100644
--- a/AppleWinExpress2019.vcxproj
+++ b/AppleWinExpress2019.vcxproj
@@ -123,6 +123,7 @@
+
@@ -245,6 +246,7 @@
+
diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters
index dafa7493..5b45ee53 100644
--- a/AppleWinExpress2019.vcxproj.filters
+++ b/AppleWinExpress2019.vcxproj.filters
@@ -229,6 +229,9 @@
Source Files\Debugger
+
+ Source Files\Windows
+
@@ -540,6 +543,9 @@
Source Files\Debugger
+
+ Source Files\Windows
+
diff --git a/HookFilter/HookFilter-vs2019.vcxproj b/HookFilter/HookFilter-vs2019.vcxproj
deleted file mode 100644
index ea9912b2..00000000
--- a/HookFilter/HookFilter-vs2019.vcxproj
+++ /dev/null
@@ -1,173 +0,0 @@
-
-
-
-
- Debug v141_xp
- Win32
-
-
- Debug
- Win32
-
-
- Release v141_xp
- Win32
-
-
- Release
- Win32
-
-
-
- HookFilter
- {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}
- HookFilter
- Win32Proj
- 10.0
-
-
-
- DynamicLibrary
- v142
- Unicode
- true
-
-
- DynamicLibrary
- v141_xp
- Unicode
- true
-
-
- DynamicLibrary
- v142
- Unicode
-
-
- DynamicLibrary
- v141_xp
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>15.0.26419.1
-
-
- $(SolutionDir)$(Configuration)\
- $(Configuration)\
- true
-
-
- $(SolutionDir)$(Configuration)\
- $(Configuration)\
- true
-
-
- $(SolutionDir)$(Configuration)\
- $(Configuration)\
- false
-
-
- $(SolutionDir)$(Configuration)\
- $(Configuration)\
- false
-
-
-
- Disabled
- WIN32;_DEBUG;_WINDOWS;_USRDLL;HOOKFILTER_EXPORTS;%(PreprocessorDefinitions)
- EnableFastChecks
- MultiThreadedDebugDLL
-
- Level3
- EditAndContinue
-
-
- true
- Windows
- MachineX86
-
-
-
-
-
- Disabled
- WIN32;_DEBUG;_WINDOWS;_USRDLL;HOOKFILTER_EXPORTS;%(PreprocessorDefinitions)
- EnableFastChecks
- MultiThreadedDebugDLL
-
-
- Level3
- EditAndContinue
-
-
- true
- Windows
- MachineX86
-
-
-
-
-
-
- MaxSpeed
- true
- WIN32;NDEBUG;_WINDOWS;_USRDLL;HOOKFILTER_EXPORTS;%(PreprocessorDefinitions)
- MultiThreadedDLL
- true
-
- Level3
- ProgramDatabase
-
-
- true
- Windows
- true
- true
- MachineX86
-
-
-
-
- MaxSpeed
- true
- WIN32;NDEBUG;_WINDOWS;_USRDLL;HOOKFILTER_EXPORTS;%(PreprocessorDefinitions)
- MultiThreadedDLL
- true
-
-
- Level3
- ProgramDatabase
-
-
-
-
- true
- Windows
- true
- true
- MachineX86
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/HookFilter/HookFilter-vs2019.vcxproj.filters b/HookFilter/HookFilter-vs2019.vcxproj.filters
deleted file mode 100644
index 7d5dd6b4..00000000
--- a/HookFilter/HookFilter-vs2019.vcxproj.filters
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- Source Files
-
-
-
\ No newline at end of file
diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp
deleted file mode 100644
index ebaf358c..00000000
--- a/HookFilter/HookFilter.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#include
-
-static HWND g_hFrameWindow = (HWND)0;
-static bool g_bHookAltTab = false;
-static bool g_bHookAltGrControl = false;
-
-// 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)
-{
-#ifndef _WIN64
- #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
-#endif
-
- if (nCode == HC_ACTION)
- {
- bool suppress = false;
-
- PKBDLLHOOKSTRUCT pKbdLlHookStruct = (PKBDLLHOOKSTRUCT) lParam;
- UINT newMsg = pKbdLlHookStruct->flags & LLKHF_UP ? WM_KEYUP : WM_KEYDOWN;
- LPARAM newlParam = newMsg == WM_KEYUP ? 3<<30 : 0; // b31:transition state, b30:previous key state
-
- //
-
- // NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
- // Keyboard scanCodes: LCONTROL=0x1D, LCONTROL_from_RMENU=0x21D
- // . For: Microsoft PS/2/Win7-64, VAIO laptop/Win7-64, Microsoft USB/Win10-64
- // NB. WM_KEYDOWN also includes a 9/10-bit? scanCode: LCONTROL=0x1D, RCONTROL=0x11D, RMENU=0x1D(not 0x21D)
- // . Can't suppress in app, since scanCode is not >= 0x200
- if (g_bHookAltGrControl && pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200) // GH#558
- {
- suppress = true;
- }
-
- // Suppress alt-tab
- if (g_bHookAltTab && pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
- {
- PostMessage(g_hFrameWindow, newMsg, VK_TAB, newlParam);
- suppress = true;
- }
-
- // Suppress alt-escape
- if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
- {
- PostMessage(g_hFrameWindow, newMsg, VK_ESCAPE, newlParam);
- suppress = true;
- }
-
- // Suppress alt-space
- if (pKbdLlHookStruct->vkCode == VK_SPACE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
- {
- PostMessage(g_hFrameWindow, newMsg, VK_SPACE, newlParam);
- suppress = true;
- }
-
- // Suppress ctrl-escape
- if (pKbdLlHookStruct->vkCode == VK_ESCAPE)
- {
- // But don't suppress CTRL+SHIFT+ESC
- if (GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) >= 0)
- suppress = true;
- }
-
- // Suppress keys by returning 1
- if (suppress)
- return 1;
- }
-
- return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam);
-}
-
-extern "C" __declspec(dllexport) void __cdecl RegisterHWND(HWND hWnd, bool bHookAltTab, bool bHookAltGrControl)
-{
- g_hFrameWindow = hWnd;
- g_bHookAltTab = bHookAltTab;
- g_bHookAltGrControl = bHookAltGrControl;
-}
diff --git a/HookFilter/HookFilter.vcproj b/HookFilter/HookFilter.vcproj
deleted file mode 100644
index 61bb8edb..00000000
--- a/HookFilter/HookFilter.vcproj
+++ /dev/null
@@ -1,181 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp
index 3a8c0dd5..03c5a6f8 100644
--- a/source/Windows/AppleWin.cpp
+++ b/source/Windows/AppleWin.cpp
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Windows/AppleWin.h"
+#include "Windows/HookFilter.h"
#include "Interface.h"
#include "Utilities.h"
#include "CmdLine.h"
@@ -73,6 +74,11 @@ void Win32Frame::SetLoadedSaveStateFlag(const bool bFlag)
g_bLoadedSaveState = bFlag;
}
+bool GetHookAltTab(void)
+{
+ return g_bHookAltTab;
+}
+
bool GetHookAltGrControl(void)
{
return g_bHookAltGrControl;
@@ -490,113 +496,6 @@ static void RegisterHotKeys(void)
//---------------------------------------------------------------------------
-static HINSTANCE g_hinstDLL = 0;
-static HHOOK g_hhook = 0;
-
-static HANDLE g_hHookThread = NULL;
-static DWORD g_HookThreadId = 0;
-
-// Pre: g_hFrameWindow must be valid
-static bool HookFilterForKeyboard()
-{
- g_hinstDLL = LoadLibrary(TEXT("HookFilter.dll"));
-
- _ASSERT(GetFrame().g_hFrameWindow);
-
- typedef void (*RegisterHWNDProc)(HWND, bool, bool);
- RegisterHWNDProc RegisterHWND = (RegisterHWNDProc) GetProcAddress(g_hinstDLL, "RegisterHWND");
- if (RegisterHWND)
- RegisterHWND(GetFrame().g_hFrameWindow, g_bHookAltTab, g_bHookAltGrControl);
-
- HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc");
-
- g_hhook = SetWindowsHookEx(
- WH_KEYBOARD_LL,
- hkprcLowLevelKeyboardProc,
- g_hinstDLL,
- 0);
-
- if (g_hhook != 0 && GetFrame().g_hFrameWindow != 0)
- return true;
-
- std::string msg("Failed to install hook filter for system keys");
-
- DWORD dwErr = GetLastError();
- GetFrame().FrameMessageBox(msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
-
- msg += "\n";
- LogFileOutput(msg.c_str());
- return false;
-}
-
-static void UnhookFilterForKeyboard()
-{
- UnhookWindowsHookEx(g_hhook);
- FreeLibrary(g_hinstDLL);
-}
-
-static DWORD WINAPI HookThread(LPVOID lpParameter)
-{
- if (!HookFilterForKeyboard())
- return -1;
-
- MSG msg;
- while(GetMessage(&msg, NULL, 0, 0) > 0)
- {
- if (msg.message == WM_QUIT)
- break;
-
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- UnhookFilterForKeyboard();
- return 0;
-}
-
-static bool InitHookThread()
-{
- g_hHookThread = CreateThread(NULL, // lpThreadAttributes
- 0, // dwStackSize
- (LPTHREAD_START_ROUTINE) HookThread,
- 0, // lpParameter
- 0, // dwCreationFlags : 0 = Run immediately
- &g_HookThreadId); // lpThreadId
- if (g_hHookThread == NULL)
- return false;
-
- return true;
-}
-
-static void UninitHookThread()
-{
- if (g_hHookThread)
- {
- if (!PostThreadMessage(g_HookThreadId, WM_QUIT, 0, 0))
- {
- _ASSERT(0);
- return;
- }
-
- do
- {
- DWORD dwExitCode;
- if (GetExitCodeThread(g_hHookThread, &dwExitCode))
- {
- if(dwExitCode == STILL_ACTIVE)
- Sleep(10);
- else
- break;
- }
- }
- while(1);
-
- CloseHandle(g_hHookThread);
- g_hHookThread = NULL;
- g_HookThreadId = 0;
- }
-}
-
static void ExceptionHandler(const char* pError)
{
GetFrame().FrameMessageBox(
@@ -666,7 +565,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (g_bHookSystemKey)
{
- UninitHookThread();
+ GetHookFilter().UninitHookThread();
LogFileOutput("Main: UnhookFilterForKeyboard()\n");
}
}
@@ -915,7 +814,7 @@ static void RepeatInitialization(void)
if (g_bHookSystemKey)
{
- if (InitHookThread()) // needs valid g_hFrameWindow (for message pump)
+ if (GetHookFilter().InitHookThread()) // needs valid g_hFrameWindow (for message pump)
LogFileOutput("Main: HookFilterForKeyboard()\n");
}
diff --git a/source/Windows/AppleWin.h b/source/Windows/AppleWin.h
index 0042829e..2e60ab95 100644
--- a/source/Windows/AppleWin.h
+++ b/source/Windows/AppleWin.h
@@ -6,6 +6,7 @@ void SingleStep(bool bReinit);
// Win32
bool GetLoadedSaveStateFlag(void);
+bool GetHookAltTab(void);
bool GetHookAltGrControl(void);
extern bool g_bRestartFullScreen;
diff --git a/source/Windows/HookFilter.cpp b/source/Windows/HookFilter.cpp
new file mode 100644
index 00000000..b9f7a9e8
--- /dev/null
+++ b/source/Windows/HookFilter.cpp
@@ -0,0 +1,203 @@
+/*
+AppleWin : An Apple //e emulator for Windows
+
+Copyright (C) 1994-1996, Michael O'Brien
+Copyright (C) 1999-2001, Oliver Schmidt
+Copyright (C) 2002-2005, Tom Charlesworth
+Copyright (C) 2006-2021, Tom Charlesworth, Michael Pohoreski
+
+AppleWin is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+AppleWin is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with AppleWin; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* Description: HookFilter
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "HookFilter.h"
+
+#include "AppleWin.h"
+#include "Interface.h"
+#include "Log.h"
+
+HookFilter& GetHookFilter(void)
+{
+ static HookFilter hookFilter;
+ return hookFilter;
+}
+
+LRESULT CALLBACK HookFilter::LowLevelKeyboardProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
+{
+ if (nCode == HC_ACTION)
+ {
+ bool suppress = false;
+
+ PKBDLLHOOKSTRUCT pKbdLlHookStruct = (PKBDLLHOOKSTRUCT) lParam;
+ UINT newMsg = pKbdLlHookStruct->flags & LLKHF_UP ? WM_KEYUP : WM_KEYDOWN;
+ LPARAM newlParam = newMsg == WM_KEYUP ? 3<<30 : 0; // b31:transition state, b30:previous key state
+
+ //
+
+ // NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
+ // Keyboard scanCodes: LCONTROL=0x1D, LCONTROL_from_RMENU=0x21D
+ // . For: Microsoft PS/2/Win7-64, VAIO laptop/Win7-64, Microsoft USB/Win10-64
+ // NB. WM_KEYDOWN also includes a 9/10-bit? scanCode: LCONTROL=0x1D, RCONTROL=0x11D, RMENU=0x1D(not 0x21D)
+ // . Can't suppress in app, since scanCode is not >= 0x200
+ if (GetHookFilter().m_bHookAltGrControl && pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200) // GH#558
+ {
+ suppress = true;
+ }
+
+ // Suppress alt-tab
+ if (GetHookFilter().m_bHookAltTab && pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
+ {
+ PostMessage(GetHookFilter().m_hFrameWindow, newMsg, VK_TAB, newlParam);
+ suppress = true;
+ }
+
+ // Suppress alt-escape
+ if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
+ {
+ PostMessage(GetHookFilter().m_hFrameWindow, newMsg, VK_ESCAPE, newlParam);
+ suppress = true;
+ }
+
+ // Suppress alt-space
+ if (pKbdLlHookStruct->vkCode == VK_SPACE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
+ {
+ PostMessage(GetHookFilter().m_hFrameWindow, newMsg, VK_SPACE, newlParam);
+ suppress = true;
+ }
+
+ // Suppress ctrl-escape
+ if (pKbdLlHookStruct->vkCode == VK_ESCAPE)
+ {
+ // But don't suppress CTRL+SHIFT+ESC
+ if (GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) >= 0)
+ suppress = true;
+ }
+
+ // Suppress keys by returning 1
+ if (suppress)
+ return 1;
+ }
+
+ return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam);
+}
+
+//---------------------------------------------------------------------------
+
+// The hook filter code can be static (within the application) rather than in a DLL.
+// Pre: g_hFrameWindow must be valid
+bool HookFilter::HookFilterForKeyboard(void)
+{
+ _ASSERT(GetFrame().g_hFrameWindow);
+
+ m_hFrameWindow = GetFrame().g_hFrameWindow;
+ m_bHookAltTab = GetHookAltTab();
+ m_bHookAltGrControl = GetHookAltGrControl();
+
+ // Since no DLL gets injected anyway for low-level hooks, we can use, for example, GetModuleHandle("kernel32.dll")
+ HINSTANCE hinstDLL = GetModuleHandle("kernel32.dll");
+
+ m_hhook = SetWindowsHookEx(
+ WH_KEYBOARD_LL,
+ LowLevelKeyboardProc,
+ hinstDLL,
+ 0);
+
+ if (m_hhook != 0 && GetFrame().g_hFrameWindow != 0)
+ return true;
+
+ std::string msg("Failed to install hook filter for system keys");
+
+ DWORD dwErr = GetLastError();
+ GetFrame().FrameMessageBox(msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
+
+ msg += "\n";
+ LogFileOutput(msg.c_str());
+ return false;
+}
+
+void HookFilter::UnhookFilterForKeyboard(void)
+{
+ UnhookWindowsHookEx(m_hhook);
+}
+
+DWORD WINAPI HookFilter::HookThread(LPVOID lpParameter)
+{
+ HookFilter* hf = (HookFilter*)lpParameter;
+
+ if (!hf->HookFilterForKeyboard())
+ return -1;
+
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0, 0) > 0)
+ {
+ if (msg.message == WM_QUIT)
+ break;
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ hf->UnhookFilterForKeyboard();
+ return 0;
+}
+
+bool HookFilter::InitHookThread(void)
+{
+ m_hHookThread = CreateThread(NULL, // lpThreadAttributes
+ 0, // dwStackSize
+ (LPTHREAD_START_ROUTINE)HookThread,
+ this, // lpParameter
+ 0, // dwCreationFlags : 0 = Run immediately
+ &m_HookThreadId); // lpThreadId
+
+ if (m_hHookThread == NULL)
+ return false;
+
+ return true;
+}
+
+void HookFilter::UninitHookThread(void)
+{
+ if (m_hHookThread)
+ {
+ if (!PostThreadMessage(m_HookThreadId, WM_QUIT, 0, 0))
+ {
+ _ASSERT(0);
+ return;
+ }
+
+ do
+ {
+ DWORD dwExitCode;
+ if (GetExitCodeThread(m_hHookThread, &dwExitCode))
+ {
+ if (dwExitCode == STILL_ACTIVE)
+ Sleep(10);
+ else
+ break;
+ }
+ } while (1);
+
+ CloseHandle(m_hHookThread);
+ m_hHookThread = NULL;
+ m_HookThreadId = 0;
+ }
+}
diff --git a/source/Windows/HookFilter.h b/source/Windows/HookFilter.h
new file mode 100644
index 00000000..809f1483
--- /dev/null
+++ b/source/Windows/HookFilter.h
@@ -0,0 +1,38 @@
+#pragma once
+
+class HookFilter
+{
+public:
+ HookFilter()
+ {
+ m_hFrameWindow = (HWND)0;
+ m_bHookAltTab = false;
+ m_bHookAltGrControl = false;
+
+ m_hhook = 0;
+ m_hHookThread = NULL;
+ m_HookThreadId = 0;
+ }
+ ~HookFilter()
+ {
+ }
+
+ bool InitHookThread(void);
+ void UninitHookThread(void);
+
+private:
+ static LRESULT CALLBACK LowLevelKeyboardProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam);
+ bool HookFilterForKeyboard(void);
+ void UnhookFilterForKeyboard(void);
+ static DWORD WINAPI HookThread(LPVOID lpParameter);
+
+ HWND m_hFrameWindow;
+ bool m_bHookAltTab;
+ bool m_bHookAltGrControl;
+
+ HHOOK m_hhook;
+ HANDLE m_hHookThread;
+ DWORD m_HookThreadId;
+};
+
+HookFilter& GetHookFilter(void);