windows-nt/Source/XPSP1/NT/shell/ext/cscui/volclean.cpp
2020-09-26 16:20:57 +08:00

283 lines
8.5 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: volclean.cpp
//
// Authors;
// Jeff Saathoff (jeffreys)
//
// Notes;
// CSC disk cleanup implementation (IEmptyVolumeCache)
//--------------------------------------------------------------------------
#include "pch.h"
#include "folder.h"
int
CoTaskLoadString(HINSTANCE hInstance, UINT idString, LPWSTR *ppwsz)
{
int nResult = 0;
*ppwsz = NULL;
ULONG cchString = SizeofStringResource(hInstance, idString);
if (cchString)
{
cchString++; // for NULL
*ppwsz = (LPWSTR)CoTaskMemAlloc(cchString * sizeof(WCHAR));
if (*ppwsz)
nResult = LoadStringW(hInstance, idString, *ppwsz, cchString);
}
return nResult;
}
///////////////////////////////////////////////////////////////////////////////
// //
// IClassFactory::CreateInstance support //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI
CCscVolumeCleaner::CreateInstance(REFIID riid, LPVOID *ppv)
{
return Create(FALSE, riid, ppv);
}
HRESULT WINAPI
CCscVolumeCleaner::CreateInstance2(REFIID riid, LPVOID *ppv)
{
return Create(TRUE, riid, ppv);
}
HRESULT WINAPI
CCscVolumeCleaner::Create(BOOL fPinned, REFIID riid, LPVOID *ppv)
{
HRESULT hr;
CCscVolumeCleaner *pThis = new CCscVolumeCleaner(fPinned);
if (pThis)
{
hr = pThis->QueryInterface(riid, ppv);
pThis->Release();
}
else
hr = E_OUTOFMEMORY;
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// //
// IUnknown implementation //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CCscVolumeCleaner::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(CCscVolumeCleaner, IEmptyVolumeCache),
QITABENT(CCscVolumeCleaner, IEmptyVolumeCache2),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) CCscVolumeCleaner::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CCscVolumeCleaner::Release()
{
if (InterlockedDecrement(&m_cRef))
return m_cRef;
delete this;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// //
// IEmptyVolumeCache implementation //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CCscVolumeCleaner::Initialize(HKEY /*hkRegKey*/,
LPCWSTR pcwszVolume,
LPWSTR *ppwszDisplayName,
LPWSTR *ppwszDescription,
LPDWORD pdwFlags)
{
BOOL bSettingsMode;
CSCSPACEUSAGEINFO sui = {0};
USES_CONVERSION;
TraceEnter(TRACE_SHELLEX, "IEmptyVolumeCache::Initialize");
TraceAssert(pcwszVolume != NULL);
TraceAssert(ppwszDisplayName != NULL);
TraceAssert(ppwszDescription != NULL);
TraceAssert(pdwFlags != NULL);
TraceAssert(IsCSCEnabled());
bSettingsMode = (BOOL)((*pdwFlags) & EVCF_SETTINGSMODE);
*ppwszDisplayName = NULL;
*ppwszDescription = NULL;
*pdwFlags = 0;
// If this isn't the volume containing the CSC database, then we have
// nothing to free. Note that we don't use the space usage data
// returned here.
GetCscSpaceUsageInfo(&sui);
if (!bSettingsMode && !PathIsSameRoot(sui.szVolume, W2CT(pcwszVolume)))
TraceLeaveResult(S_FALSE);
m_PurgerSel.SetFlags(m_fPinned ? PURGE_FLAG_PINNED : (PURGE_FLAG_UNPINNED | PURGE_IGNORE_ACCESS));
m_pPurger = new CCachePurger(m_PurgerSel,
CachePurgerCallback,
this);
if (!m_pPurger)
TraceLeaveResult(E_FAIL);
// If we're freeing auto-cached files, we want to be enabled by default,
// but not if we're freeing pinned files.
*pdwFlags = 0;
if (!m_fPinned)
*pdwFlags = EVCF_ENABLEBYDEFAULT | EVCF_ENABLEBYDEFAULT_AUTO;
// If policy allows, turn on the "Details" button which launches the viewer
if (!CConfig::GetSingleton().NoCacheViewer())
*pdwFlags |= EVCF_HASSETTINGS;
// Load the display name string
CoTaskLoadString(g_hInstance,
m_fPinned ? IDS_APPLICATION : IDS_DISKCLEAN_DISPLAY,
ppwszDisplayName);
// Load the description string
CoTaskLoadString(g_hInstance,
m_fPinned ? IDS_DISKCLEAN_PIN_DESCRIPTION : IDS_DISKCLEAN_DESCRIPTION,
ppwszDescription);
TraceLeaveResult(S_OK);
}
STDMETHODIMP
CCscVolumeCleaner::GetSpaceUsed(DWORDLONG *pdwlSpaceUsed,
LPEMPTYVOLUMECACHECALLBACK picb)
{
m_pDiskCleaner = picb;
m_pPurger->Scan();
if (m_pDiskCleaner)
m_pDiskCleaner->ScanProgress(m_dwlSpaceToFree,
EVCCBF_LASTNOTIFICATION,
NULL);
*pdwlSpaceUsed = m_dwlSpaceToFree;
return S_OK;
}
STDMETHODIMP
CCscVolumeCleaner::Purge(DWORDLONG /*dwlSpaceToFree*/,
LPEMPTYVOLUMECACHECALLBACK picb)
{
m_pDiskCleaner = picb;
m_pPurger->Delete();
if (m_pDiskCleaner)
m_pDiskCleaner->PurgeProgress(m_dwlSpaceFreed,
0,
EVCCBF_LASTNOTIFICATION,
NULL);
return S_OK;
}
STDMETHODIMP
CCscVolumeCleaner::ShowProperties(HWND /*hwnd*/)
{
// Launch the viewer
COfflineFilesFolder::Open();
return S_FALSE;
}
STDMETHODIMP
CCscVolumeCleaner::Deactivate(LPDWORD /*pdwFlags*/)
{
// nothing to do here
return S_OK;
}
// IEmptyVolumeCache2 method
STDMETHODIMP
CCscVolumeCleaner::InitializeEx(HKEY hkRegKey,
LPCWSTR pcwszVolume,
LPCWSTR pcwszKeyName,
LPWSTR *ppwszDisplayName,
LPWSTR *ppwszDescription,
LPWSTR *ppwszBtnText,
LPDWORD pdwFlags)
{
HRESULT hr = Initialize(hkRegKey,
pcwszVolume,
ppwszDisplayName,
ppwszDescription,
pdwFlags);
if (S_OK == hr)
CoTaskLoadString(g_hInstance, IDS_DISKCLEAN_BTN_TEXT, ppwszBtnText);
return hr;
}
BOOL
CCscVolumeCleaner::ScanCallback(CCachePurger *pPurger)
{
BOOL bContinue = TRUE;
// If the pinned state matches what we're looking for, add the
// size to the total.
if (pPurger->WillDeleteThisFile())
m_dwlSpaceToFree += pPurger->FileBytes();
if (m_pDiskCleaner)
bContinue = SUCCEEDED(m_pDiskCleaner->ScanProgress(m_dwlSpaceToFree,
0,
NULL));
return bContinue;
}
BOOL
CCscVolumeCleaner::DeleteCallback(CCachePurger *pPurger)
{
BOOL bContinue = TRUE;
// Don't let this go below zero
m_dwlSpaceToFree -= min(pPurger->FileBytes(), m_dwlSpaceToFree);
m_dwlSpaceFreed += pPurger->FileBytes();
if (m_pDiskCleaner)
bContinue = SUCCEEDED(m_pDiskCleaner->PurgeProgress(m_dwlSpaceFreed,
m_dwlSpaceToFree,
0,
NULL));
return bContinue;
}
BOOL CALLBACK
CCscVolumeCleaner::CachePurgerCallback(CCachePurger *pPurger)
{
PCSCVOLCLEANER pThis = (PCSCVOLCLEANER)pPurger->CallbackData();
switch (pPurger->Phase())
{
case PURGE_PHASE_SCAN:
return pThis->ScanCallback(pPurger);
case PURGE_PHASE_DELETE:
return pThis->DeleteCallback(pPurger);
}
return FALSE;
}