283 lines
8.5 KiB
C++
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;
|
|
}
|