Skip to content

Commit 467dec4

Browse files
authored
[CLEANMGR] Only allow one instance per drive (reactos#7832)
CORE-18941
1 parent 21b3382 commit 467dec4

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ class CSelectDriveDlg : public CDialogImpl<CSelectDriveDlg>
2525

2626
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
2727
{
28+
// Try to find an existing instance of this dialog
29+
WCHAR buf[300];
30+
GetWindowTextW(buf, _countof(buf));
31+
for (HWND hNext = NULL, hFind; (hFind = ::FindWindowExW(NULL, hNext, NULL, buf)) != NULL; hNext = hFind)
32+
{
33+
if (hFind != *this && ::IsWindowVisible(hFind))
34+
{
35+
::SetForegroundWindow(hFind);
36+
EndDialog(IDCANCEL);
37+
return FALSE;
38+
}
39+
}
40+
2841
CWindow cbo = GetDlgItem(IDC_DRIVES);
2942
WCHAR VolumeNameBuffer[MAX_PATH + 1];
3043
CStringW Tmp;

base/applications/cleanmgr/cleanmgr/cleanmgr.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,22 @@ class CCleanMgrModule : public ATL::CAtlExeModuleT< CCleanMgrModule >
247247
return true;
248248
}
249249

250+
static inline UINT GetWindowProcessId(_In_ HWND hWnd)
251+
{
252+
DWORD pid;
253+
return GetWindowThreadProcessId(hWnd, &pid) ? pid : 0;
254+
}
255+
256+
static BOOL CALLBACK EnumSingleInstanceCallback(_In_ HWND hWnd, _In_ LPARAM lParam)
257+
{
258+
if (::IsWindowVisible(hWnd) && (LPARAM)GetWindowProcessId(hWnd) == lParam)
259+
{
260+
::SetForegroundWindow(hWnd);
261+
return FALSE;
262+
}
263+
return TRUE;
264+
}
265+
250266
HRESULT Run(_In_ int nShowCmd) throw()
251267
{
252268
if (m_Drive == UNICODE_NULL)
@@ -257,6 +273,19 @@ class CCleanMgrModule : public ATL::CAtlExeModuleT< CCleanMgrModule >
257273
if (m_Drive == UNICODE_NULL)
258274
return E_FAIL;
259275

276+
CStringW Title;
277+
Title.Format(IDS_PROPERTIES_MAIN_TITLE, m_Drive);
278+
279+
HWND hWndInstance = ::CreateWindowExW(WS_EX_TOOLWINDOW, WC_STATIC, Title, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
280+
for (HWND hNext = NULL, hFind; (hFind = ::FindWindowExW(NULL, hNext, WC_STATIC, Title)) != NULL; hNext = hFind)
281+
{
282+
if (hFind != hWndInstance)
283+
{
284+
::EnumWindows(EnumSingleInstanceCallback, GetWindowProcessId(hFind));
285+
return S_FALSE;
286+
}
287+
}
288+
260289
CCleanupHandlerList Handlers;
261290
CEmptyVolumeCacheCallBack CacheCallBack;
262291

@@ -271,16 +300,19 @@ class CCleanMgrModule : public ATL::CAtlExeModuleT< CCleanMgrModule >
271300
psh.dwFlags = PSH_NOAPPLYNOW | PSH_USEICONID | PSH_NOCONTEXTHELP;
272301
psh.hInstance = _AtlBaseModule.GetResourceInstance();
273302
psh.pszIcon = MAKEINTRESOURCEW(IDI_CLEANMGR);
274-
CStringW Title;
275-
Title.Format(IDS_PROPERTIES_MAIN_TITLE, m_Drive);
276303
psh.pszCaption = Title;
277304
psh.nPages = _countof(hpsp);
278305
psh.phpage = hpsp;
279306

280307
if (PropertySheetW(&psh) >= 1)
281308
{
309+
::DestroyWindow(hWndInstance); // Allow new "cleanmgr /D" without waiting for these handlers
282310
Handlers.ExecuteCleanup(&CacheCallBack);
283311
}
312+
else
313+
{
314+
::DestroyWindow(hWndInstance);
315+
}
284316
return S_OK;
285317
}
286318
};

0 commit comments

Comments
 (0)