From 467dec4d16986b131ce1a16646aed89dbedb346d Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Sat, 29 Mar 2025 16:58:18 +0100 Subject: [PATCH] [CLEANMGR] Only allow one instance per drive (#7832) CORE-18941 --- .../cleanmgr/cleanmgr/CSelectDriveDlg.cpp | 13 +++++++ .../cleanmgr/cleanmgr/cleanmgr.cpp | 36 +++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp b/base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp index 6387bcd87a3..c78927f909c 100644 --- a/base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp +++ b/base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp @@ -25,6 +25,19 @@ public: LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { + // Try to find an existing instance of this dialog + WCHAR buf[300]; + GetWindowTextW(buf, _countof(buf)); + for (HWND hNext = NULL, hFind; (hFind = ::FindWindowExW(NULL, hNext, NULL, buf)) != NULL; hNext = hFind) + { + if (hFind != *this && ::IsWindowVisible(hFind)) + { + ::SetForegroundWindow(hFind); + EndDialog(IDCANCEL); + return FALSE; + } + } + CWindow cbo = GetDlgItem(IDC_DRIVES); WCHAR VolumeNameBuffer[MAX_PATH + 1]; CStringW Tmp; diff --git a/base/applications/cleanmgr/cleanmgr/cleanmgr.cpp b/base/applications/cleanmgr/cleanmgr/cleanmgr.cpp index 13505521208..99918381b74 100644 --- a/base/applications/cleanmgr/cleanmgr/cleanmgr.cpp +++ b/base/applications/cleanmgr/cleanmgr/cleanmgr.cpp @@ -247,6 +247,22 @@ public: return true; } + static inline UINT GetWindowProcessId(_In_ HWND hWnd) + { + DWORD pid; + return GetWindowThreadProcessId(hWnd, &pid) ? pid : 0; + } + + static BOOL CALLBACK EnumSingleInstanceCallback(_In_ HWND hWnd, _In_ LPARAM lParam) + { + if (::IsWindowVisible(hWnd) && (LPARAM)GetWindowProcessId(hWnd) == lParam) + { + ::SetForegroundWindow(hWnd); + return FALSE; + } + return TRUE; + } + HRESULT Run(_In_ int nShowCmd) throw() { if (m_Drive == UNICODE_NULL) @@ -257,6 +273,19 @@ public: if (m_Drive == UNICODE_NULL) return E_FAIL; + CStringW Title; + Title.Format(IDS_PROPERTIES_MAIN_TITLE, m_Drive); + + HWND hWndInstance = ::CreateWindowExW(WS_EX_TOOLWINDOW, WC_STATIC, Title, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + for (HWND hNext = NULL, hFind; (hFind = ::FindWindowExW(NULL, hNext, WC_STATIC, Title)) != NULL; hNext = hFind) + { + if (hFind != hWndInstance) + { + ::EnumWindows(EnumSingleInstanceCallback, GetWindowProcessId(hFind)); + return S_FALSE; + } + } + CCleanupHandlerList Handlers; CEmptyVolumeCacheCallBack CacheCallBack; @@ -271,16 +300,19 @@ public: psh.dwFlags = PSH_NOAPPLYNOW | PSH_USEICONID | PSH_NOCONTEXTHELP; psh.hInstance = _AtlBaseModule.GetResourceInstance(); psh.pszIcon = MAKEINTRESOURCEW(IDI_CLEANMGR); - CStringW Title; - Title.Format(IDS_PROPERTIES_MAIN_TITLE, m_Drive); psh.pszCaption = Title; psh.nPages = _countof(hpsp); psh.phpage = hpsp; if (PropertySheetW(&psh) >= 1) { + ::DestroyWindow(hWndInstance); // Allow new "cleanmgr /D" without waiting for these handlers Handlers.ExecuteCleanup(&CacheCallBack); } + else + { + ::DestroyWindow(hWndInstance); + } return S_OK; } };