706 lines
19 KiB
C++
706 lines
19 KiB
C++
|
#include "init.h"
|
||
|
#include <emptyvc.h>
|
||
|
#include <regstr.h>
|
||
|
#include "general.h"
|
||
|
#include "dlg.h"
|
||
|
#include "emptyvol.h"
|
||
|
#include "parseinf.h"
|
||
|
|
||
|
#define MAX_DRIVES 26 // there are 26 letters only
|
||
|
|
||
|
// {8369AB20-56C9-11d0-94E8-00AA0059CE02}
|
||
|
const CLSID CLSID_EmptyControlVolumeCache = {
|
||
|
0x8369ab20, 0x56c9, 0x11d0,
|
||
|
0x94, 0xe8, 0x0, 0xaa, 0x0,
|
||
|
0x59, 0xce, 0x2};
|
||
|
|
||
|
/******************************************************************************
|
||
|
class CEmptyControlVolumeCache
|
||
|
******************************************************************************/
|
||
|
|
||
|
class CEmptyControlVolumeCache : public IEmptyVolumeCache
|
||
|
{
|
||
|
public:
|
||
|
// IUnknown Methods
|
||
|
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
|
||
|
STDMETHODIMP_(ULONG) AddRef();
|
||
|
STDMETHODIMP_(ULONG) Release();
|
||
|
|
||
|
// IEmptyVolumeCache Methods
|
||
|
STDMETHODIMP Initialize(HKEY hRegKey, LPCWSTR pszVolume,
|
||
|
LPWSTR *ppszDisplayName, LPWSTR *ppszDescription, DWORD *pdwFlags);
|
||
|
STDMETHODIMP GetSpaceUsed(DWORDLONG *pdwSpaceUsed,
|
||
|
IEmptyVolumeCacheCallBack *picb);
|
||
|
STDMETHODIMP Purge(DWORDLONG dwSpaceToFree,
|
||
|
IEmptyVolumeCacheCallBack *picb);
|
||
|
STDMETHODIMP ShowProperties(HWND hwnd);
|
||
|
STDMETHODIMP Deactivate(DWORD *pdwFlags);
|
||
|
|
||
|
// Attributes
|
||
|
public:
|
||
|
static HRESULT IsControlExpired(HANDLE hControl, BOOL fUseCache = TRUE);
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
// Constructor and destructor
|
||
|
CEmptyControlVolumeCache();
|
||
|
virtual ~CEmptyControlVolumeCache();
|
||
|
|
||
|
protected:
|
||
|
// implementation data helpers
|
||
|
|
||
|
// Note. Write operations are only perfomed by the private functions
|
||
|
// prefixed cpl_XXX. Read access is not restricted.
|
||
|
LPCACHE_PATH_NODE m_pPathsHead,
|
||
|
m_pPathsTail;
|
||
|
|
||
|
// Note. Write operations are only perfomed by the private functions
|
||
|
// prefixed chl_XXX. Read access is not restricted.
|
||
|
LPCONTROL_HANDLE_NODE m_pControlsHead,
|
||
|
m_pControlsTail;
|
||
|
|
||
|
WCHAR m_szVol[4];
|
||
|
DWORDLONG m_dwTotalSize;
|
||
|
ULONG m_cRef;
|
||
|
|
||
|
// implementation helper routines
|
||
|
|
||
|
// cpl prefix stands for CachePathsList
|
||
|
HRESULT cpl_Add(LPCTSTR pszCachePath);
|
||
|
void cpl_Remove();
|
||
|
HRESULT cpl_CreateForVolume(LPCWSTR pszVolume = NULL);
|
||
|
|
||
|
// chl prefix stands for ControlHandlesList
|
||
|
HRESULT chl_Find(HANDLE hControl,
|
||
|
LPCONTROL_HANDLE_NODE *rgp = NULL, UINT nSize = 1) const;
|
||
|
HRESULT chl_Add(HANDLE hControl);
|
||
|
void chl_Remove(LPCONTROL_HANDLE_NODE rgp[2]);
|
||
|
HRESULT chl_Remove(HANDLE hControl = NULL);
|
||
|
HRESULT chl_CreateForPath(LPCTSTR pszCachePath,
|
||
|
DWORDLONG *pdwUsedInFolder = NULL);
|
||
|
|
||
|
friend HRESULT _stdcall EmptyControl_CreateInstance(IUnknown *pUnkOuter,
|
||
|
REFIID riid, LPVOID* ppv);
|
||
|
|
||
|
// friend BOOL CALLBACK EmptyControl_PropertiesDlgProc(HWND hDlg,
|
||
|
// UINT msg, WPARAM wp, LPARAM lp);
|
||
|
};
|
||
|
|
||
|
|
||
|
STDAPI EmptyControl_CreateInstance(IUnknown *pUnkOuter, REFIID riid, LPVOID* ppv)
|
||
|
{
|
||
|
*ppv = NULL;
|
||
|
|
||
|
if (pUnkOuter != NULL)
|
||
|
return CLASS_E_NOAGGREGATION;
|
||
|
|
||
|
CEmptyControlVolumeCache *pCRC = new CEmptyControlVolumeCache;
|
||
|
if (pCRC == NULL)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
HRESULT hr = pCRC->QueryInterface(riid, ppv);
|
||
|
pCRC->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CEmptyControlVolumeCache constructor and destructor
|
||
|
|
||
|
CEmptyControlVolumeCache::CEmptyControlVolumeCache()
|
||
|
{
|
||
|
DllAddRef();
|
||
|
|
||
|
m_pPathsHead = m_pPathsTail = NULL;
|
||
|
m_pControlsHead = m_pControlsTail = NULL;
|
||
|
|
||
|
m_szVol[0] = L'\0';
|
||
|
m_dwTotalSize = 0;
|
||
|
m_cRef = 1;
|
||
|
}
|
||
|
|
||
|
CEmptyControlVolumeCache::~CEmptyControlVolumeCache()
|
||
|
{
|
||
|
ASSERT(m_cRef == 0);
|
||
|
cpl_Remove();
|
||
|
chl_Remove();
|
||
|
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CEmptyControlVolumeCache attributes
|
||
|
|
||
|
|
||
|
// CEmptyControlVolumeCache::IsControlExpired
|
||
|
// Check if a control has not been accessed for more than N days. If there is
|
||
|
// no registry entry, default is DEFAULT_DAYS_BEFORE_EXPIRE.
|
||
|
//
|
||
|
// Parameters: fUseCache can be used to not go to the registry for the value
|
||
|
// of N above.
|
||
|
//
|
||
|
// Returns: either the Win32 error converted to HRESULT or
|
||
|
// S_OK if control is expired and S_FALSE if not;
|
||
|
//
|
||
|
// Used by: only by CEmptyControlVolumeCache::chl_CreateForPath
|
||
|
//
|
||
|
HRESULT CEmptyControlVolumeCache::IsControlExpired(HANDLE hControl,
|
||
|
BOOL fUseCache /*= TRUE*/)
|
||
|
{
|
||
|
SYSTEMTIME stNow;
|
||
|
FILETIME ftNow;
|
||
|
FILETIME ftLastAccess;
|
||
|
LARGE_INTEGER timeExpire;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
|
||
|
|
||
|
// don't expire controls with uncertain access time.
|
||
|
if (FAILED(GetLastAccessTime(hControl, &ftLastAccess)))
|
||
|
return S_FALSE;
|
||
|
|
||
|
//----- Time calculations (wierd looking) -----
|
||
|
// Add to last access date the length of time before a control expires
|
||
|
timeExpire.LowPart = ftLastAccess.dwLowDateTime;
|
||
|
timeExpire.HighPart = ftLastAccess.dwHighDateTime;
|
||
|
timeExpire.QuadPart += (((CCacheItem*)hControl)->GetExpireDays() * 864000000000L); //24*3600*10^7
|
||
|
|
||
|
GetLocalTime(&stNow);
|
||
|
SystemTimeToFileTime(&stNow, &ftNow);
|
||
|
|
||
|
return CompareFileTime((FILETIME*)&timeExpire, &ftNow) <= 0 ?
|
||
|
S_OK : S_FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CEmptyControlVolumeCache CachePathsList routines
|
||
|
|
||
|
// CEmptyControlVolumeCache::cpl_Add
|
||
|
// Check if a control has not been accessed for more than N days. If there is
|
||
|
// no registry entry, default is DEFAULT_DAYS_BEFORE_EXPIRE.
|
||
|
//
|
||
|
// Parameters: a cache folder path to add.
|
||
|
//
|
||
|
// Returns: E_OUTOFMEMORY or
|
||
|
// S_FALSE if path is already in the list or S_OK if added.
|
||
|
//
|
||
|
// Used by: only by CEmptyControlVolumeCache::cpl_CreateForVolume
|
||
|
//
|
||
|
HRESULT CEmptyControlVolumeCache::cpl_Add(LPCTSTR pszCachePath)
|
||
|
{
|
||
|
LPCACHE_PATH_NODE pNode;
|
||
|
|
||
|
ASSERT(pszCachePath != NULL);
|
||
|
|
||
|
for (pNode = m_pPathsHead; pNode != NULL; pNode = pNode->pNext)
|
||
|
if (lstrcmpi(pNode->szCachePath, pszCachePath) == 0)
|
||
|
break;
|
||
|
if (pNode != NULL)
|
||
|
return S_FALSE;
|
||
|
|
||
|
pNode = new CACHE_PATH_NODE;
|
||
|
if (pNode == NULL)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
lstrcpyn(pNode->szCachePath, pszCachePath, MAX_PATH);
|
||
|
pNode->pNext = NULL;
|
||
|
if (m_pPathsHead == NULL)
|
||
|
m_pPathsHead = pNode;
|
||
|
else
|
||
|
m_pPathsTail->pNext = pNode;
|
||
|
m_pPathsTail = pNode;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// CEmptyControlVolumeCache::cpl_Remove
|
||
|
// Remove all paths from the internal list.
|
||
|
//
|
||
|
// Parameters: none;
|
||
|
//
|
||
|
// Returns: void;
|
||
|
//
|
||
|
// Used by: several obvious places
|
||
|
//
|
||
|
void CEmptyControlVolumeCache::cpl_Remove()
|
||
|
{
|
||
|
// remove cache path list
|
||
|
for (LPCACHE_PATH_NODE pCur = m_pPathsHead;
|
||
|
m_pPathsHead != NULL;
|
||
|
pCur = m_pPathsHead) {
|
||
|
|
||
|
m_pPathsHead = m_pPathsHead->pNext;
|
||
|
delete[] pCur;
|
||
|
}
|
||
|
m_pPathsTail = NULL;
|
||
|
}
|
||
|
|
||
|
// CEmptyControlVolumeCache::cpl_CreateForVolume
|
||
|
// Build a list of paths to cache folders.
|
||
|
//
|
||
|
// Parameters: volume (or drive) where these folders are;
|
||
|
//
|
||
|
// Returns: S_OK or one out of the bunch of obvious errors;
|
||
|
//
|
||
|
// Used by: only by IEmptyVolumeCache::GetSpaceUsed
|
||
|
//
|
||
|
HRESULT CEmptyControlVolumeCache::cpl_CreateForVolume(LPCWSTR pszVolume)
|
||
|
{
|
||
|
HKEY hkey = NULL;
|
||
|
HRESULT hr = E_FAIL;
|
||
|
int iDriveNum;
|
||
|
|
||
|
ASSERT(pszVolume != NULL);
|
||
|
iDriveNum = PathGetDriveNumberW(pszVolume);
|
||
|
if (iDriveNum < 0)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_ACTIVEX_CACHE, 0,
|
||
|
KEY_READ, &hkey) != ERROR_SUCCESS)
|
||
|
return E_FAIL;
|
||
|
|
||
|
TCHAR szCachePath[MAX_PATH],
|
||
|
szValue[MAX_PATH];
|
||
|
DWORD dwIndex = 0,
|
||
|
dwValueLen = MAX_PATH, dwLen = MAX_PATH;
|
||
|
|
||
|
cpl_Remove();
|
||
|
while (RegEnumValue(hkey, dwIndex++, szValue, &dwValueLen, NULL, NULL,
|
||
|
(LPBYTE)szCachePath, &dwLen) == ERROR_SUCCESS) {
|
||
|
dwLen = dwValueLen = MAX_PATH;
|
||
|
|
||
|
if (PathGetDriveNumber(szCachePath) != iDriveNum)
|
||
|
continue;
|
||
|
|
||
|
// we must have added at least one successfully to get a success code..
|
||
|
hr = cpl_Add(szCachePath);
|
||
|
if (FAILED(hr))
|
||
|
break;
|
||
|
}
|
||
|
RegCloseKey(hkey);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
cpl_Remove();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CEmptyControlVolumeCache ControlHandlesList routines
|
||
|
|
||
|
// CEmptyControlVolumeCache::chl_Find
|
||
|
// Find and return a location for the specified handle in the internal list.
|
||
|
// if (rgp == NULL), only result matters;
|
||
|
// if (rgp != NULL),
|
||
|
// if (nSize == 1), *rgp is going to have found item (if it's there)
|
||
|
// if (nSize >= 2), *rgp[0] = prev to the found item, and *rgp[1] is the
|
||
|
// item.
|
||
|
//
|
||
|
// Parameters: explained above;
|
||
|
//
|
||
|
// Returns: S_OK if the item is found, S_FALSE otherwise or
|
||
|
// one out of the bunch of obvious errors;
|
||
|
//
|
||
|
// Used by: CEmptyControlVolumeCache::chl_Add and
|
||
|
// CEmptyControlVolumeCache::chl_Remove
|
||
|
//
|
||
|
HRESULT CEmptyControlVolumeCache::chl_Find(HANDLE hControl,
|
||
|
LPCONTROL_HANDLE_NODE *rgp /*= NULL*/, UINT nSize /*= 1*/) const
|
||
|
{
|
||
|
LPCONTROL_HANDLE_NODE pCur,
|
||
|
pPrev = NULL;
|
||
|
|
||
|
ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
|
||
|
for (pCur = m_pControlsHead; pCur != NULL; pCur = pCur->pNext) {
|
||
|
if (pCur->hControl == hControl)
|
||
|
break;
|
||
|
pPrev = pCur;
|
||
|
}
|
||
|
if (pCur == NULL)
|
||
|
pPrev = NULL; // zero out possible return
|
||
|
|
||
|
if (rgp != NULL && nSize > 0)
|
||
|
if (nSize == 1)
|
||
|
*rgp = pCur;
|
||
|
else { /* if (nSize >= 2) */
|
||
|
rgp[0] = pPrev;
|
||
|
rgp[1] = pCur;
|
||
|
}
|
||
|
|
||
|
return (pCur != NULL) ? S_OK : E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CEmptyControlVolumeCache::chl_Add(HANDLE hControl)
|
||
|
{
|
||
|
LPCONTROL_HANDLE_NODE pNode;
|
||
|
DWORD dwSize;
|
||
|
|
||
|
// Note. Retail build assumes that handle is not in the list.
|
||
|
ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
|
||
|
ASSERT(FAILED(chl_Find(hControl)));
|
||
|
|
||
|
pNode = new CONTROL_HANDLE_NODE;
|
||
|
if (pNode == NULL)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
GetControlInfo(hControl, GCI_SIZESAVED, &dwSize, NULL, 0);
|
||
|
|
||
|
pNode->hControl = hControl;
|
||
|
pNode->pNext = NULL;
|
||
|
|
||
|
if (m_pControlsHead == NULL)
|
||
|
m_pControlsHead = pNode;
|
||
|
else {
|
||
|
ASSERT(m_pControlsHead != NULL);
|
||
|
m_pControlsTail->pNext = pNode;
|
||
|
}
|
||
|
m_pControlsTail = pNode;
|
||
|
|
||
|
m_dwTotalSize += dwSize;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
void CEmptyControlVolumeCache::chl_Remove(LPCONTROL_HANDLE_NODE rgp[2])
|
||
|
{
|
||
|
DWORD dwSize;
|
||
|
|
||
|
if (m_pControlsHead == NULL || (rgp[0] != NULL && rgp[1] == NULL))
|
||
|
return;
|
||
|
|
||
|
if (rgp[0] != NULL)
|
||
|
rgp[0]->pNext = rgp[1]->pNext;
|
||
|
else {
|
||
|
rgp[1] = m_pControlsHead;
|
||
|
m_pControlsHead = m_pControlsHead->pNext;
|
||
|
}
|
||
|
|
||
|
if (rgp[1] == m_pControlsTail)
|
||
|
m_pControlsTail = rgp[0];
|
||
|
|
||
|
if (GetControlInfo(rgp[1]->hControl, GCI_SIZESAVED, &dwSize, NULL, 0))
|
||
|
{
|
||
|
// only proceeed if GetControlInfo succeeds
|
||
|
|
||
|
// Note. This code assumes that the size of a control didn't change since
|
||
|
// it was added.
|
||
|
m_dwTotalSize -= dwSize;
|
||
|
}
|
||
|
|
||
|
ReleaseControlHandle(rgp[1]->hControl);
|
||
|
delete rgp[1];
|
||
|
}
|
||
|
|
||
|
HRESULT CEmptyControlVolumeCache::chl_Remove(HANDLE hControl /*= NULL*/)
|
||
|
{
|
||
|
LPCONTROL_HANDLE_NODE rgp[2] = { NULL, NULL };
|
||
|
HRESULT hr;
|
||
|
|
||
|
ASSERT(hControl != INVALID_HANDLE_VALUE);
|
||
|
if (hControl != NULL) {
|
||
|
hr = chl_Find(hControl, rgp, 2);
|
||
|
if (FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
chl_Remove(rgp);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
while (m_pControlsHead != NULL)
|
||
|
chl_Remove(rgp);
|
||
|
|
||
|
ASSERT(m_pControlsHead == NULL && m_pControlsTail == NULL);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// CEmptyControlVolumeCache::chl_CreateForPath
|
||
|
// Calculate the size in bytes taken up by controls in the control cache
|
||
|
// folder specified.
|
||
|
//
|
||
|
// Parameters: pszCachePath is a path to the controls cache folder;
|
||
|
// pdwSpaceUsed is the result
|
||
|
//
|
||
|
// Used by: only by IEmptyVolumeCache::GetSpaceUsed
|
||
|
//
|
||
|
HRESULT CEmptyControlVolumeCache::chl_CreateForPath(LPCTSTR pszCachePath,
|
||
|
DWORDLONG *pdwUsedInFolder /*= NULL*/)
|
||
|
{
|
||
|
DWORDLONG dwCopy;
|
||
|
HANDLE hFind = NULL,
|
||
|
hControl = NULL;
|
||
|
LONG lResult;
|
||
|
BOOL fCache = FALSE;
|
||
|
|
||
|
dwCopy = m_dwTotalSize;
|
||
|
for (lResult = FindFirstControl(hFind, hControl, pszCachePath);
|
||
|
lResult == ERROR_SUCCESS;
|
||
|
lResult = FindNextControl(hFind, hControl)) {
|
||
|
|
||
|
lResult = HRESULT_CODE(IsControlExpired(hControl, fCache));
|
||
|
fCache = TRUE;
|
||
|
if (lResult != ERROR_SUCCESS)
|
||
|
continue;
|
||
|
|
||
|
lResult = HRESULT_CODE(chl_Add(hControl));
|
||
|
if (lResult != ERROR_SUCCESS)
|
||
|
break;
|
||
|
}
|
||
|
FindControlClose(hFind);
|
||
|
|
||
|
if (lResult == ERROR_NO_MORE_ITEMS)
|
||
|
lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (pdwUsedInFolder != NULL) {
|
||
|
*pdwUsedInFolder = m_dwTotalSize - dwCopy;
|
||
|
}
|
||
|
return HRESULT_FROM_WIN32(lResult);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
IUnknown Methods
|
||
|
******************************************************************************/
|
||
|
|
||
|
STDMETHODIMP CEmptyControlVolumeCache::QueryInterface(REFIID iid, void** ppv)
|
||
|
{
|
||
|
if (ppv == NULL)
|
||
|
return E_POINTER;
|
||
|
*ppv = NULL;
|
||
|
|
||
|
if (iid != IID_IUnknown && iid != IID_IEmptyVolumeCache)
|
||
|
return E_NOINTERFACE;
|
||
|
|
||
|
*ppv = (void *)this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CEmptyControlVolumeCache::AddRef()
|
||
|
{
|
||
|
return (++m_cRef);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CEmptyControlVolumeCache::Release()
|
||
|
{
|
||
|
if (--m_cRef)
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/******************************************************************************
|
||
|
IEmptyVolumeCache Methods
|
||
|
******************************************************************************/
|
||
|
|
||
|
STDMETHODIMP CEmptyControlVolumeCache::Initialize(HKEY hRegKey,
|
||
|
LPCWSTR pszVolume, LPWSTR *ppszDisplayName, LPWSTR *ppszDescription,
|
||
|
DWORD *pdwFlags)
|
||
|
{
|
||
|
if (pszVolume == NULL)
|
||
|
return E_POINTER;
|
||
|
|
||
|
if (ppszDisplayName == NULL || ppszDescription == NULL)
|
||
|
return E_POINTER;
|
||
|
|
||
|
if (pdwFlags == NULL)
|
||
|
return E_POINTER;
|
||
|
|
||
|
StrCpyNW(m_szVol, pszVolume, ARRAYSIZE(m_szVol));
|
||
|
cpl_Remove();
|
||
|
chl_Remove();
|
||
|
|
||
|
if (lstrlenW(m_szVol) == 0) {
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
if (FAILED(cpl_CreateForVolume(m_szVol))) {
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
*ppszDisplayName = *ppszDescription = NULL;
|
||
|
*pdwFlags = EVCF_HASSETTINGS | EVCF_ENABLEBYDEFAULT |
|
||
|
EVCF_ENABLEBYDEFAULT_AUTO;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CEmptyControlVolumeCache::GetSpaceUsed(DWORDLONG *pdwSpaceUsed,
|
||
|
IEmptyVolumeCacheCallBack *picb)
|
||
|
{
|
||
|
LPCACHE_PATH_NODE pCur;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if (pdwSpaceUsed == NULL) {
|
||
|
hr = E_POINTER;
|
||
|
goto LastNotification;
|
||
|
}
|
||
|
*pdwSpaceUsed = 0;
|
||
|
|
||
|
if (lstrlenW(m_szVol) == 0) {
|
||
|
hr = E_UNEXPECTED;
|
||
|
goto LastNotification;
|
||
|
}
|
||
|
|
||
|
for (pCur = m_pPathsHead; pCur != NULL; pCur = pCur->pNext) {
|
||
|
DWORDLONG dwlThisItem = 0;
|
||
|
if (FAILED(chl_CreateForPath(pCur->szCachePath, &dwlThisItem)))
|
||
|
hr = S_FALSE; // at least one failed
|
||
|
|
||
|
m_dwTotalSize += dwlThisItem;
|
||
|
|
||
|
if (picb != NULL)
|
||
|
picb->ScanProgress(m_dwTotalSize, 0, NULL);
|
||
|
}
|
||
|
// cpl_Remove(); // because of ShowProperties
|
||
|
|
||
|
*pdwSpaceUsed = m_dwTotalSize;
|
||
|
|
||
|
LastNotification:
|
||
|
if (picb != NULL)
|
||
|
picb->ScanProgress(m_dwTotalSize, EVCCBF_LASTNOTIFICATION, NULL);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CEmptyControlVolumeCache::Purge(DWORDLONG dwSpaceToFree,
|
||
|
IEmptyVolumeCacheCallBack *picb)
|
||
|
{
|
||
|
LPCONTROL_HANDLE_NODE rgp[2] = { NULL, NULL };
|
||
|
DWORDLONG dwSpaceFreed;
|
||
|
HANDLE hControl;
|
||
|
DWORD dwSize;
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (m_pControlsHead == NULL) {
|
||
|
DWORDLONG dwSpaceUsed;
|
||
|
|
||
|
hr = GetSpaceUsed(&dwSpaceUsed, picb);
|
||
|
if (FAILED(hr) || m_pControlsHead == NULL)
|
||
|
hr = FAILED(hr) ? hr : STG_E_NOMOREFILES;
|
||
|
|
||
|
if (picb != NULL)
|
||
|
picb->PurgeProgress(0, dwSpaceToFree, EVCCBF_LASTNOTIFICATION,
|
||
|
NULL);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
dwSpaceFreed = 0;
|
||
|
ASSERT(m_pControlsHead != NULL);
|
||
|
while (m_pControlsHead != NULL) {
|
||
|
hControl = m_pControlsHead->hControl;
|
||
|
ASSERT(hControl != NULL && hControl != INVALID_HANDLE_VALUE);
|
||
|
|
||
|
GetControlInfo(hControl, GCI_SIZESAVED, &dwSize, NULL, 0);
|
||
|
|
||
|
hr = RemoveControlByHandle2(hControl, FALSE, TRUE);
|
||
|
if (SUCCEEDED(hr)) {
|
||
|
dwSpaceFreed += dwSize;
|
||
|
|
||
|
if (picb != NULL)
|
||
|
picb->PurgeProgress(dwSpaceFreed, dwSpaceToFree, 0, NULL);
|
||
|
}
|
||
|
chl_Remove(rgp);
|
||
|
|
||
|
if (dwSpaceFreed >= dwSpaceToFree)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (picb != NULL)
|
||
|
picb->PurgeProgress(dwSpaceFreed, dwSpaceToFree, 0, NULL);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// Note. This function opens the last cache folder in the internal list.
|
||
|
STDMETHODIMP CEmptyControlVolumeCache::ShowProperties(HWND hwnd)
|
||
|
{
|
||
|
// Note. (According to SeanF) The codedownload engine will query
|
||
|
// ActiveXCache key under HKLM\SOFTWARE\Microsoft\Windows\
|
||
|
// CurrentVersion\Internet Settings. The value of this key should
|
||
|
// be equal to the last item in the CachePathsList which is why
|
||
|
// navigation below is done for the tail.
|
||
|
if (m_pPathsTail == NULL || m_pPathsTail->szCachePath == NULL)
|
||
|
return E_UNEXPECTED;
|
||
|
|
||
|
ShellExecute(hwnd, NULL, m_pPathsTail->szCachePath, NULL, NULL, SW_SHOW);
|
||
|
return S_OK;
|
||
|
/*
|
||
|
int iDlgResult;
|
||
|
|
||
|
iDlgResult = MLDialogBoxWrap(MLGetHinst(), MAKEINTRESOURCE(IDD_PROP_EXPIRE), hwnd,
|
||
|
EmptyControl_PropertiesDlgProc);
|
||
|
|
||
|
return iDlgResult == IDOK ? S_OK : S_FALSE;
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CEmptyControlVolumeCache::Deactivate(DWORD *pdwFlags)
|
||
|
{
|
||
|
if (pdwFlags == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
*pdwFlags = 0;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Implementation helpers routines (private)
|
||
|
|
||
|
/*
|
||
|
static void msg_OnInitDialog(HWND hDlg);
|
||
|
static BOOL msg_OnCommand(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
|
||
|
|
||
|
static BOOL cmd_OnOK(HWND hDlg);
|
||
|
|
||
|
INT_PTR CALLBACK EmptyControl_PropertiesDlgProc(HWND hDlg,
|
||
|
UINT msg, WPARAM wp, LPARAM lp)
|
||
|
{
|
||
|
static MSD rgmsd[] = {
|
||
|
{ WM_INITDIALOG, ms_vh, (PFN)msg_OnInitDialog },
|
||
|
{ WM_COMMAND, ms_bwwwl, (PFN)msg_OnCommand },
|
||
|
{ WM_NULL, ms_end, (PFN)NULL }
|
||
|
};
|
||
|
|
||
|
return Dlg_MsgProc(rgmsd, hDlg, msg, wp, lp);
|
||
|
}
|
||
|
|
||
|
void msg_OnInitDialog(HWND hDlg)
|
||
|
{
|
||
|
UINT nDays;
|
||
|
|
||
|
CEmptyControlVolumeCache::GetDaysBeforeExpire(&nDays);
|
||
|
SetDlgItemInt(hDlg, IDC_EDIT_EXPIRE, nDays, FALSE);
|
||
|
}
|
||
|
|
||
|
BOOL msg_OnCommand(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
|
||
|
{
|
||
|
static CMD rgcmd[] = {
|
||
|
{ IDOK, 0, ms_bh, (PFN)cmd_OnOK },
|
||
|
{ 0, 0, ms_end, (PFN)NULL }
|
||
|
};
|
||
|
|
||
|
return Msg_OnCmd(rgcmd, hDlg, msg, wp, lp);
|
||
|
}
|
||
|
|
||
|
BOOL cmd_OnOK(HWND hDlg)
|
||
|
{
|
||
|
UINT nDays;
|
||
|
BOOL fWorked;
|
||
|
|
||
|
nDays = GetDlgItemInt(hDlg, IDC_EDIT_EXPIRE, &fWorked, FALSE);
|
||
|
if (!fWorked) {
|
||
|
MessageBeep(-1);
|
||
|
SetFocus(GetDlgItem(hDlg, IDC_EDIT_EXPIRE));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CEmptyControlVolumeCache::SetDaysBeforeExpire(nDays);
|
||
|
return TRUE;
|
||
|
}
|
||
|
*/
|