2828#include " keycapture.h"
2929#include " keyboardproc.h"
3030#include " mouseinput.h"
31- #include " keyboardinput.h"
3231#include " configfile.h"
3332
3433// === prototypes
@@ -39,9 +38,11 @@ extern "C"
3938 __declspec (dllexport) void ShutdownCapture();
4039}
4140
42- HHOOK g_hookMain = NULL ;
41+ // non extern functions
42+ void InitiallizeEntryContainerListItem (RemapEntryContainerListItem* pKeyItem, RemapEntry* pEntry);
4343
4444// sweet globals
45+ HHOOK g_hookMain = NULL ;
4546RemapEntryContainerListItem* g_KeyTranslationTable[WIN_KEY_COUNT];
4647RemapEntry* g_KeyTranslationHead = NULL ;
4748void * g_KeyTranslationEnd = NULL ; // pointer indicating the end of the input file data
@@ -83,20 +84,19 @@ __declspec(dllexport) int LoadAndCaptureFromFile(HINSTANCE hInstance, char* sFil
8384 return INPUT_BAD;
8485 }
8586 // TODO: just get a pointer to g_KeyTranslationTable[pKey->inputConfig.virtualKey] ?
86-
87+ # ifdef _DEBUG
8788 char * pInputConfigDescription = GetInputConfigDescription (pEntry->inputConfig );
8889 LogDebugMessage (" Loading %s Outputs: %d" , pInputConfigDescription, pEntry->outputCount );
8990 free (pInputConfigDescription);
90-
91+ # endif
9192 // if the entry doesn't exist yet for the given input vkey create a new one with a null next pointer
9293 if (NULL == g_KeyTranslationTable[pEntry->inputConfig .virtualKey ])
9394 {
9495 g_KeyTranslationTable[pEntry->inputConfig .virtualKey ] = (RemapEntryContainerListItem*)malloc (sizeof (RemapEntryContainerListItem));
95- g_KeyTranslationTable[pEntry->inputConfig .virtualKey ]->pEntryContainer = (RemapEntryContainer*)malloc (sizeof (RemapEntryContainer));
96- g_KeyTranslationTable[pEntry->inputConfig .virtualKey ]->pEntryContainer ->pEntryState = (RemapEntryState*)malloc (sizeof (RemapEntryState));
97- g_KeyTranslationTable[pEntry->inputConfig .virtualKey ]->pEntryContainer ->pEntry = pEntry;
96+ InitiallizeEntryContainerListItem (g_KeyTranslationTable[pEntry->inputConfig .virtualKey ], pEntry);
9897 g_KeyTranslationTable[pEntry->inputConfig .virtualKey ]->pNext = NULL ;
9998 }
99+
100100 // if the entry does exist create a new entry and append it to the existing linked list
101101 else
102102 {
@@ -107,9 +107,7 @@ __declspec(dllexport) int LoadAndCaptureFromFile(HINSTANCE hInstance, char* sFil
107107 }
108108 pKeyItem->pNext = (RemapEntryContainerListItem*)malloc (sizeof (RemapEntryContainerListItem));
109109 pKeyItem = pKeyItem->pNext ;
110- pKeyItem->pEntryContainer = (RemapEntryContainer*)malloc (sizeof (RemapEntryContainer));
111- pKeyItem->pEntryContainer ->pEntryState = (RemapEntryState*)malloc (sizeof (RemapEntryState));
112- pKeyItem->pEntryContainer ->pEntry = pEntry;
110+ InitiallizeEntryContainerListItem (pKeyItem, pEntry);
113111 pKeyItem->pNext = NULL ;
114112 }
115113 // jump to the next entry
@@ -130,7 +128,7 @@ __declspec(dllexport) int LoadAndCaptureFromFile(HINSTANCE hInstance, char* sFil
130128 if (bValidTranslationSet)
131129 {
132130 // Note: This fails in VisualStudio if managed debugging is NOT enabled in the project(!)
133- HHOOK g_hookMain = SetWindowsHookEx ( WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, NULL );
131+ g_hookMain = SetWindowsHookEx ( WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, NULL );
134132 if (NULL == g_hookMain)
135133 {
136134 ShutdownCapture ();
@@ -148,11 +146,67 @@ __declspec(dllexport) int LoadAndCaptureFromFile(HINSTANCE hInstance, char* sFil
148146 }
149147}
150148
149+ void InitiallizeEntryContainerListItem (RemapEntryContainerListItem* pKeyItem, RemapEntry* pEntry)
150+ {
151+ pKeyItem->pEntryContainer = (RemapEntryContainer*)malloc (sizeof (RemapEntryContainer));
152+ pKeyItem->pEntryContainer ->pEntryState = (RemapEntryState*)calloc (1 , sizeof (RemapEntryState));
153+ pKeyItem->pEntryContainer ->pEntry = pEntry;
154+ }
155+
151156/*
152157Shuts down the key capture hook and frees any allocated memory
153158*/
154159__declspec (dllexport) void ShutdownCapture()
155160{
161+ // signal shutdown for all entries with a thread handle
162+ for (int nIdx = 0 ; nIdx < WIN_KEY_COUNT; nIdx++)
163+ {
164+ if (NULL != g_KeyTranslationTable[nIdx])
165+ {
166+ RemapEntryContainerListItem* pListItem = g_KeyTranslationTable[nIdx];
167+ RemapEntryContainerListItem* pNextItem = NULL ;
168+ while (NULL != pListItem)
169+ {
170+ pNextItem = pListItem->pNext ;
171+ if (NULL != pListItem->pEntryContainer ->pEntryState ->threadHandle )
172+ {
173+ pListItem->pEntryContainer ->pEntryState ->bShutdown = true ;
174+ }
175+ pListItem = pNextItem;
176+ }
177+ }
178+ }
179+
180+ // monitor and terminate threads for all entries with a thread handle
181+ for (int nIdx = 0 ; nIdx < WIN_KEY_COUNT; nIdx++)
182+ {
183+ if (NULL != g_KeyTranslationTable[nIdx])
184+ {
185+ RemapEntryContainerListItem* pListItem = g_KeyTranslationTable[nIdx];
186+ RemapEntryContainerListItem* pNextItem = NULL ;
187+ while (NULL != pListItem)
188+ {
189+ pNextItem = pListItem->pNext ;
190+ if (NULL != pListItem->pEntryContainer ->pEntryState ->threadHandle )
191+ {
192+ DWORD dwExitCode = WAIT_TIMEOUT;
193+ for (int shutdownIteration = 0 ; shutdownIteration < THREAD_SHUTDOWN_MAX_ATTEMPTS && dwExitCode != WAIT_OBJECT_0; shutdownIteration++)
194+ {
195+ // check on the state of the thread (for 100ms) (MS says not to use GetExitCodeThread unless the thread is known to be exited)
196+ dwExitCode = WaitForSingleObject (pListItem->pEntryContainer ->pEntryState ->threadHandle , THREAD_SHUTDOWN_ATTEMPT_DELAY_MS);
197+ }
198+ if (dwExitCode != WAIT_OBJECT_0)
199+ {
200+ LogDebugMessage (" Force terminating thread!" );
201+ TerminateThread (pListItem->pEntryContainer ->pEntryState ->threadHandle , 1 );
202+ }
203+ }
204+ pListItem = pNextItem;
205+ }
206+ }
207+ }
208+
209+
156210 // disable the hook
157211 if (NULL != g_hookMain)
158212 {
0 commit comments