471 lines
13 KiB
C++
471 lines
13 KiB
C++
|
// Author: Karim Farouki
|
||
|
// Date: 24 June 1998
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include "util.h"
|
||
|
#include <emptyvc.h>
|
||
|
#include <mluisupp.h> // for MLLoadString
|
||
|
#include "resource.h" // for the string ID's
|
||
|
|
||
|
typedef HRESULT (* LPFCALLBACK )(LPINTERNET_CACHE_ENTRY_INFO, void *);
|
||
|
|
||
|
typedef struct tagRTSCBSTRUCT
|
||
|
{
|
||
|
IEmptyVolumeCacheCallBack * picb;
|
||
|
DWORDLONG * pdwlSpaceUsed;
|
||
|
} RTSCBSTRUCT; // RunningTotalSizeCallBack Struct
|
||
|
|
||
|
typedef struct tagDECBSTRUCT
|
||
|
{
|
||
|
IEmptyVolumeCacheCallBack * picb;
|
||
|
DWORDLONG dwlSpaceFreed;
|
||
|
DWORDLONG dwlTotalSpace;
|
||
|
} DECBSTRUCT; // DeleteEntryCallBack Struct
|
||
|
|
||
|
class COfflinePagesCacheCleaner : public IEmptyVolumeCache2
|
||
|
{
|
||
|
private:
|
||
|
// Data
|
||
|
ULONG m_cRef;
|
||
|
DWORDLONG m_dwlSpaceUsed;
|
||
|
TCHAR m_szCacheDir[MAX_PATH + 1];
|
||
|
|
||
|
// Functions
|
||
|
HRESULT WalkOfflineCache(
|
||
|
LPFCALLBACK lpfCallBack,
|
||
|
void * pv
|
||
|
);
|
||
|
|
||
|
static HRESULT CALLBACK RunningTotalSizeCallback(
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
|
||
|
void * pv
|
||
|
);
|
||
|
|
||
|
static HRESULT CALLBACK DeleteEntryCallback(
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
|
||
|
void * pv
|
||
|
);
|
||
|
static VOID IncrementFileSize(
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
|
||
|
DWORDLONG * pdwlSize
|
||
|
);
|
||
|
|
||
|
~COfflinePagesCacheCleaner(void);
|
||
|
|
||
|
public:
|
||
|
// Constructor/Destructor
|
||
|
COfflinePagesCacheCleaner(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
|
||
|
);
|
||
|
};
|
||
|
|
||
|
STDAPI COfflinePagesCacheCleaner_CreateInstance(
|
||
|
IUnknown * punkOuter,
|
||
|
IUnknown ** ppunk,
|
||
|
LPCOBJECTINFO poi
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
*ppunk = NULL;
|
||
|
|
||
|
COfflinePagesCacheCleaner * lpOPCC = new COfflinePagesCacheCleaner();
|
||
|
|
||
|
if (lpOPCC == NULL)
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
else
|
||
|
*ppunk = SAFECAST(lpOPCC, IEmptyVolumeCache *);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
COfflinePagesCacheCleaner::COfflinePagesCacheCleaner() : m_cRef(1)
|
||
|
{
|
||
|
DllAddRef();
|
||
|
}
|
||
|
|
||
|
COfflinePagesCacheCleaner::~COfflinePagesCacheCleaner()
|
||
|
{
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::QueryInterface(REFIID riid, LPVOID * ppv)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEmptyVolumeCache) || IsEqualIID(riid, IID_IEmptyVolumeCache2))
|
||
|
{
|
||
|
*ppv = SAFECAST(this, IEmptyVolumeCache2 *);
|
||
|
AddRef();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppv = NULL;
|
||
|
hr = E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) COfflinePagesCacheCleaner::AddRef()
|
||
|
{
|
||
|
return ++m_cRef;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) COfflinePagesCacheCleaner::Release()
|
||
|
{
|
||
|
ULONG uRefCount = --m_cRef;
|
||
|
|
||
|
if (!uRefCount)
|
||
|
delete this;
|
||
|
|
||
|
return uRefCount;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::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_CACHEOFF_BTNTEXT, *ppwszBtnText, 512 );
|
||
|
|
||
|
return Initialize(hkRegKey, pcwszVolume, ppwszDisplayName, ppwszDescription, pdwFlags );
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::Initialize(
|
||
|
HKEY hkRegkey,
|
||
|
LPCWSTR pcwszVolume,
|
||
|
LPWSTR * ppwszDisplayName,
|
||
|
LPWSTR * ppwszDescription,
|
||
|
DWORD * pdwFlags
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
uCLSSPEC ucs; // Used to see if Webcheck is installed
|
||
|
QUERYCONTEXT qc = { 0 }; // Used to see if Webcheck is installed
|
||
|
DWORDLONG dwlSize; // Amount of offline cachespace
|
||
|
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
// We can't use the registry values on NT because they can't be multi-local localized.
|
||
|
// Instead we must use strings loaded 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_CACHEOFF_DISPLAY, *ppwszDisplayName, 512 );
|
||
|
MLLoadString( IDS_CACHEOFF_DESCRIPTION, *ppwszDescription, 512 );
|
||
|
|
||
|
#else
|
||
|
// We can use the default registry DisplayName and Description
|
||
|
*ppwszDisplayName = NULL;
|
||
|
*ppwszDescription = NULL;
|
||
|
#endif
|
||
|
|
||
|
// Intentionally am not turning on cleanup by default; turning on *view pages* button
|
||
|
*pdwFlags = EVCF_HASSETTINGS;
|
||
|
|
||
|
// Let's check if the Internet Cache Folder is in pcwzVolume
|
||
|
GetCacheLocation(m_szCacheDir, sizeof(m_szCacheDir));
|
||
|
if (StrCmpNI(pcwszVolume, m_szCacheDir, 3))
|
||
|
{
|
||
|
// If the cache is on a different drive return S_FALSE so that we don't show up in UI
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
// Determine if offline browsing pack is intalled.
|
||
|
ucs.tyspec = TYSPEC_CLSID;
|
||
|
ucs.tagged_union.clsid = CLSID_SubscriptionMgr;
|
||
|
|
||
|
hr = FaultInIEFeature(NULL, &ucs, &qc, FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI);
|
||
|
|
||
|
if (SUCCEEDED(hr)) // (if offline pack installed)
|
||
|
{
|
||
|
GetSpaceUsed(&dwlSize, NULL);
|
||
|
|
||
|
if (dwlSize) // If there is something in offline cache to delete
|
||
|
return S_OK; // load cleaner/
|
||
|
}
|
||
|
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::GetSpaceUsed(
|
||
|
DWORDLONG * pdwlSpaceUsed,
|
||
|
IEmptyVolumeCacheCallBack * picb
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
ASSERT(NULL != pdwlSpaceUsed);
|
||
|
|
||
|
if (NULL != pdwlSpaceUsed)
|
||
|
{
|
||
|
RTSCBSTRUCT * prtscbStruct = new RTSCBSTRUCT;
|
||
|
|
||
|
if (NULL != prtscbStruct)
|
||
|
{
|
||
|
// Initialize GetSpazeUsed Structure
|
||
|
prtscbStruct->pdwlSpaceUsed = pdwlSpaceUsed;
|
||
|
*(prtscbStruct->pdwlSpaceUsed) = 0;
|
||
|
prtscbStruct->picb = picb;
|
||
|
|
||
|
// Get Offline Cache Space Usage
|
||
|
hr = WalkOfflineCache(RunningTotalSizeCallback, (void *)(prtscbStruct));
|
||
|
m_dwlSpaceUsed = *(prtscbStruct->pdwlSpaceUsed);
|
||
|
|
||
|
// Send the last notification to the cleanup manager
|
||
|
if (picb != NULL)
|
||
|
picb->ScanProgress(*(prtscbStruct->pdwlSpaceUsed), EVCCBF_LASTNOTIFICATION, NULL);
|
||
|
|
||
|
delete prtscbStruct;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::Purge(
|
||
|
DWORDLONG dwlSpaceToFree, // Spec makes this irrelevent!
|
||
|
IEmptyVolumeCacheCallBack * picb
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
DECBSTRUCT * pdecbStruct = new DECBSTRUCT;
|
||
|
|
||
|
if (NULL != pdecbStruct)
|
||
|
{
|
||
|
// Initialize DeleteEntry Structure
|
||
|
pdecbStruct->picb = picb;
|
||
|
pdecbStruct->dwlSpaceFreed = 0;
|
||
|
pdecbStruct->dwlTotalSpace = m_dwlSpaceUsed;
|
||
|
|
||
|
// Delete Offline Cache Entries
|
||
|
hr = WalkOfflineCache(DeleteEntryCallback, (void *)(pdecbStruct));
|
||
|
|
||
|
// Send the last notification to the cleanup manager
|
||
|
if (picb != NULL)
|
||
|
{
|
||
|
picb->PurgeProgress(m_dwlSpaceUsed, 0, EVCCBF_LASTNOTIFICATION, NULL);
|
||
|
}
|
||
|
|
||
|
delete pdecbStruct;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::ShowProperties(HWND hwnd)
|
||
|
{
|
||
|
TCHAR szOfflinePath[MAX_PATH];
|
||
|
DWORD dwSize = SIZEOF(szOfflinePath);
|
||
|
|
||
|
if (SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_SUBSCRIPTION,
|
||
|
REGSTR_VAL_DIRECTORY, NULL, (LPBYTE)szOfflinePath, &dwSize) != ERROR_SUCCESS)
|
||
|
{
|
||
|
TCHAR szWindows[MAX_PATH];
|
||
|
|
||
|
GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows));
|
||
|
PathCombine(szOfflinePath, szWindows, TEXT("Offline Web Pages"));
|
||
|
}
|
||
|
|
||
|
SHELLEXECUTEINFO shei;
|
||
|
ZeroMemory(&shei, sizeof(shei));
|
||
|
shei.cbSize = sizeof(shei);
|
||
|
shei.lpFile = szOfflinePath;
|
||
|
shei.nShow = SW_SHOWNORMAL;
|
||
|
ShellExecuteEx(&shei);
|
||
|
|
||
|
// Returning S_OK insures that GetSpaceUsed is recalled (to recalc) the size being
|
||
|
// used (in case someone deletes some MAO stuff).
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP COfflinePagesCacheCleaner::Deactivate(DWORD * pdwFlags)
|
||
|
{
|
||
|
// We don't implement this.
|
||
|
*pdwFlags = 0;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT COfflinePagesCacheCleaner::WalkOfflineCache(
|
||
|
LPFCALLBACK lpfCallBack,
|
||
|
void * pv
|
||
|
)
|
||
|
{
|
||
|
ASSERT(pv);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
|
||
|
HANDLE hCacheEntryInfo;
|
||
|
DWORD dwCacheEntryInfoSize;
|
||
|
|
||
|
if ((lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO) LocalAlloc(LPTR,
|
||
|
MAX_CACHE_ENTRY_INFO_SIZE)) == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
|
||
|
if ((hCacheEntryInfo = FindFirstUrlCacheEntry(NULL, lpCacheEntryInfo,
|
||
|
&dwCacheEntryInfoSize)) == NULL)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
if (lpCacheEntryInfo->CacheEntryType & STICKY_CACHE_ENTRY)
|
||
|
{
|
||
|
hr = lpfCallBack(lpCacheEntryInfo, pv);
|
||
|
}
|
||
|
|
||
|
dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
|
||
|
} while ((E_ABORT != hr) &&
|
||
|
FindNextUrlCacheEntry(hCacheEntryInfo, lpCacheEntryInfo,
|
||
|
&dwCacheEntryInfoSize));
|
||
|
|
||
|
if (hr != E_ABORT)
|
||
|
{
|
||
|
DWORD dwLastErr = GetLastError();
|
||
|
|
||
|
if (dwLastErr != ERROR_NO_MORE_ITEMS)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(dwLastErr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LocalFree(lpCacheEntryInfo);
|
||
|
lpCacheEntryInfo = NULL;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CALLBACK COfflinePagesCacheCleaner::RunningTotalSizeCallback(
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo, // Name of the CacheEntry to sum
|
||
|
void * pv // A RTSCBSTRUCT
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RTSCBSTRUCT * prtscbStruct = (RTSCBSTRUCT *)pv;
|
||
|
|
||
|
// Add current file size to total
|
||
|
IncrementFileSize(lpCacheEntryInfo, prtscbStruct->pdwlSpaceUsed);
|
||
|
|
||
|
// Update the progressbar!
|
||
|
if (prtscbStruct->picb != NULL)
|
||
|
hr = prtscbStruct->picb->ScanProgress(*(prtscbStruct->pdwlSpaceUsed), 0, NULL);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CALLBACK COfflinePagesCacheCleaner::DeleteEntryCallback(
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo, // Name of the CacheEntry to delete
|
||
|
void * pv // Pointer to DECBSTRUCT
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
DECBSTRUCT * pdecbStruct = (DECBSTRUCT *)pv;
|
||
|
|
||
|
// Add current file size to total deleted
|
||
|
IncrementFileSize(lpCacheEntryInfo, &(pdecbStruct->dwlSpaceFreed));
|
||
|
|
||
|
DeleteUrlCacheEntry(lpCacheEntryInfo->lpszSourceUrlName);
|
||
|
|
||
|
// Update the progress bar!
|
||
|
if (pdecbStruct->picb != NULL)
|
||
|
{
|
||
|
hr = pdecbStruct->picb->PurgeProgress(pdecbStruct->dwlSpaceFreed,
|
||
|
pdecbStruct->dwlTotalSpace - pdecbStruct->dwlSpaceFreed, NULL, NULL);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
VOID COfflinePagesCacheCleaner::IncrementFileSize(
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
|
||
|
DWORDLONG * pdwlSize
|
||
|
)
|
||
|
{
|
||
|
ULARGE_INTEGER uliFileSize;
|
||
|
|
||
|
uliFileSize.HighPart = lpCacheEntryInfo->dwSizeHigh;
|
||
|
uliFileSize.LowPart = lpCacheEntryInfo->dwSizeLow;
|
||
|
|
||
|
*pdwlSize += QUAD_PART(uliFileSize);
|
||
|
}
|