|
|
// 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); }
|