From 900921736675047806c92e5b0e276e7a74cfef9c Mon Sep 17 00:00:00 2001 From: Quantum Date: Sun, 14 Sep 2025 16:26:05 -0400 Subject: [PATCH] [idd] helper: stop using MsgWaitForMultipleObjects `MsgWaitForMultipleObjects` doesn't handle inner message loops, which may happen during `TrackPopupMenu`, causing exits to fail. --- idd/LGIddHelper/CNotifyWindow.cpp | 16 +++++++++- idd/LGIddHelper/CNotifyWindow.h | 4 +++ idd/LGIddHelper/main.cpp | 53 +++++++++++-------------------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/idd/LGIddHelper/CNotifyWindow.cpp b/idd/LGIddHelper/CNotifyWindow.cpp index a03a4989..77373df6 100644 --- a/idd/LGIddHelper/CNotifyWindow.cpp +++ b/idd/LGIddHelper/CNotifyWindow.cpp @@ -22,7 +22,8 @@ bool CNotifyWindow::registerClass() return s_atom; } -CNotifyWindow::CNotifyWindow() : m_iconData({ 0 }), m_menu(CreatePopupMenu()) +CNotifyWindow::CNotifyWindow() : m_iconData({ 0 }), m_menu(CreatePopupMenu()), + closeRequested(false) { CreateWindowEx(0, MAKEINTATOM(s_atom), NULL, 0, 0, 0, 0, 0, NULL, NULL, hInstance, this); @@ -63,6 +64,13 @@ LRESULT CNotifyWindow::onCreate() return 0; } +LRESULT CNotifyWindow::onClose() +{ + if (closeRequested) + destroy(); + return 0; +} + LRESULT CNotifyWindow::onNotifyIcon(UINT uEvent, WORD wIconId, int x, int y) { switch (uEvent) @@ -95,3 +103,9 @@ void CNotifyWindow::registerIcon() if (!Shell_NotifyIcon(NIM_SETVERSION, &m_iconData)) DEBUG_ERROR_HR(GetLastError(), "Shell_NotifyIcon(NIM_SETVERSION)"); } + +void CNotifyWindow::close() +{ + closeRequested = true; + PostMessage(m_hwnd, WM_CLOSE, 0, 0); +} diff --git a/idd/LGIddHelper/CNotifyWindow.h b/idd/LGIddHelper/CNotifyWindow.h index e7186c80..690cb93a 100644 --- a/idd/LGIddHelper/CNotifyWindow.h +++ b/idd/LGIddHelper/CNotifyWindow.h @@ -10,15 +10,19 @@ class CNotifyWindow : public CWindow NOTIFYICONDATA m_iconData; HMENU m_menu; + bool closeRequested; LRESULT onNotifyIcon(UINT uEvent, WORD wIconId, int x, int y); void registerIcon(); virtual LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override; virtual LRESULT onCreate() override; + virtual LRESULT onClose() override; public: CNotifyWindow(); ~CNotifyWindow() override; static bool registerClass(); + + void close(); }; diff --git a/idd/LGIddHelper/main.cpp b/idd/LGIddHelper/main.cpp index a1fa63f8..c772c67c 100644 --- a/idd/LGIddHelper/main.cpp +++ b/idd/LGIddHelper/main.cpp @@ -31,6 +31,13 @@ static HandleT l_process; static void Launch(); +void CALLBACK DestroyNotifyWindow(PVOID lpParam, BOOLEAN bTimedOut) +{ + DEBUG_INFO("Parent process exited, exiting..."); + CNotifyWindow *window = (CNotifyWindow *)lpParam; + window->close(); +} + int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) { wchar_t buffer[MAX_PATH]; @@ -79,46 +86,24 @@ int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _ return EXIT_FAILURE; } + if (!g_pipe.Init()) + return EXIT_FAILURE; + CNotifyWindow window; - if (!g_pipe.Init()) + HANDLE hWait; + if (!RegisterWaitForSingleObject(&hWait, hParent.Get(), DestroyNotifyWindow, &window, INFINITE, WT_EXECUTEONLYONCE)) + DEBUG_ERROR_HR(GetLastError(), "Failed to RegisterWaitForSingleObject"); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) { - window.destroy(); - hParent.Close(); + TranslateMessage(&msg); + DispatchMessage(&msg); } - while (true) - { - DWORD dwHandles = hParent.IsValid() ? 1 : 0; - LPHANDLE lpHandles = hParent.GetAddressOf(); + (void) UnregisterWait(hWait); - DWORD dwResult = MsgWaitForMultipleObjects(dwHandles, lpHandles, FALSE, INFINITE, QS_ALLINPUT); - if (dwResult == WAIT_FAILED) - { - DEBUG_ERROR_HR(GetLastError(), "MsgWaitForMultipleObjects Failed"); - g_pipe.DeInit(); - return EXIT_FAILURE; - } - else if (dwResult == WAIT_OBJECT_0 + dwHandles) - { - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - goto exit; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - else - { - DEBUG_INFO("Parent process exited, exiting..."); - hParent.Close(); - window.destroy(); - } - } - -exit: DEBUG_INFO("Helper window destroyed."); g_pipe.DeInit(); return EXIT_SUCCESS;