mirror of
https://github.com/reactos/reactos.git
synced 2026-05-30 23:33:24 +08:00
[CLEANMGR] Add basic cleanmgr implementation
CORE-18941
This commit is contained in:
@@ -3,6 +3,7 @@ add_subdirectory(atactl)
|
||||
add_subdirectory(cacls)
|
||||
add_subdirectory(calc)
|
||||
add_subdirectory(charmap)
|
||||
add_subdirectory(cleanmgr)
|
||||
add_subdirectory(clipbrd)
|
||||
add_subdirectory(cmdutils)
|
||||
add_subdirectory(control)
|
||||
|
||||
9
base/applications/cleanmgr/CMakeLists.txt
Normal file
9
base/applications/cleanmgr/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
project(cleanmgr)
|
||||
|
||||
# The main application
|
||||
add_subdirectory(cleanmgr)
|
||||
|
||||
# Cleanup handlers
|
||||
#add_subdirectory(dataclen) # Data Driven Cleaner
|
||||
|
||||
212
base/applications/cleanmgr/cleanmgr/CCleanupHandler.cpp
Normal file
212
base/applications/cleanmgr/cleanmgr/CCleanupHandler.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: CCleanupHandler implementation
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#include "cleanmgr.h"
|
||||
|
||||
|
||||
CCleanupHandler::CCleanupHandler(CRegKey &subKey, const CStringW &keyName, const GUID &guid)
|
||||
: hSubKey(subKey)
|
||||
, KeyName(keyName)
|
||||
, Guid(guid)
|
||||
, dwFlags(0)
|
||||
, Priority(0)
|
||||
, StateFlags(0)
|
||||
, SpaceUsed(0)
|
||||
, ShowHandler(true)
|
||||
, hIcon(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CCleanupHandler::~CCleanupHandler()
|
||||
{
|
||||
Deactivate();
|
||||
::DestroyIcon(hIcon);
|
||||
}
|
||||
|
||||
void
|
||||
CCleanupHandler::Deactivate()
|
||||
{
|
||||
if (Handler)
|
||||
{
|
||||
DWORD dwFlags = 0;
|
||||
Handler->Deactivate(&dwFlags);
|
||||
if (dwFlags & EVCF_REMOVEFROMLIST)
|
||||
UNIMPLEMENTED_DBGBREAK();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CCleanupHandler::Initialize(LPCWSTR pcwszVolume)
|
||||
{
|
||||
if (FAILED_UNEXPECTEDLY(
|
||||
::CoCreateInstance(Guid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IEmptyVolumeCache, &Handler))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwSize = sizeof(Priority);
|
||||
if (hSubKey.QueryBinaryValue(L"Priority", &Priority, &dwSize) != ERROR_SUCCESS)
|
||||
{
|
||||
if (hSubKey.QueryDWORDValue(L"Priority", Priority) != ERROR_SUCCESS)
|
||||
Priority = 200;
|
||||
}
|
||||
|
||||
dwSize = sizeof(StateFlags);
|
||||
if (hSubKey.QueryDWORDValue(L"StateFlags", StateFlags) != ERROR_SUCCESS)
|
||||
StateFlags = 0;
|
||||
|
||||
WCHAR PathBuffer[MAX_PATH] = {};
|
||||
ULONG nChars = _countof(PathBuffer);
|
||||
if (hSubKey.QueryStringValue(L"IconPath", PathBuffer, &nChars) != ERROR_SUCCESS)
|
||||
{
|
||||
CStringW Tmp;
|
||||
WCHAR GuidStr[50] = {};
|
||||
if (StringFromGUID2(Guid, GuidStr, _countof(GuidStr)))
|
||||
{
|
||||
Tmp.Format(L"CLSID\\%s\\DefaultIcon", GuidStr);
|
||||
CRegKey clsid;
|
||||
nChars = _countof(PathBuffer);
|
||||
if (clsid.Open(HKEY_CLASSES_ROOT, Tmp, KEY_READ) != ERROR_SUCCESS ||
|
||||
clsid.QueryStringValue(NULL, PathBuffer, &nChars) != ERROR_SUCCESS)
|
||||
{
|
||||
PathBuffer[0] = UNICODE_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!PathBuffer[0])
|
||||
StringCchCopyW(PathBuffer, _countof(PathBuffer), L"%systemroot%\\system32\\shell32.dll");
|
||||
|
||||
int Index = 0;
|
||||
WCHAR *ptr = wcschr(PathBuffer, L',');
|
||||
if (ptr)
|
||||
{
|
||||
*ptr++ = UNICODE_NULL;
|
||||
Index = wcstol(ptr, NULL, 10);
|
||||
}
|
||||
HICON Large, Small;
|
||||
UINT Result = ExtractIconExW(PathBuffer, Index, &Large, &Small, 1);
|
||||
if (Result < 1)
|
||||
Result = ExtractIconExW(L"%systemroot%\\system32\\shell32.dll", 0, &Large, &Small, 1);
|
||||
if (Result >= 1)
|
||||
{
|
||||
hIcon = Small;
|
||||
if (!hIcon)
|
||||
{
|
||||
hIcon = Large;
|
||||
}
|
||||
else
|
||||
{
|
||||
::DestroyIcon(Large);
|
||||
}
|
||||
}
|
||||
|
||||
// These options should come from the command line
|
||||
// dwFlags |= EVCF_SETTINGSMODE;
|
||||
// dwFlags |= EVCF_OUTOFDISKSPACE;
|
||||
|
||||
CComPtr<IEmptyVolumeCache2> spHandler2;
|
||||
HRESULT hr = Handler->QueryInterface(IID_PPV_ARG(IEmptyVolumeCache2, &spHandler2));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = spHandler2->InitializeEx(
|
||||
hSubKey, pcwszVolume, KeyName, &wszDisplayName, &wszDescription, &wszBtnText, &dwFlags);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return false;
|
||||
|
||||
// No files to clean will return S_FALSE;
|
||||
if (hr != S_OK)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Observed behavior:
|
||||
// When Initialize is called, wszDescription is actually pointing to data
|
||||
// wszDescription.AllocateBytes(0x400u);
|
||||
hr = Handler->Initialize(hSubKey, pcwszVolume, &wszDisplayName, &wszDescription, &dwFlags);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return false;
|
||||
|
||||
// No files to clean will return S_FALSE;
|
||||
if (hr != S_OK)
|
||||
return false;
|
||||
|
||||
CComPtr<IPropertyBag> spBag;
|
||||
WCHAR GuidStr[50] = {};
|
||||
nChars = _countof(GuidStr);
|
||||
if (hSubKey.QueryStringValue(L"PropertyBag", GuidStr, &nChars) == ERROR_SUCCESS)
|
||||
{
|
||||
GUID guid = {};
|
||||
if (!FAILED_UNEXPECTEDLY(CLSIDFromString(GuidStr, &guid)))
|
||||
{
|
||||
FAILED_UNEXPECTEDLY(
|
||||
CoCreateInstance(guid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPropertyBag, &spBag)));
|
||||
}
|
||||
}
|
||||
ReadProperty(L"Display", spBag, wszDisplayName);
|
||||
ReadProperty(L"Description", spBag, wszDescription);
|
||||
|
||||
if (dwFlags & EVCF_HASSETTINGS)
|
||||
{
|
||||
ReadProperty(L"AdvancedButtonText", spBag, wszBtnText);
|
||||
}
|
||||
}
|
||||
|
||||
if ((dwFlags & EVCF_ENABLEBYDEFAULT) && !(StateFlags & HANDLER_STATE_SELECTED))
|
||||
{
|
||||
StateFlags |= HANDLER_STATE_SELECTED;
|
||||
}
|
||||
|
||||
// For convenience
|
||||
if (!wszDisplayName)
|
||||
SHStrDupW(KeyName, &wszDisplayName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CCleanupHandler::ReadProperty(LPCWSTR Name, IPropertyBag *pBag, CComHeapPtr<WCHAR> &storage)
|
||||
{
|
||||
if (storage)
|
||||
return;
|
||||
|
||||
if (pBag)
|
||||
{
|
||||
CComVariant tmp;
|
||||
tmp.vt = VT_BSTR;
|
||||
HRESULT hr = pBag->Read(Name, &tmp, NULL);
|
||||
if (!FAILED_UNEXPECTEDLY(hr) && tmp.vt == VT_BSTR)
|
||||
{
|
||||
SHStrDupW(tmp.bstrVal, &storage);
|
||||
}
|
||||
}
|
||||
|
||||
if (!storage)
|
||||
{
|
||||
WCHAR TmpStr[0x200] = {};
|
||||
DWORD dwSize = _countof(TmpStr);
|
||||
|
||||
if (hSubKey.QueryStringValue(Name, TmpStr, &dwSize) == ERROR_SUCCESS)
|
||||
{
|
||||
WCHAR ResolvedStr[0x200] = {};
|
||||
SHLoadIndirectString(TmpStr, ResolvedStr, _countof(ResolvedStr), NULL);
|
||||
SHStrDupW(ResolvedStr, &storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
CCleanupHandler::HasSettings() const
|
||||
{
|
||||
return !!(dwFlags & EVCF_HASSETTINGS);
|
||||
}
|
||||
|
||||
BOOL
|
||||
CCleanupHandler::DontShowIfZero() const
|
||||
{
|
||||
return !!(dwFlags & EVCF_DONTSHOWIFZERO);
|
||||
}
|
||||
|
||||
48
base/applications/cleanmgr/cleanmgr/CCleanupHandler.hpp
Normal file
48
base/applications/cleanmgr/cleanmgr/CCleanupHandler.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: CCleanupHandler definition
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#define HANDLER_STATE_SELECTED 1
|
||||
|
||||
|
||||
struct CCleanupHandler
|
||||
{
|
||||
CCleanupHandler(CRegKey &subKey, const CStringW &keyName, const GUID &guid);
|
||||
~CCleanupHandler();
|
||||
|
||||
void Deactivate();
|
||||
|
||||
bool
|
||||
Initialize(LPCWSTR pcwszVolume);
|
||||
|
||||
void
|
||||
ReadProperty(LPCWSTR Name, IPropertyBag *pBag, CComHeapPtr<WCHAR> &storage);
|
||||
|
||||
BOOL
|
||||
HasSettings() const;
|
||||
|
||||
BOOL
|
||||
DontShowIfZero() const;
|
||||
|
||||
CRegKey hSubKey;
|
||||
CStringW KeyName;
|
||||
GUID Guid;
|
||||
|
||||
CComHeapPtr<WCHAR> wszDisplayName;
|
||||
CComHeapPtr<WCHAR> wszDescription;
|
||||
CComHeapPtr<WCHAR> wszBtnText;
|
||||
|
||||
CStringW IconPath;
|
||||
DWORD dwFlags;
|
||||
DWORD Priority;
|
||||
DWORD StateFlags;
|
||||
|
||||
CComPtr<IEmptyVolumeCache> Handler;
|
||||
DWORDLONG SpaceUsed;
|
||||
bool ShowHandler;
|
||||
HICON hIcon;
|
||||
};
|
||||
|
||||
163
base/applications/cleanmgr/cleanmgr/CCleanupHandlerList.cpp
Normal file
163
base/applications/cleanmgr/cleanmgr/CCleanupHandlerList.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: CCleanupHandlerList implementation
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#include "cleanmgr.h"
|
||||
|
||||
void CCleanupHandlerList::LoadHandlers(WCHAR Drive)
|
||||
{
|
||||
m_DriveStr.Format(L"%c:", Drive);
|
||||
|
||||
CRegKey VolumeCaches;
|
||||
if (VolumeCaches.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VolumeCaches", KEY_READ) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
LONG ItemIndex = 0;
|
||||
WCHAR szKeyName[MAX_PATH];
|
||||
|
||||
WCHAR wszVolume[] = { Drive, L':', L'\\', UNICODE_NULL };
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
DWORD dwSize = _countof(szKeyName);
|
||||
if (VolumeCaches.EnumKey(ItemIndex++, szKeyName, &dwSize) != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
CRegKey hSubKey;
|
||||
if (hSubKey.Open(VolumeCaches, szKeyName, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
WCHAR GuidStr[50] = {};
|
||||
dwSize = _countof(GuidStr);
|
||||
if (hSubKey.QueryStringValue(NULL, GuidStr, &dwSize) != ERROR_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GUID guid = {};
|
||||
if (FAILED_UNEXPECTEDLY(CLSIDFromString(GuidStr, &guid)))
|
||||
continue;
|
||||
|
||||
CCleanupHandler* handler = new CCleanupHandler(hSubKey, szKeyName, guid);
|
||||
|
||||
if (!handler->Initialize(wszVolume))
|
||||
{
|
||||
delete handler;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_Handlers.AddTail(handler);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort handlers
|
||||
BOOL fChanged = m_Handlers.GetCount() > 0;
|
||||
while (fChanged)
|
||||
{
|
||||
fChanged = FALSE;
|
||||
|
||||
for (size_t n = 0; n < m_Handlers.GetCount() - 1; n++)
|
||||
{
|
||||
POSITION leftPos = m_Handlers.FindIndex(n);
|
||||
POSITION rightPos = m_Handlers.FindIndex(n+1);
|
||||
CCleanupHandler* left = m_Handlers.GetAt(leftPos);
|
||||
CCleanupHandler* right = m_Handlers.GetAt(rightPos);
|
||||
|
||||
if (right->Priority < left->Priority)
|
||||
{
|
||||
m_Handlers.SwapElements(leftPos, rightPos);
|
||||
fChanged = TRUE;
|
||||
}
|
||||
else if (right->Priority == left->Priority)
|
||||
{
|
||||
CStringW leftStr(left->wszDisplayName);
|
||||
if (leftStr.Compare(right->wszDisplayName) > 0)
|
||||
{
|
||||
m_Handlers.SwapElements(leftPos, rightPos);
|
||||
fChanged = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DWORDLONG
|
||||
CCleanupHandlerList::ScanDrive(IEmptyVolumeCacheCallBack *picb)
|
||||
{
|
||||
CProgressDlg progress;
|
||||
CString Caption;
|
||||
Caption.Format(IDS_CALCULATING, m_DriveStr.GetString());
|
||||
CStringW Title(MAKEINTRESOURCE(IDS_DISK_CLEANUP));
|
||||
progress.Start((DWORD)m_Handlers.GetCount(), Title, Caption);
|
||||
int ItemIndex = 0;
|
||||
DWORDLONG TotalSpaceUsed = 0;
|
||||
ForEach(
|
||||
[&](CCleanupHandler *current)
|
||||
{
|
||||
Caption.Format(IDS_SCANNING, current->wszDisplayName.m_pData);
|
||||
progress.Step(++ItemIndex, Caption);
|
||||
|
||||
HRESULT hr = current->Handler->GetSpaceUsed(¤t->SpaceUsed, picb);
|
||||
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
current->ShowHandler = false;
|
||||
current->StateFlags &= ~HANDLER_STATE_SELECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (current->SpaceUsed == 0 && current->DontShowIfZero())
|
||||
{
|
||||
current->ShowHandler = false;
|
||||
current->StateFlags &= ~HANDLER_STATE_SELECTED;
|
||||
}
|
||||
TotalSpaceUsed += current->SpaceUsed;
|
||||
});
|
||||
progress.Stop();
|
||||
|
||||
return TotalSpaceUsed;
|
||||
}
|
||||
|
||||
void
|
||||
CCleanupHandlerList::ExecuteCleanup(IEmptyVolumeCacheCallBack *picb)
|
||||
{
|
||||
CProgressDlg progress;
|
||||
CString Caption;
|
||||
Caption.Format(IDS_CLEANING_CAPTION, m_DriveStr.GetString());
|
||||
|
||||
DWORD TotalSelected = 0;
|
||||
ForEach(
|
||||
[&](CCleanupHandler *current)
|
||||
{
|
||||
if (current->StateFlags & HANDLER_STATE_SELECTED)
|
||||
TotalSelected++;
|
||||
});
|
||||
|
||||
CStringW Title(MAKEINTRESOURCE(IDS_DISK_CLEANUP));
|
||||
progress.Start(TotalSelected, Title, Caption);
|
||||
int ItemIndex = 0;
|
||||
ForEach(
|
||||
[&](CCleanupHandler *current)
|
||||
{
|
||||
if (!(current->StateFlags & HANDLER_STATE_SELECTED))
|
||||
return;
|
||||
|
||||
Caption.Format(IDS_CLEANING, current->wszDisplayName.m_pData);
|
||||
progress.Step(++ItemIndex, Caption);
|
||||
|
||||
// If there is nothing to clean, we might get STG_E_NOMOREFILES
|
||||
if (current->SpaceUsed > 0)
|
||||
{
|
||||
HRESULT hr = current->Handler->Purge(-1, picb);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
}
|
||||
});
|
||||
progress.Stop();
|
||||
}
|
||||
31
base/applications/cleanmgr/cleanmgr/CCleanupHandlerList.hpp
Normal file
31
base/applications/cleanmgr/cleanmgr/CCleanupHandlerList.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: CCleanupHandlerList definition
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
|
||||
class CCleanupHandlerList
|
||||
{
|
||||
private:
|
||||
CAtlList<CCleanupHandler *> m_Handlers;
|
||||
CStringW m_DriveStr;
|
||||
|
||||
public:
|
||||
|
||||
void LoadHandlers(WCHAR Drive);
|
||||
DWORDLONG ScanDrive(IEmptyVolumeCacheCallBack* picb);
|
||||
void ExecuteCleanup(IEmptyVolumeCacheCallBack *picb);
|
||||
|
||||
template<typename Fn>
|
||||
void ForEach(Fn callback)
|
||||
{
|
||||
for (POSITION it = m_Handlers.GetHeadPosition(); it; m_Handlers.GetNext(it))
|
||||
{
|
||||
CCleanupHandler *current = m_Handlers.GetAt(it);
|
||||
|
||||
callback(current);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: CEmptyVolumeCacheCallBack definition / implementation
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
|
||||
// We don't really use this, but some windows handlers crash without it
|
||||
struct CEmptyVolumeCacheCallBack
|
||||
: public IEmptyVolumeCacheCallBack
|
||||
{
|
||||
|
||||
STDMETHOD_(ULONG, AddRef)() throw()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
STDMETHOD_(ULONG, Release)() throw()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
STDMETHOD(QueryInterface)(
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void** ppvObject) throw()
|
||||
{
|
||||
if (riid == IID_IUnknown || riid == IID_IEmptyVolumeCacheCallBack)
|
||||
{
|
||||
*ppvObject = (IUnknown*)this;
|
||||
return S_OK;
|
||||
}
|
||||
*ppvObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP ScanProgress(
|
||||
_In_ DWORDLONG dwlSpaceUsed,
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ LPCWSTR pcwszStatus) override
|
||||
{
|
||||
DPRINT("dwlSpaceUsed: %lld, dwFlags: %x\n", dwlSpaceUsed, dwFlags);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP PurgeProgress(
|
||||
_In_ DWORDLONG dwlSpaceFreed,
|
||||
_In_ DWORDLONG dwlSpaceToFree,
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ LPCWSTR pcwszStatus) override
|
||||
{
|
||||
DPRINT("dwlSpaceFreed: %lld, dwlSpaceToFree: %lld, dwFlags: %x\n", dwlSpaceFreed, dwlSpaceToFree, dwFlags);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
19
base/applications/cleanmgr/cleanmgr/CMakeLists.txt
Normal file
19
base/applications/cleanmgr/cleanmgr/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
add_executable(cleanmgr
|
||||
cleanmgr.cpp
|
||||
cleanmgr.h
|
||||
cleanmgr.rc
|
||||
resource.h
|
||||
CEmptyVolumeCacheCallBack.hpp
|
||||
CProgressDlg.hpp
|
||||
CSelectDriveDlg.cpp
|
||||
CCleanupHandler.cpp
|
||||
CCleanupHandler.hpp
|
||||
CCleanupHandlerList.cpp
|
||||
CCleanupHandlerList.hpp
|
||||
)
|
||||
set_module_type(cleanmgr win32gui UNICODE)
|
||||
target_link_libraries(cleanmgr uuid cpprt atl_classes)
|
||||
add_importlibs(cleanmgr shlwapi oleaut32 ole32 shell32 comctl32 user32 advapi32 msvcrt kernel32 ntdll)
|
||||
add_dependencies(cleanmgr psdk)
|
||||
add_cd_file(TARGET cleanmgr DESTINATION reactos/system32 FOR all)
|
||||
50
base/applications/cleanmgr/cleanmgr/CProgressDlg.hpp
Normal file
50
base/applications/cleanmgr/cleanmgr/CProgressDlg.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Progress dialog implementation
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class CProgressDlg
|
||||
{
|
||||
CComPtr<IProgressDialog> m_spProgress;
|
||||
DWORD m_dwTotal = 0;
|
||||
public:
|
||||
|
||||
~CProgressDlg()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
|
||||
void Start(DWORD dwTotalSteps, LPCWSTR Title, LPCWSTR Text)
|
||||
{
|
||||
HRESULT hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC, IID_PPV_ARG(IProgressDialog, &m_spProgress));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
m_dwTotal = dwTotalSteps;
|
||||
|
||||
m_spProgress->SetTitle(Title);
|
||||
m_spProgress->SetLine(2, Text, TRUE, NULL);
|
||||
m_spProgress->StartProgressDialog(NULL, NULL, PROGDLG_NOMINIMIZE, NULL);
|
||||
m_spProgress->SetProgress(0, m_dwTotal);
|
||||
}
|
||||
|
||||
void Step(DWORD dwProgress, LPCWSTR Text)
|
||||
{
|
||||
m_spProgress->SetProgress(dwProgress, m_dwTotal);
|
||||
m_spProgress->SetLine(1, Text, TRUE, NULL);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
if (m_spProgress)
|
||||
{
|
||||
m_spProgress->StopProgressDialog();
|
||||
m_spProgress.Release();
|
||||
}
|
||||
}
|
||||
};
|
||||
67
base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp
Normal file
67
base/applications/cleanmgr/cleanmgr/CSelectDriveDlg.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Drive selection dialog
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#include "cleanmgr.h"
|
||||
|
||||
class CSelectDriveDlg : public CDialogImpl<CSelectDriveDlg>
|
||||
{
|
||||
public:
|
||||
enum { IDD = IDD_SELECTDRIVE };
|
||||
|
||||
BEGIN_MSG_MAP(CSelectDriveDlg)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_ID_HANDLER(IDOK, OnEndDialog)
|
||||
COMMAND_ID_HANDLER(IDCANCEL, OnEndDialog)
|
||||
END_MSG_MAP()
|
||||
|
||||
CSelectDriveDlg()
|
||||
:m_SelectedDrive(UNICODE_NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
|
||||
{
|
||||
CWindow cbo = GetDlgItem(IDC_DRIVES);
|
||||
WCHAR VolumeNameBuffer[MAX_PATH + 1];
|
||||
CStringW Tmp;
|
||||
for (WCHAR Drive = 'A'; Drive <= 'Z'; ++Drive)
|
||||
{
|
||||
WCHAR RootPathName[] = { Drive,':','\\',0 };
|
||||
UINT Type = GetDriveTypeW(RootPathName);
|
||||
if (Type == DRIVE_FIXED)
|
||||
{
|
||||
GetVolumeInformationW(RootPathName, VolumeNameBuffer, _countof(VolumeNameBuffer), 0, 0, 0, 0, 0);
|
||||
Tmp.Format(L"%s (%.2s)", VolumeNameBuffer, RootPathName);
|
||||
|
||||
int index = (int)cbo.SendMessage(CB_ADDSTRING, NULL, (LPARAM)Tmp.GetString());
|
||||
cbo.SendMessage(CB_SETITEMDATA, index, Drive);
|
||||
}
|
||||
}
|
||||
cbo.SendMessage(CB_SETCURSEL, 0);
|
||||
return 1;
|
||||
}
|
||||
LRESULT OnEndDialog(WORD, WORD wID, HWND, BOOL&)
|
||||
{
|
||||
CWindow cbo = GetDlgItem(IDC_DRIVES);
|
||||
m_SelectedDrive = (WCHAR)cbo.SendMessage(CB_GETITEMDATA, cbo.SendMessage(CB_GETCURSEL));
|
||||
EndDialog(wID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WCHAR m_SelectedDrive;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
SelectDrive(WCHAR &Drive)
|
||||
{
|
||||
CSelectDriveDlg dlgSelectDrive;
|
||||
if (dlgSelectDrive.DoModal() == IDOK)
|
||||
{
|
||||
Drive = dlgSelectDrive.m_SelectedDrive;
|
||||
}
|
||||
}
|
||||
296
base/applications/cleanmgr/cleanmgr/cleanmgr.cpp
Normal file
296
base/applications/cleanmgr/cleanmgr/cleanmgr.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Disk cleanup entrypoint
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#include "cleanmgr.h"
|
||||
|
||||
// for listview with extend style LVS_EX_CHECKBOXES, State image 1 is the unchecked box, and state image 2 is the
|
||||
// checked box. see this: https://docs.microsoft.com/en-us/windows/win32/controls/extended-list-view-styles
|
||||
#define STATEIMAGETOINDEX(x) (((x)&LVIS_STATEIMAGEMASK) >> 12)
|
||||
#define STATEIMAGE_UNCHECKED 1
|
||||
#define STATEIMAGE_CHECKED 2
|
||||
|
||||
|
||||
struct CCleanMgrProperties :
|
||||
public CPropertyPageImpl<CCleanMgrProperties>
|
||||
{
|
||||
enum { IDD = IDD_PROPERTIES_MAIN };
|
||||
CWindow m_HandlerListControl;
|
||||
WCHAR m_Drive;
|
||||
DWORDLONG m_TotalSpaceUsed;
|
||||
CCleanupHandlerList* m_HandlerList;
|
||||
bool m_IgnoreChanges = true;
|
||||
|
||||
|
||||
CCleanMgrProperties(WCHAR Drive, DWORDLONG TotalSpaceUsed, CCleanupHandlerList *handlerList)
|
||||
: m_Drive(Drive)
|
||||
, m_TotalSpaceUsed(TotalSpaceUsed)
|
||||
, m_HandlerList(handlerList)
|
||||
{
|
||||
}
|
||||
|
||||
int OnApply()
|
||||
{
|
||||
CStringW Title(MAKEINTRESOURCE(IDS_DISK_CLEANUP));
|
||||
CStringW Text(MAKEINTRESOURCE(IDS_CONFIRM_DELETE));
|
||||
|
||||
if (MessageBoxW(Text, Title, MB_YESNO | MB_ICONQUESTION) != IDYES)
|
||||
return PSNRET_INVALID;
|
||||
|
||||
return PSNRET_NOERROR;
|
||||
}
|
||||
|
||||
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
HICON hIcon = (HICON)::LoadImageW(
|
||||
_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCEW(IDI_CLEANMGR), IMAGE_ICON, 0, 0,
|
||||
LR_DEFAULTSIZE | LR_SHARED);
|
||||
SendDlgItemMessage(IDC_DISKICON, STM_SETICON, (WPARAM)hIcon);
|
||||
|
||||
m_HandlerListControl = GetDlgItem(IDC_HANDLERLIST);
|
||||
RECT rc;
|
||||
m_HandlerListControl.GetClientRect(&rc);
|
||||
rc.right -= GetSystemMetrics(SM_CXVSCROLL);
|
||||
|
||||
LV_COLUMN column = {};
|
||||
column.mask = LVCF_FMT | LVCF_WIDTH;
|
||||
column.fmt = LVCFMT_LEFT;
|
||||
column.cx = rc.right * 80 / 100;
|
||||
ListView_InsertColumn(m_HandlerListControl, 0, &column);
|
||||
column.fmt = LVCFMT_RIGHT;
|
||||
column.cx = rc.right * 20 / 100;
|
||||
|
||||
ListView_InsertColumn(m_HandlerListControl, 1, &column);
|
||||
HIMAGELIST hImagelist = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 1, 1);
|
||||
ListView_SetImageList(m_HandlerListControl, hImagelist, LVSIL_SMALL);
|
||||
|
||||
ListView_SetExtendedListViewStyleEx(m_HandlerListControl, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
|
||||
|
||||
m_HandlerList->ForEach(
|
||||
[&](CCleanupHandler *current)
|
||||
{
|
||||
if (!current->ShowHandler)
|
||||
return;
|
||||
|
||||
LV_ITEM item = {};
|
||||
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
item.lParam = (LPARAM)current;
|
||||
item.pszText = (LPWSTR)current->wszDisplayName;
|
||||
item.iItem = ListView_GetItemCount(m_HandlerListControl);
|
||||
item.iImage = ImageList_AddIcon(hImagelist, current->hIcon);
|
||||
item.iItem = ListView_InsertItem(m_HandlerListControl, &item);
|
||||
ListView_SetCheckState(
|
||||
m_HandlerListControl, item.iItem, !!(current->StateFlags & HANDLER_STATE_SELECTED));
|
||||
|
||||
item.mask = LVIF_TEXT;
|
||||
WCHAR ByteSize[100] = {};
|
||||
StrFormatByteSizeW(current->SpaceUsed, ByteSize, _countof(ByteSize));
|
||||
ListView_SetItemText(m_HandlerListControl, item.iItem, 1, ByteSize);
|
||||
});
|
||||
|
||||
// Now we should start responding to changes
|
||||
m_IgnoreChanges = false;
|
||||
|
||||
// Select the first item
|
||||
ListView_SetItemState(m_HandlerListControl, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
||||
|
||||
UpdateSpaceUsed();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CCleanupHandler* GetHandler(int Index)
|
||||
{
|
||||
LVITEMW item = {};
|
||||
item.iItem = Index;
|
||||
if (item.iItem >= 0)
|
||||
{
|
||||
item.mask = LVIF_PARAM;
|
||||
ListView_GetItem(m_HandlerListControl, &item);
|
||||
return (CCleanupHandler*)item.lParam;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
LRESULT OnDetails(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
|
||||
{
|
||||
CCleanupHandler *handler = GetHandler(ListView_GetNextItem(m_HandlerListControl, -1, LVIS_FOCUSED));
|
||||
if (handler)
|
||||
{
|
||||
handler->Handler->ShowProperties(m_hWnd);
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
LRESULT OnHandlerItemchanged(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
|
||||
{
|
||||
if (idCtrl == IDC_HANDLERLIST)
|
||||
{
|
||||
// We are still initializing, don't respond to changes just yet!
|
||||
if (m_IgnoreChanges)
|
||||
return 0L;
|
||||
|
||||
LPNMLISTVIEW pnic = (LPNMLISTVIEW)pnmh;
|
||||
|
||||
// We only care about state changes
|
||||
if (!(pnic->uChanged & LVIF_STATE))
|
||||
return 0L;
|
||||
|
||||
|
||||
INT ItemIndex = pnic->iItem;
|
||||
if (ItemIndex == -1 || ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
|
||||
bool GotSelected = (pnic->uNewState & LVIS_SELECTED) && !(pnic->uOldState & LVIS_SELECTED);
|
||||
if (GotSelected)
|
||||
{
|
||||
CWindow DetailsButton = GetDlgItem(IDC_DETAILS);
|
||||
CCleanupHandler* handler = (CCleanupHandler*)pnic->lParam;
|
||||
|
||||
SetDlgItemText(IDC_DESCRIPTION, handler->wszDescription ? handler->wszDescription : L"");
|
||||
if (handler->HasSettings())
|
||||
{
|
||||
DetailsButton.ShowWindow(SW_SHOW);
|
||||
DetailsButton.SetWindowText(handler->wszBtnText);
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailsButton.ShowWindow(SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
int iOldState = STATEIMAGETOINDEX(pnic->uOldState);
|
||||
int iNewState = STATEIMAGETOINDEX(pnic->uNewState);
|
||||
|
||||
if ((iOldState ^ iNewState) == (STATEIMAGE_UNCHECKED ^ STATEIMAGE_CHECKED))
|
||||
{
|
||||
CCleanupHandler* handler = (CCleanupHandler*)pnic->lParam;
|
||||
if (iNewState == STATEIMAGE_CHECKED)
|
||||
handler->StateFlags |= HANDLER_STATE_SELECTED;
|
||||
else
|
||||
handler->StateFlags &= ~HANDLER_STATE_SELECTED;
|
||||
UpdateSpaceUsed();
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
void UpdateSpaceUsed()
|
||||
{
|
||||
CStringW tmp;
|
||||
WCHAR ByteSize[100];
|
||||
StrFormatByteSizeW(m_TotalSpaceUsed, ByteSize, _countof(ByteSize));
|
||||
|
||||
tmp.Format(IDS_TOTAL_CLEANABLE_CAPTION, ByteSize, m_Drive);
|
||||
SetDlgItemText(IDC_TOTAL_CLEANABLE, tmp);
|
||||
|
||||
DWORDLONG SelectedGained = 0;
|
||||
|
||||
m_HandlerList->ForEach(
|
||||
[&](CCleanupHandler *current)
|
||||
{
|
||||
if (current->StateFlags & HANDLER_STATE_SELECTED)
|
||||
{
|
||||
SelectedGained += current->SpaceUsed;
|
||||
}
|
||||
});
|
||||
|
||||
StrFormatByteSizeW(SelectedGained, ByteSize, _countof(ByteSize));
|
||||
SetDlgItemText(IDC_SELECTED_GAINED, ByteSize);
|
||||
}
|
||||
|
||||
BEGIN_MSG_MAP(CCleanMgrProperties)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_ID_HANDLER(IDC_DETAILS, OnDetails)
|
||||
NOTIFY_HANDLER(IDC_HANDLERLIST, LVN_ITEMCHANGED, OnHandlerItemchanged)
|
||||
CHAIN_MSG_MAP(CPropertyPageImpl<CCleanMgrProperties>) // Allow the default handler to call 'OnApply' etc
|
||||
END_MSG_MAP()
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CCleanMgrModule : public ATL::CAtlExeModuleT< CCleanMgrModule >
|
||||
{
|
||||
public:
|
||||
WCHAR m_Drive = UNICODE_NULL;
|
||||
|
||||
bool ParseCommandLine(
|
||||
_In_z_ LPCTSTR lpCmdLine,
|
||||
_Out_ HRESULT* pnRetCode) throw()
|
||||
{
|
||||
int argc = 0;
|
||||
CLocalPtr<LPWSTR> argv(CommandLineToArgvW(lpCmdLine, &argc));
|
||||
|
||||
for (int n = 1; n < argc; ++n)
|
||||
{
|
||||
if ((argv[n][0] == '/' || argv[n][0] == '-') && towlower(argv[n][1]) == 'd')
|
||||
{
|
||||
if (iswalpha(argv[n][2]))
|
||||
{
|
||||
m_Drive = towupper(argv[n][2]);
|
||||
continue;
|
||||
}
|
||||
if ((n + 1) < argc)
|
||||
{
|
||||
m_Drive = towupper(argv[n + 1][0]);
|
||||
++n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pnRetCode = S_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT Run(_In_ int nShowCmd) throw()
|
||||
{
|
||||
if (m_Drive == UNICODE_NULL)
|
||||
{
|
||||
SelectDrive(m_Drive);
|
||||
}
|
||||
|
||||
if (m_Drive == UNICODE_NULL)
|
||||
return E_FAIL;
|
||||
|
||||
CCleanupHandlerList Handlers;
|
||||
CEmptyVolumeCacheCallBack CacheCallBack;
|
||||
|
||||
Handlers.LoadHandlers(m_Drive);
|
||||
DWORDLONG TotalSpaceUsed = Handlers.ScanDrive(&CacheCallBack);
|
||||
|
||||
CCleanMgrProperties cleanMgr(m_Drive, TotalSpaceUsed, &Handlers);
|
||||
HPROPSHEETPAGE hpsp[1] = { cleanMgr.Create() };
|
||||
|
||||
PROPSHEETHEADERW psh = { };
|
||||
psh.dwSize = sizeof(psh);
|
||||
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)
|
||||
{
|
||||
Handlers.ExecuteCleanup(&CacheCallBack);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
CCleanMgrModule _AtlModule;
|
||||
|
||||
|
||||
|
||||
extern "C" int WINAPI wWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
|
||||
LPWSTR /*lpCmdLine*/, int nShowCmd)
|
||||
{
|
||||
return _AtlModule.WinMain(nShowCmd);
|
||||
}
|
||||
66
base/applications/cleanmgr/cleanmgr/cleanmgr.h
Normal file
66
base/applications/cleanmgr/cleanmgr/cleanmgr.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Main header file
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef STRICT
|
||||
#define STRICT
|
||||
#endif
|
||||
|
||||
#define _ATL_APARTMENT_THREADED
|
||||
#define _ATL_NO_AUTOMATIC_NAMESPACE
|
||||
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||
#define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW
|
||||
|
||||
#define _FORCENAMELESSUNION
|
||||
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <atlcom.h>
|
||||
#include <atlstr.h>
|
||||
#include <strsafe.h>
|
||||
#include <emptyvc.h>
|
||||
#include <atlcoll.h>
|
||||
|
||||
|
||||
using namespace ATL;
|
||||
|
||||
#define NDEBUG
|
||||
#include <reactos/debug.h>
|
||||
#include <reactos/shellutils.h>
|
||||
#include <ui/rosdlgs.h>
|
||||
|
||||
|
||||
template <class T> class CLocalPtr
|
||||
: public CHeapPtr<T, CLocalAllocator>
|
||||
{
|
||||
public:
|
||||
CLocalPtr() throw()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CLocalPtr(_In_ T* pData) throw() :
|
||||
CHeapPtr<T, CLocalAllocator>(pData)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#include "resource.h"
|
||||
#include "CProgressDlg.hpp"
|
||||
#include "CCleanupHandler.hpp"
|
||||
#include "CCleanupHandlerList.hpp"
|
||||
#include "CEmptyVolumeCacheCallBack.hpp"
|
||||
|
||||
// CSelectDriveDlg.cpp
|
||||
void
|
||||
SelectDrive(WCHAR &Drive);
|
||||
64
base/applications/cleanmgr/cleanmgr/cleanmgr.rc
Normal file
64
base/applications/cleanmgr/cleanmgr/cleanmgr.rc
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Resources
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#include <windef.h>
|
||||
#include <winuser.h>
|
||||
#include <commctrl.h>
|
||||
#include "resource.h"
|
||||
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Disk Cleanup"
|
||||
#define REACTOS_STR_INTERNAL_NAME "cleanmgr"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "cleanmgr.exe"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
#include <reactos/manifest_exe.rc>
|
||||
|
||||
IDI_CLEANMGR ICON "resources/cleanmgr.ico"
|
||||
|
||||
#pragma code_page(65001)
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_PROPERTIES_MAIN_TITLE "Disk Cleanup for (%c:)"
|
||||
IDS_TOTAL_CLEANABLE_CAPTION "You can use Disk Cleanup to free up to %s of disk space on (%c:)."
|
||||
IDS_DISK_CLEANUP "Disk Cleanup"
|
||||
IDS_CONFIRM_DELETE "Are you sure you want to delete these files permanently?"
|
||||
IDS_CALCULATING "Disk Cleanup is calculating how much space can be gained on (%s)."
|
||||
IDS_SCANNING "Scanning: %s"
|
||||
IDS_CLEANING_CAPTION "Disk Cleanup is cleaning up files on %s."
|
||||
IDS_CLEANING "Cleaning: %s"
|
||||
END
|
||||
|
||||
IDD_PROPERTIES_MAIN DIALOGEX 0, 0, 235, 215
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD | WS_DISABLED | WS_CAPTION
|
||||
CAPTION "Disk Cleanup"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "",IDC_DISKICON,"Static",SS_ICON,6,6,20,20
|
||||
LTEXT "You can use Disk Cleanup to free up to 0.0MB of disk space on drive C.",IDC_TOTAL_CLEANABLE,36,6,192,18
|
||||
LTEXT "Files to delete:",IDC_STATIC,6,30,222,8
|
||||
CONTROL "",IDC_HANDLERLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,6,42,222,66
|
||||
LTEXT "Total amount of disk space gained:",IDC_STATIC,6,114,144,8
|
||||
RTEXT "",IDC_SELECTED_GAINED,156,114,73,8
|
||||
GROUPBOX "Description",IDC_STATIC,6,126,222,84
|
||||
LTEXT "",IDC_DESCRIPTION,12,138,210,54
|
||||
PUSHBUTTON "Details...",IDC_DETAILS,150,192,74,14
|
||||
END
|
||||
|
||||
IDD_SELECTDRIVE DIALOGEX 0, 0, 177, 74
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Disk Cleanup - Select Drive"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,30,48,50,14
|
||||
PUSHBUTTON "E&xit",IDCANCEL,96,48,50,14
|
||||
LTEXT "Select the drive to clean up.",IDC_STATIC,12,6,150,8
|
||||
COMBOBOX IDC_DRIVES,12,24,150,90,CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
30
base/applications/cleanmgr/cleanmgr/resource.h
Normal file
30
base/applications/cleanmgr/cleanmgr/resource.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Disk Cleanup
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Resource definitions
|
||||
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
|
||||
*/
|
||||
|
||||
#define IDC_STATIC -1
|
||||
|
||||
#define IDI_CLEANMGR 100
|
||||
|
||||
#define IDD_PROPERTIES_MAIN 200
|
||||
#define IDC_DISKICON 201
|
||||
#define IDC_TOTAL_CLEANABLE 202
|
||||
#define IDC_HANDLERLIST 203
|
||||
#define IDC_SELECTED_GAINED 204
|
||||
#define IDC_DESCRIPTION 205
|
||||
#define IDC_DETAILS 206
|
||||
|
||||
#define IDD_SELECTDRIVE 220
|
||||
#define IDC_DRIVES 221
|
||||
|
||||
#define IDS_PROPERTIES_MAIN_TITLE 1000
|
||||
#define IDS_TOTAL_CLEANABLE_CAPTION 1001
|
||||
#define IDS_DISK_CLEANUP 1002
|
||||
#define IDS_CONFIRM_DELETE 1003
|
||||
#define IDS_CALCULATING 1004
|
||||
#define IDS_SCANNING 1005
|
||||
#define IDS_CLEANING_CAPTION 1006
|
||||
#define IDS_CLEANING 1007
|
||||
BIN
base/applications/cleanmgr/cleanmgr/resources/cleanmgr.ico
Normal file
BIN
base/applications/cleanmgr/cleanmgr/resources/cleanmgr.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Reference in New Issue
Block a user