- Properly handle cases of more than 64 icons

- Don't leak the list of handles on each pass through the loop
- Make sure we clean up if the wait fails for whatever reason
This commit is contained in:
Ged Murphy 2018-01-20 18:09:23 +00:00
parent 851e0ca5a8
commit be2bf9b8c5

View file

@ -112,7 +112,8 @@ public:
void Uninitialize() void Uninitialize()
{ {
m_Loop = false; m_Loop = false;
SetEvent(m_WakeUpEvent); if (m_WakeUpEvent)
SetEvent(m_WakeUpEvent);
EnterCriticalSection(&m_ListLock); EnterCriticalSection(&m_ListLock);
@ -134,22 +135,41 @@ public:
bool AddIconToWatcher(_In_ NOTIFYICONDATA *iconData) bool AddIconToWatcher(_In_ NOTIFYICONDATA *iconData)
{ {
IconWatcherData *Icon = new IconWatcherData(iconData); DWORD ProcessId;
(void)GetWindowThreadProcessId(iconData->hWnd, &ProcessId);
(void)GetWindowThreadProcessId(iconData->hWnd, &Icon->ProcessId); HANDLE hProcess;
hProcess = OpenProcess(SYNCHRONIZE, FALSE, ProcessId);
Icon->hProcess = OpenProcess(SYNCHRONIZE, FALSE, Icon->ProcessId); if (hProcess == NULL)
if (Icon->hProcess == NULL) {
return false; return false;
}
IconWatcherData *Icon = new IconWatcherData(iconData);
Icon->hProcess = hProcess;
Icon->ProcessId;
bool Added = false;
EnterCriticalSection(&m_ListLock); EnterCriticalSection(&m_ListLock);
m_WatcherList.AddTail(Icon); // The likelyhood of someone having more than 64 icons in their tray is
SetEvent(m_WakeUpEvent); // pretty slim. We could spin up a new thread for each multiple of 64, but
// it's not worth the effort, so we just won't bother watching those icons
if (m_WatcherList.GetCount() <= MAXIMUM_WAIT_OBJECTS)
{
m_WatcherList.AddTail(Icon);
SetEvent(m_WakeUpEvent);
Added = true;
}
LeaveCriticalSection(&m_ListLock); LeaveCriticalSection(&m_ListLock);
return true; if (!Added)
{
delete Icon;
}
return Added;
} }
bool RemoveIconFromWatcher(_In_ NOTIFYICONDATA *iconData) bool RemoveIconFromWatcher(_In_ NOTIFYICONDATA *iconData)
@ -198,16 +218,19 @@ private:
static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam) static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam)
{ {
CIconWatcher* This = reinterpret_cast<CIconWatcher *>(lpParam); CIconWatcher* This = reinterpret_cast<CIconWatcher *>(lpParam);
HANDLE *WatchList = NULL;
This->m_Loop = true; This->m_Loop = true;
while (This->m_Loop) while (This->m_Loop)
{ {
HANDLE *WatchList;
DWORD Size;
EnterCriticalSection(&This->m_ListLock); EnterCriticalSection(&This->m_ListLock);
DWORD Size;
Size = This->m_WatcherList.GetCount() + 1; Size = This->m_WatcherList.GetCount() + 1;
ASSERT(Size <= MAXIMUM_WAIT_OBJECTS);
if (WatchList)
delete WatchList;
WatchList = new HANDLE[Size]; WatchList = new HANDLE[Size];
WatchList[0] = This->m_WakeUpEvent; WatchList[0] = This->m_WakeUpEvent;
@ -274,10 +297,13 @@ private:
Status = GetLastError(); Status = GetLastError();
} }
ERR("Failed to wait on process handles : %lu\n", Status); ERR("Failed to wait on process handles : %lu\n", Status);
This->m_Loop = false; This->Uninitialize();
} }
} }
if (WatchList)
delete WatchList;
return 0; return 0;
} }
}; };
@ -851,7 +877,7 @@ public:
ret = Toolbar.AddButton(iconData); ret = Toolbar.AddButton(iconData);
if (ret == TRUE) if (ret == TRUE)
{ {
AddIconToWatcher(iconData); (void)AddIconToWatcher(iconData);
} }
break; break;
case NIM_MODIFY: case NIM_MODIFY:
@ -861,7 +887,7 @@ public:
ret = Toolbar.RemoveButton(iconData); ret = Toolbar.RemoveButton(iconData);
if (ret == TRUE) if (ret == TRUE)
{ {
RemoveIconFromWatcher(iconData); (void)RemoveIconFromWatcher(iconData);
} }
break; break;
default: default: