Windows2000/private/shell/shdocvw/cachecln.cpp
2020-09-30 17:12:32 +02:00

525 lines
13 KiB
C++

// Author: Pritvinath Obla
// Date: 10 July 1997
#include "priv.h"
#include "util.h"
#include <emptyvc.h>
#include <mluisupp.h> // for MLLoadString
#include "resource.h" // for the string ID's
class CInternetCacheCleaner : public IEmptyVolumeCache2
{
private:
// Data
ULONG m_cRef; // reference count
DWORDLONG m_dwlSpaceUsed;
TCHAR m_szCacheDir[MAX_PATH + 1];
// Functions
HRESULT GetInternetCacheSize(
DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb
);
HRESULT DelInternetCacheFiles(
DWORD dwPercentToFree,
IEmptyVolumeCacheCallBack *picb
);
public:
// Constructor and Destructor
CInternetCacheCleaner(void);
~CInternetCacheCleaner(void);
// IUnknown interface members
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IEmptyVolumeCache interface methods
STDMETHODIMP Initialize(
HKEY hkRegKey,
LPCWSTR pcwszVolume,
LPWSTR *ppwszDisplayName,
LPWSTR *ppwszDescription,
DWORD *pdwFlags
);
STDMETHODIMP GetSpaceUsed(
DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb
);
STDMETHODIMP Purge(
DWORDLONG dwlSpaceToFree,
IEmptyVolumeCacheCallBack *picb
);
STDMETHODIMP ShowProperties(
HWND hwnd
);
STDMETHODIMP Deactivate(
DWORD *pdwFlags
);
// IEmptyVolumeCache2 interface methods
STDMETHODIMP InitializeEx(
HKEY hkRegKey,
LPCWSTR pcwszVolume,
LPCWSTR pcwszKeyName,
LPWSTR *ppwszDisplayName,
LPWSTR *ppwszDescription,
LPWSTR *ppwszBtnText,
DWORD *pdwFlags
);
};
// CInternetCacheCleaner_CreateInstance
// Purpose: CreateInstance function for IClassFactory
STDAPI CInternetCacheCleaner_CreateInstance(
IUnknown *punkOuter,
IUnknown **ppunk,
LPCOBJECTINFO poi
)
{
*ppunk = NULL;
CInternetCacheCleaner *lpICC = new CInternetCacheCleaner();
if (lpICC == NULL)
return E_OUTOFMEMORY;
*ppunk = SAFECAST(lpICC, IEmptyVolumeCache *);
return S_OK;
}
CInternetCacheCleaner::CInternetCacheCleaner() : m_cRef(1)
{
DllAddRef();
m_dwlSpaceUsed = 0;
*m_szCacheDir = '\0';
}
CInternetCacheCleaner::~CInternetCacheCleaner()
{
DllRelease();
}
STDMETHODIMP CInternetCacheCleaner::QueryInterface(REFIID riid, LPVOID *ppv)
{
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_IEmptyVolumeCache2) ||
IsEqualIID(riid, IID_IEmptyVolumeCache))
{
*ppv = SAFECAST(this, IEmptyVolumeCache2 *);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG) CInternetCacheCleaner::AddRef()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CInternetCacheCleaner::Release()
{
// Decrement and check
if (--m_cRef)
return m_cRef;
// No references left to this object
delete this;
return 0;
}
// CInternetCacheCleaner::InitializeEx
// Purpose: Initializes the Internet Cache Cleaner and returns the
// specified IEmptyVolumeCache flags to the cache manager
STDMETHODIMP CInternetCacheCleaner::InitializeEx(
HKEY hkRegKey,
LPCWSTR pcwszVolume,
LPCWSTR pcwszKeyName,
LPWSTR *ppwszDisplayName,
LPWSTR *ppwszDescription,
LPWSTR *ppwszBtnText,
DWORD *pdwFlags
)
{
*ppwszBtnText = (LPWSTR)CoTaskMemAlloc( 128*sizeof(WCHAR) );
if ( !*ppwszBtnText )
return E_OUTOFMEMORY;
MLLoadString( IDS_CACHECLN_BTNTEXT, *ppwszBtnText, 128 );
return Initialize(hkRegKey, pcwszVolume, ppwszDisplayName, ppwszDescription, pdwFlags );
}
// CInternetCacheCleaner::Initialize
// Purpose: Initializes the Internet Cache Cleaner and returns the
// specified IEmptyVolumeCache flags to the cache manager
STDMETHODIMP CInternetCacheCleaner::Initialize(
HKEY hkRegKey,
LPCWSTR pcwszVolume,
LPWSTR *ppwszDisplayName,
LPWSTR *ppwszDescription,
DWORD *pdwFlags
)
{
#ifdef UNICODE
// We can't use the registry values on NT because they can't be multi-local localized. As
// a result we must set the out pointers with values read from resources.
*ppwszDisplayName = (LPWSTR)CoTaskMemAlloc( 512*sizeof(WCHAR) );
if ( !*ppwszDisplayName )
return E_OUTOFMEMORY;
*ppwszDescription = (LPWSTR)CoTaskMemAlloc( 512*sizeof(WCHAR) );
if ( !*ppwszDescription )
return E_OUTOFMEMORY;
MLLoadString( IDS_CACHECLN_DISPLAY, *ppwszDisplayName, 512 );
MLLoadString( IDS_CACHECLN_DESCRIPTION, *ppwszDescription, 512 );
#else
// Let cleanmgr read the default DisplayName and Description
// from hkRegKey and use them
*ppwszDisplayName = NULL;
*ppwszDescription = NULL;
#endif
*pdwFlags = 0; // initialize the [out] parameter
// Check if the Internet Cache Folder is in pcwzVolume
GetCacheLocation(m_szCacheDir, sizeof(m_szCacheDir));
if (StrCmpNI(pcwszVolume, m_szCacheDir, 3))
{
// Different drives; return S_FALSE so that this cleaner
// doesn't show up in cleanmgr's UI
return S_FALSE;
}
// Enable this cleaner by default both in cleanup and tuneup modes
*pdwFlags = EVCF_ENABLEBYDEFAULT |
EVCF_ENABLEBYDEFAULT_AUTO |
EVCF_HASSETTINGS;
#if 0
/**
// BUGBUG: Since GetInternetCacheSize returns only an approx. size,
// we would never get a value of 0 even if the cache is empty
// Should enable this check once wininet.dll exports a GetCacheSize API
// Check if there is any disk space to free at all
// If not, return S_FALSE so that this cleaner doesn't show up in
// cleanmgr's UI
DWORDLONG dwlSpaceUsed;
if (SUCCEEDED(GetInternetCacheSize(&dwlSpaceUsed, NULL)) &&
dwlSpaceUsed == 0)
{
return S_FALSE;
}
**/
#endif
return S_OK;
}
// CInternetCacheCleaner::GetSpaceUsed
// Purpose: Return the total amount of space this internet cache cleaner
// can free up
STDMETHODIMP CInternetCacheCleaner::GetSpaceUsed(
DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb
)
{
HRESULT hr;
hr = GetInternetCacheSize(pdwlSpaceUsed, picb);
m_dwlSpaceUsed = *pdwlSpaceUsed;
// Send the last notification to the cleanup manager
if (picb != NULL)
{
picb->ScanProgress(*pdwlSpaceUsed, EVCCBF_LASTNOTIFICATION, NULL);
}
if (hr != E_ABORT)
{
if (FAILED(hr))
{
// *pdwlSpaceUsed is only a guesstimate; so return S_FALSE
hr = S_FALSE;
}
else
{
// BUGBUG: Return S_OK once wininet exports a GetCacheSize API;
// till then use FindFirstUrlCacheEntry/FindNextUrlCacheEntry
// to get approx. size of the cache
hr = S_FALSE;
}
}
return hr;
}
// CInternetCacheCleaner::Purge
// Purpose: Delete the internet cache files
STDMETHODIMP CInternetCacheCleaner::Purge(
DWORDLONG dwlSpaceToFree,
IEmptyVolumeCacheCallBack *picb
)
{
HRESULT hr;
DWORD dwPercentToFree = 100; // Optimize the most common scenario:
// In most cases, dwlSpaceToFree will be
// equal to m_dwlSpaceUsed
if (dwlSpaceToFree != m_dwlSpaceUsed)
{
dwPercentToFree = m_dwlSpaceUsed ?
DWORD((dwlSpaceToFree * 100) / m_dwlSpaceUsed) :
100;
}
hr = DelInternetCacheFiles(dwPercentToFree, picb);
// Send the last notification to the cleanup manager
if (picb != NULL)
{
picb->PurgeProgress(dwlSpaceToFree, 0,
EVCCBF_LASTNOTIFICATION, NULL);
}
if (hr != E_ABORT)
{
hr = S_OK; // cannot return anything else
}
return hr;
}
// CInternetCacheCleaner::ShowProperties
// Purpose: Launch the cache viewer to list the internet cache files
STDMETHODIMP CInternetCacheCleaner::ShowProperties(
HWND hwnd
)
{
DWORD dwAttrib;
if (*m_szCacheDir == '\0') // Internet cache dir is not yet initialized
{
GetCacheLocation(m_szCacheDir, sizeof(m_szCacheDir));
}
dwAttrib = GetFileAttributes(m_szCacheDir);
if (dwAttrib != 0xffffffff && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
{
SHELLEXECUTEINFO sei;
// Launch the cache viewer
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.hwnd = hwnd;
sei.lpVerb = NULL;
sei.lpFile = m_szCacheDir;
sei.lpParameters = NULL;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOWNORMAL;
sei.fMask = 0;
ShellExecuteEx(&sei);
}
// The user may or may not delete files directly from the cachevu folder
// Since there is no way of knowing this, don't return S_OK which would
// trigger cleanmgr to call GetSpaceUsed again
return S_OK;
}
// CInternetCacheCleaner::Deactivate
// Purpose: Deactivates the Internet Cache Cleaner...Not implemented
STDMETHODIMP CInternetCacheCleaner::Deactivate(
DWORD *pdwFlags
)
{
*pdwFlags = 0;
return S_OK;
}
// CInternetCacheCleaner::GetInternetCacheSize
// Purpose: Find the size of the internet cache by calling into wininet APIs
// Notes: The current implementation is temporary; once wininet exports
// a real API for getting the cache size, use that
HRESULT CInternetCacheCleaner::GetInternetCacheSize(
DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb // not used
)
{
HRESULT hr = S_OK;
DWORD dwLastErr;
LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo;
HANDLE hCacheEntryInfo;
DWORD dwCacheEntryInfoSize;
*pdwlSpaceUsed = 0;
if ((lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFOA) LocalAlloc(LPTR,
MAX_CACHE_ENTRY_INFO_SIZE)) == NULL)
{
return E_OUTOFMEMORY;
}
dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
if ((hCacheEntryInfo = FindFirstUrlCacheEntryA(NULL, lpCacheEntryInfo,
&dwCacheEntryInfoSize)) == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
do
{
if (!(lpCacheEntryInfo->CacheEntryType & (STICKY_CACHE_ENTRY | COOKIE_CACHE_ENTRY)))
{
ULARGE_INTEGER uliFileSize;
uliFileSize.HighPart = lpCacheEntryInfo->dwSizeHigh;
uliFileSize.LowPart = lpCacheEntryInfo->dwSizeLow;
*pdwlSpaceUsed += QUAD_PART(uliFileSize);
}
dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
} while (FindNextUrlCacheEntryA(hCacheEntryInfo, lpCacheEntryInfo,
&dwCacheEntryInfoSize));
if ((dwLastErr = GetLastError()) != ERROR_NO_MORE_ITEMS)
{
hr = HRESULT_FROM_WIN32(dwLastErr);
}
}
if (lpCacheEntryInfo != NULL)
LocalFree(lpCacheEntryInfo);
return hr;
}
// CInternetCacheCleaner::DelInternetCacheFiles
// Purpose: Delete the internet cache files
HRESULT CInternetCacheCleaner::DelInternetCacheFiles(
DWORD dwPercentToFree,
IEmptyVolumeCacheCallBack *picb // not used
)
{
HRESULT hr = S_OK;
if (*m_szCacheDir == '\0') // Internet cache dir is not yet initialized
{
hr = GetCacheLocation(m_szCacheDir, sizeof(m_szCacheDir));
}
if (SUCCEEDED(hr))
{
FreeUrlCacheSpace(m_szCacheDir, dwPercentToFree, STICKY_CACHE_ENTRY);
}
return hr;
}