Skip to content

Commit 13d7084

Browse files
committed
[CTFMON] Some fixes for event handles management (reactos#8392)
- Validate the opened `WinSta0_DesktopSwitch` handle; - Don't pass the `ahEvents` array containing a NULL pointer to `MsgWaitForMultipleObjects()`, but provide the correct number of non-NULL handles, otherwise the function fails and the code ends up busy-looping. - Validate the `MsgWaitForMultipleObjects()` result: bail out if `WAIT_FAILED` is returned. - Validate the event index passed to `CRegWatcher::InitEvent()` and `CRegWatcher::OnEvent()`. - Rename `WATCHENTRY_MAX` to `WI_REGEVTS_MAX` and add it in the `WATCH_INDEX` enumeration. - Fix some code comments.
1 parent d524fd8 commit 13d7084

File tree

4 files changed

+65
-40
lines changed

4 files changed

+65
-40
lines changed

base/ctf/ctfmon/CRegWatcher.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
#include <ime/indicml.h>
1111

1212
// The event handles to use in watching
13-
HANDLE CRegWatcher::s_ahWatchEvents[WATCHENTRY_MAX] = { NULL };
13+
HANDLE CRegWatcher::s_ahWatchEvents[WI_REGEVTS_MAX] = { NULL };
1414

1515
// The registry entries to watch
16-
WATCHENTRY CRegWatcher::s_WatchEntries[WATCHENTRY_MAX] =
16+
WATCHENTRY CRegWatcher::s_WatchEntries[WI_REGEVTS_MAX] =
1717
{
1818
{ HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Toggle") }, // WI_TOGGLE
1919
{ HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\CTF\\TIP") }, // WI_MACHINE_TIF
@@ -114,6 +114,9 @@ CRegWatcher::InitEvent(
114114
_In_ SIZE_T iEvent,
115115
_In_ BOOL bResetEvent)
116116
{
117+
if (iEvent >= _countof(s_ahWatchEvents))
118+
return FALSE;
119+
117120
// Reset the signal status
118121
if (bResetEvent)
119122
::ResetEvent(s_ahWatchEvents[iEvent]);
@@ -315,6 +318,9 @@ VOID
315318
CRegWatcher::OnEvent(
316319
_In_ SIZE_T iEvent)
317320
{
321+
if (iEvent >= _countof(s_ahWatchEvents))
322+
return;
323+
318324
InitEvent(iEvent, TRUE);
319325

320326
switch (iEvent)

base/ctf/ctfmon/CRegWatcher.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ struct WATCHENTRY
1414
HKEY hKey;
1515
};
1616

17-
#define WATCHENTRY_MAX 12
18-
1917
struct CRegWatcher
2018
{
21-
static HANDLE s_ahWatchEvents[WATCHENTRY_MAX];
22-
static WATCHENTRY s_WatchEntries[WATCHENTRY_MAX];
19+
static HANDLE s_ahWatchEvents[WI_REGEVTS_MAX];
20+
static WATCHENTRY s_WatchEntries[WI_REGEVTS_MAX];
2321
static UINT s_nSysColorTimerId, s_nKbdToggleTimerId, s_nRegImxTimerId;
2422

2523
static BOOL Init();

base/ctf/ctfmon/ctfmon.cpp

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ InitApp(
189189
_In_ HINSTANCE hInstance,
190190
_In_ LPTSTR lpCmdLine)
191191
{
192-
g_hInst = hInstance; // Save the instance handle
192+
g_hInst = hInstance; // Save the instance handle
193193

194-
g_bOnWow64 = cicIsWow64(); // Is the current process on WoW64?
194+
g_bOnWow64 = cicIsWow64(); // Is the current process on WoW64?
195195
cicGetOSInfo(&g_uACP, &g_dwOsInfo); // Get OS info
196196

197197
// Create a mutex for Cicero
@@ -227,7 +227,7 @@ InitApp(
227227

228228
if (g_pLoaderWnd->CreateWnd())
229229
{
230-
// Go to the bottom of the hell
230+
// Go to the bottom of the (s)hell
231231
::SetWindowPos(g_pLoaderWnd->m_hWnd, HWND_BOTTOM, 0, 0, 0, 0,
232232
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
233233
}
@@ -236,7 +236,7 @@ InitApp(
236236
if (!g_bOnWow64)
237237
GetPopupTipbar(g_pLoaderWnd->m_hWnd, g_fWinLogon);
238238

239-
// Do x64 stuffs
239+
// Initialize x64-specific support
240240
CheckX64System(lpCmdLine);
241241

242242
return TRUE;
@@ -264,7 +264,7 @@ DoMainLoop(VOID)
264264

265265
if (g_bOnWow64) // Is the current process on WoW64?
266266
{
267-
// Just a simple message loop
267+
// Simply run a message loop
268268
while (::GetMessage(&msg, NULL, 0, 0))
269269
{
270270
::TranslateMessage(&msg);
@@ -273,26 +273,30 @@ DoMainLoop(VOID)
273273
return (INT)msg.wParam;
274274
}
275275

276-
// Open the existing event by the name
277-
HANDLE hSwitchEvent = ::OpenEvent(SYNCHRONIZE, FALSE, TEXT("WinSta0_DesktopSwitch"));
278-
279-
// The target events to watch
280-
HANDLE ahEvents[WATCHENTRY_MAX + 1];
276+
// We wait on the CRegWatcher and the WinSta0 desktop-switch events.
277+
HANDLE ahEvents[WI_REGEVTS_MAX + 1];
278+
DWORD dwEventCount;
281279

282-
// Borrow some handles from CRegWatcher
283-
CopyMemory(ahEvents, CRegWatcher::s_ahWatchEvents, WATCHENTRY_MAX * sizeof(HANDLE));
280+
// Get the CRegWatcher handles
281+
CopyMemory(ahEvents, CRegWatcher::s_ahWatchEvents, WI_REGEVTS_MAX * sizeof(HANDLE));
282+
dwEventCount = WI_REGEVTS_MAX;
284283

285-
ahEvents[WI_DESKTOP_SWITCH] = hSwitchEvent; // Add it
284+
// Open the WinSta0 desktop-switch event and add it
285+
HANDLE hSwitchEvent = ::OpenEvent(SYNCHRONIZE, FALSE, TEXT("WinSta0_DesktopSwitch"));
286+
if (hSwitchEvent)
287+
{
288+
ahEvents[WI_DESKTOP_SWITCH] = hSwitchEvent;
289+
++dwEventCount;
290+
}
286291

287-
// Another message loop
292+
// Run the event loop
288293
for (;;)
289294
{
290-
// Wait for target signal
291-
DWORD dwWait = ::MsgWaitForMultipleObjects(_countof(ahEvents), ahEvents, 0, INFINITE,
292-
QS_ALLINPUT);
293-
if (dwWait == (WAIT_OBJECT_0 + _countof(ahEvents))) // Is input available?
295+
DWORD dwWait = ::MsgWaitForMultipleObjects(dwEventCount, ahEvents,
296+
FALSE, INFINITE, QS_ALLINPUT);
297+
if (dwWait == (WAIT_OBJECT_0 + dwEventCount)) // Is input available?
294298
{
295-
// Do the events
299+
// Pump available messages
296300
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
297301
{
298302
if (msg.message == WM_QUIT)
@@ -307,14 +311,30 @@ DoMainLoop(VOID)
307311
SetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0);
308312
::ResetEvent(hSwitchEvent);
309313
}
310-
else // Do the other events
314+
else if (dwWait < (WAIT_OBJECT_0 + WI_REGEVTS_MAX)) // Do the other events
311315
{
312316
CRegWatcher::OnEvent(dwWait - WAIT_OBJECT_0);
313317
}
318+
else if (dwWait == WAIT_TIMEOUT)
319+
{
320+
// Ignore
321+
#ifndef NDEBUG
322+
OutputDebugStringA("DoMainLoop: WAIT_TIMEOUT\n");
323+
#endif
324+
}
325+
else if (dwWait == WAIT_FAILED)
326+
{
327+
// Something failed, bail out
328+
#ifndef NDEBUG
329+
OutputDebugStringA("DoMainLoop: WAIT_FAILED, exiting\n");
330+
#endif
331+
break;
332+
}
314333
}
315334

316335
Quit:
317-
::CloseHandle(hSwitchEvent);
336+
if (hSwitchEvent)
337+
::CloseHandle(hSwitchEvent);
318338

319339
return (INT)msg.wParam;
320340
}

base/ctf/ctfmon/precomp.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,18 @@ VOID UninitApp(VOID);
3232

3333
typedef enum WATCH_INDEX
3434
{
35-
WI_TOGGLE = 0,
36-
WI_MACHINE_TIF = 1,
37-
WI_PRELOAD = 2,
38-
WI_RUN = 3,
39-
WI_USER_TIF = 4,
40-
WI_USER_SPEECH = 5,
41-
WI_APPEARANCE = 6,
42-
WI_COLORS = 7,
43-
WI_WINDOW_METRICS = 8,
44-
WI_MACHINE_SPEECH = 9,
45-
WI_KEYBOARD_LAYOUT = 10,
46-
WI_ASSEMBLIES = 11,
47-
WI_DESKTOP_SWITCH = 12,
35+
WI_TOGGLE = 0,
36+
WI_MACHINE_TIF = 1,
37+
WI_PRELOAD = 2,
38+
WI_RUN = 3,
39+
WI_USER_TIF = 4,
40+
WI_USER_SPEECH = 5,
41+
WI_APPEARANCE = 6,
42+
WI_COLORS = 7,
43+
WI_WINDOW_METRICS = 8,
44+
WI_MACHINE_SPEECH = 9,
45+
WI_KEYBOARD_LAYOUT = 10,
46+
WI_ASSEMBLIES = 11,
47+
WI_REGEVTS_MAX,
48+
WI_DESKTOP_SWITCH = WI_REGEVTS_MAX,
4849
} WATCH_INDEX;

0 commit comments

Comments
 (0)