https://git.reactos.org/?p=reactos.git;a=commitdiff;h=be2bf9b8c59edeb4c9c57540a4b499ad0f351b81

commit be2bf9b8c59edeb4c9c57540a4b499ad0f351b81
Author:     Ged Murphy <[email protected]>
AuthorDate: Sat Jan 20 18:09:23 2018 +0000
Commit:     Ged Murphy <[email protected]>
CommitDate: Sat Jan 20 18:38:42 2018 +0000

    - 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
---
 base/shell/explorer/trayntfy.cpp | 56 +++++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 15 deletions(-)

diff --git a/base/shell/explorer/trayntfy.cpp b/base/shell/explorer/trayntfy.cpp
index d7e3b52754..ae52dee226 100644
--- a/base/shell/explorer/trayntfy.cpp
+++ b/base/shell/explorer/trayntfy.cpp
@@ -112,7 +112,8 @@ public:
     void Uninitialize()
     {
         m_Loop = false;
-        SetEvent(m_WakeUpEvent);
+        if (m_WakeUpEvent)
+            SetEvent(m_WakeUpEvent);
 
         EnterCriticalSection(&m_ListLock);
 
@@ -134,22 +135,41 @@ public:
 
     bool AddIconToWatcher(_In_ NOTIFYICONDATA *iconData)
     {
-        IconWatcherData *Icon = new IconWatcherData(iconData);
+        DWORD ProcessId;
+        (void)GetWindowThreadProcessId(iconData->hWnd, &ProcessId);
 
-        (void)GetWindowThreadProcessId(iconData->hWnd, &Icon->ProcessId);
-
-        Icon->hProcess = OpenProcess(SYNCHRONIZE, FALSE, Icon->ProcessId);
-        if (Icon->hProcess == NULL)
+        HANDLE hProcess;
+        hProcess = OpenProcess(SYNCHRONIZE, FALSE, ProcessId);
+        if (hProcess == NULL)
+        {
             return false;
+        }
+
+        IconWatcherData *Icon = new IconWatcherData(iconData);
+        Icon->hProcess = hProcess;
+        Icon->ProcessId;
 
+        bool Added = false;
         EnterCriticalSection(&m_ListLock);
 
-        m_WatcherList.AddTail(Icon);
-        SetEvent(m_WakeUpEvent);
+        // The likelyhood of someone having more than 64 icons in their tray is
+        // 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);
 
-        return true;
+        if (!Added)
+        {
+            delete Icon;
+        }
+
+        return Added;
     }
 
     bool RemoveIconFromWatcher(_In_ NOTIFYICONDATA *iconData)
@@ -198,16 +218,19 @@ private:
     static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam)
     {
         CIconWatcher* This = reinterpret_cast<CIconWatcher *>(lpParam);
+        HANDLE *WatchList = NULL;
 
         This->m_Loop = true;
         while (This->m_Loop)
         {
-            HANDLE *WatchList;
-            DWORD Size;
-
             EnterCriticalSection(&This->m_ListLock);
 
+            DWORD Size;
             Size = This->m_WatcherList.GetCount() + 1;
+            ASSERT(Size <= MAXIMUM_WAIT_OBJECTS);
+
+            if (WatchList)
+                delete WatchList;
             WatchList = new HANDLE[Size];
             WatchList[0] = This->m_WakeUpEvent;
 
@@ -274,10 +297,13 @@ private:
                     Status = GetLastError();
                 }
                 ERR("Failed to wait on process handles : %lu\n", Status);
-                This->m_Loop = false;
+                This->Uninitialize();
             }
         }
 
+        if (WatchList)
+            delete WatchList;
+
         return 0;
     }
 };
@@ -851,7 +877,7 @@ public:
                 ret = Toolbar.AddButton(iconData);
                 if (ret == TRUE)
                 {
-                    AddIconToWatcher(iconData);
+                    (void)AddIconToWatcher(iconData);
                 }
                 break;
             case NIM_MODIFY:
@@ -861,7 +887,7 @@ public:
                 ret = Toolbar.RemoveButton(iconData);
                 if (ret == TRUE)
                 {
-                    RemoveIconFromWatcher(iconData);
+                    (void)RemoveIconFromWatcher(iconData);
                 }
                 break;
             default:

Reply via email to