|
|
//////////////////////////////////////////////////////////////////////////////////////////////
//
// EmptyVolumeCache.cpp
//
// Copyright (C) 1998, 1999 Microsoft Corporation. All rights reserved.
//
// Abstract :
//
// This is the implementation of IEmptyVolumeCache
//
// History :
//
// 10/12/1999 jchauvin/luish Created
//
//////////////////////////////////////////////////////////////////////////////////////////////
#include <assert.h>
#include "AppMan.h"
#include "AppManAdmin.h"
#include "emptyvc.h"
#include "resource.h"
#include "ApplicationManager.h"
#include "AppManDebug.h"
#include "ExceptionHandler.h"
#include "ExceptionHandler.h"
#include "Lock.h"
#include "StructIdentifiers.h"
#include "Global.h"
#include "RegistryKey.h"
#ifdef DBG_MODULE
#undef DBG_MODULE
#endif
#define DBG_MODULE DBG_EMPTYVOLUMECACHE
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CEmptyVolumeCache::CEmptyVolumeCache(void) { FUNCTION("CEmptyVolumeCache::CEmptyVolumeCache (void)"); }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CEmptyVolumeCache::CEmptyVolumeCache(CApplicationManagerRoot * lpParent) { FUNCTION("CEmptyVolumeCache::CEmptyVolumeCache (CApplicationManagerRoot *pParent)");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try { assert(NULL != lpParent);
m_lpoParentObject = lpParent; m_oInformationManager.Initialize(); }
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException) { hResult = pException->GetResultCode(); delete pException; }
catch(...) { hResult = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////////////////////////
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CEmptyVolumeCache::~CEmptyVolumeCache(void) { FUNCTION("CEmptyVolumeCache::~CEmptyVolumeCache (void)"); }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEmptyVolumeCache::QueryInterface(REFIID RefIID, LPVOID * lppVoidObject) { FUNCTION("CEmptyVolumeCache::QueryInterface (REFIID RefIID, LPVOID * lppVoidObject)");
if (NULL == m_lpoParentObject) { return E_NOINTERFACE; }
return m_lpoParentObject->QueryInterface(RefIID, lppVoidObject); }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CEmptyVolumeCache::AddRef(void) { FUNCTION("CEmptyVolumeCache::AddRef (void)");
if (NULL != m_lpoParentObject) { return m_lpoParentObject->AddRef(); }
return 0; }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CEmptyVolumeCache::Release(void) { FUNCTION("CEmptyVolumeCache::Release (void)");
if (NULL != m_lpoParentObject) { return m_lpoParentObject->Release(); }
return 0; }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEmptyVolumeCache::Initialize(HKEY /*hRegKey*/, LPCWSTR lpwszVolume, LPWSTR * lppwszDisplayName, LPWSTR * lppwszDescription, DWORD * lpdwFlags) { FUNCTION("CEmptyVolumeCache::Initialize (HKEY hRegKey, LPCWSTR lpwszVolume, LPWSTR * lppwszDisplayName, LPWSTR * lppwszDescription, DWORD * lpdwFlags)");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try { CRegistryKey oRegistryKey; DWORD dwSize; DWORD dwType; CHAR cBuffer[20];
//
// Now Get Day Threshold from Registry
//
oRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VolumeCaches\\Delete Game Manager Files", KEY_READ); dwSize = sizeof(cBuffer); hResult = oRegistryKey.GetValue("DiskCleanerDayThreshold", &dwType, (LPBYTE) cBuffer, &dwSize); m_dwDiskCleanerDayThreshold = *((LPDWORD) cBuffer);
//
// Check to make sure sub key exists and correct type and size, else use default
//
if (FAILED(hResult)||(dwType != REG_DWORD)||(dwSize != sizeof(DWORD))) { m_dwDiskCleanerDayThreshold = DISKCLEANER_DAY_THRESHOLD; }
//
// Now convert Day Threshold into String
//
_ltow(m_dwDiskCleanerDayThreshold, m_wszDiskCleanerDayTH, 10);
//
// Break Strings into several parts for easier localization, and because string table is
// limited to 1024 per string
//
GetResourceStringW(IDS_DISKCLEANERNAME1, m_wszDiskCleanerName, sizeof(m_wszDiskCleanerName)); GetResourceStringW(IDS_DISKCLEANERNAME2, m_wszDiskCleanerName2, sizeof(m_wszDiskCleanerName2)); wcscat(m_wszDiskCleanerName,m_wszDiskCleanerDayTH); //Append Day Threshold
wcscat(m_wszDiskCleanerName,m_wszDiskCleanerName2); //Append Rest of String;
GetResourceStringW(IDS_DISKCLEANERDESC1, m_wszDiskCleanerDesc, sizeof(m_wszDiskCleanerDesc)); GetResourceStringW(IDS_DISKCLEANERDESC2, m_wszDiskCleanerDesc2, sizeof(m_wszDiskCleanerDesc2)); wcscat(m_wszDiskCleanerDesc,m_wszDiskCleanerDayTH); //Append Day Threshold
wcscat(m_wszDiskCleanerDesc,m_wszDiskCleanerDesc2); //Append Rest of String;
*lppwszDisplayName = (LPWSTR) m_wszDiskCleanerName; *lppwszDescription = (LPWSTR) m_wszDiskCleanerDesc;
//
// Set Volume number and make sure we are not enabled by default.
//
m_dwVolume = VolumeStringToNumber(lpwszVolume);
//
// *pdwFlags = EVCF_DONTSHOWIFZERO | EVCF_ENABLEBYDEFAULT | EVCF_ENABLEBYDEFAULT_AUTO;
//
*lpdwFlags = EVCF_DONTSHOWIFZERO; }
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException) { hResult = pException->GetResultCode(); delete pException; }
catch(...) { hResult = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////////////////////////
return hResult; } //////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEmptyVolumeCache::GetSpaceUsed(DWORDLONG * lpdwSpaceUsed, IEmptyVolumeCacheCallBack * lpCallBack) { FUNCTION("CEmptyVolumeCache::GetSpaceUsed(DWORDLONG * lpdwSpaceUsed, IEmptyVolumeCacheCallBack * lpCallBack)");
HRESULT hResult = S_OK;
try { DWORD dwKilobytes; DWORDLONG dwlSpaceUtilization;
GetSpaceUtilization(m_dwVolume, m_dwDiskCleanerDayThreshold, (LPDWORD) &dwKilobytes, lpCallBack); dwlSpaceUtilization = (DWORDLONG)(dwKilobytes)*(DWORDLONG)1024;
(*lpdwSpaceUsed) = dwlSpaceUtilization; }
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException) { hResult = pException->GetResultCode(); delete pException; }
catch(...) { hResult = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////////////////////////
return hResult; } //////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEmptyVolumeCache::Purge(DWORDLONG dwSpaceToFree, IEmptyVolumeCacheCallBack * lpCallBack) {
FUNCTION("CEmptyVolumeCache::Purge(DWORDLONG dwSpaceToFree, IEmptyVolumeCacheCallBack * lpCallBack)");
HRESULT hResult = S_OK; ///////////////////////////////////////////////////////////////////////////////////////
try { DWORD dwKilobytes;
dwKilobytes = (DWORD) (dwSpaceToFree / 1024);
hResult = CleanDisk(m_dwVolume, m_dwDiskCleanerDayThreshold, dwKilobytes, lpCallBack);
if (FAILED(hResult)) { THROW(hResult); } }
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException) { hResult = pException->GetResultCode(); delete pException; }
catch(...) { hResult = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////////////////////////
return hResult; } //////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEmptyVolumeCache::ShowProperties(HWND /*hwnd*/) { return S_OK; }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CEmptyVolumeCache::Deactivate(DWORD * /*pdwFlags*/) { return S_OK; } //////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CEmptyVolumeCache::GetSpaceUtilization(DWORD dwDeviceIndex, DWORD dwDays, LPDWORD lpdwKilobytes, IEmptyVolumeCacheCallBack * lpCallBack) { FUNCTION("CEmptyVolumeCache::GetSpaceUtilization(DWORD dwDeviceIndex, DWORD dwDays, LPDWORD lpdwKilobytes, IEmptyVolumeCacheCallBack * lpCallBack)");
HRESULT hResult = S_OK; DWORD dwKilobytesAvailable = 0;
///////////////////////////////////////////////////////////////////////////////////////
try { DEVICE_RECORD sDeviceRecord; APPLICATION_DATA sApplicationData; DWORD dwElapsedDays; SYSTEMTIME stLastUsedDate;
//
// Record the initial state
//
if (FAILED(m_oInformationManager.GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord))) { THROW(E_UNEXPECTED); }
//
// Go through each application to determine removable diskspace consumed by game apps
// that have been last accessed over X days ago, where X = DiskCleanerDayThreshold value
// from registry. These are candidates for downsizing.
// Note: X default value = 120 days. Also, pinned apps are not considered candidates for
// downsizing, regardless of age.
//
if (S_OK == m_oInformationManager.GetOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)) { do { //
// Get the age of the application
//
stLastUsedDate = sApplicationData.sAgingInfo.stLastUsedDate; dwElapsedDays = ElapsedDays(&stLastUsedDate);
//
// Determine amount that can be freed sApplicationRecord
//
if ((dwElapsedDays >= dwDays)&&(APP_CATEGORY_ENTERTAINMENT & sApplicationData.sBaseInfo.dwCategory)&&(sApplicationData.sBaseInfo.dwPinState == 0)) { dwKilobytesAvailable += sApplicationData.sBaseInfo.dwRemovableKilobytes; hResult = lpCallBack->ScanProgress(dwKilobytesAvailable*1024, 0, NULL);
if(FAILED(hResult)) { THROW(E_UNEXPECTED); } } } while ((dwElapsedDays >= dwDays)&&(S_OK == m_oInformationManager.GetNextOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData))); }
//
// Now pass back the available kilobytes
//
*lpdwKilobytes = dwKilobytesAvailable; }
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException) { hResult = pException->GetResultCode(); delete pException; }
catch(...) { hResult = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////////////////////////
hResult = lpCallBack->ScanProgress(dwKilobytesAvailable * 1024, EVCCBF_LASTNOTIFICATION, NULL); if(FAILED(hResult)) { hResult = E_UNEXPECTED; }
return hResult; }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CEmptyVolumeCache::CleanDisk(DWORD dwDeviceIndex, DWORD dwDays, DWORD dwKilobytesToFree, IEmptyVolumeCacheCallBack * lpCallBack) { FUNCTION("CEmptyVolumeCache::CleanDisk(DWORD dwDeviceIndex, DWORD dwDays, DWORD dwKilobytesToFree, IEmptyVolumeCacheCallBack * lpCallBack)");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try { DEVICE_SPACE_INFO sDeviceSpaceInfo; APPLICATION_DATA sApplicationData; DWORD dwKilobytesFreed; DWORD dwElapsedDays; DWORDLONG dwlMBFreed; DWORDLONG dwlMBToFree; SYSTEMTIME stLastUsedDate;
if (FAILED(m_oInformationManager.GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo))) { THROW(E_UNEXPECTED); }
//
// Record the initial state
//
dwlMBToFree = dwKilobytesToFree * 1024; dwlMBFreed = 0;
//
// Downsize removable diskspace consumed by game apps that have been last accessed over
// X days ago, where X = DiskCleanerDayThreshold value from registry.
// Note: X default value = 120 days. Also, pinned apps are not downsized,
// regardless of age.
//
if (S_OK == m_oInformationManager.GetOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)) { do { //
// Get the age of the application
//
stLastUsedDate = sApplicationData.sAgingInfo.stLastUsedDate; dwElapsedDays = ElapsedDays(&stLastUsedDate);
//
// Determine amount that can be freed sApplicationRecord
//
if ((dwElapsedDays >= dwDays)&&(APP_CATEGORY_ENTERTAINMENT & sApplicationData.sBaseInfo.dwCategory)&&(sApplicationData.sBaseInfo.dwPinState == 0)) { m_oInformationManager.DownsizeApplication(sApplicationData.sBaseInfo.dwRemovableKilobytes, &sApplicationData); dwKilobytesFreed = sApplicationData.sBaseInfo.dwRemovableKilobytes; dwlMBFreed += (DWORDLONG)dwKilobytesFreed*(DWORDLONG)1024; //dwlMBFreed is cumulative up to that point
hResult = lpCallBack->PurgeProgress(dwlMBFreed,dwlMBToFree-dwlMBFreed, 0,NULL); if (FAILED(hResult)) { THROW(E_UNEXPECTED); } } } while ((dwElapsedDays >= dwDays)&&(S_OK == m_oInformationManager.GetNextOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)));
hResult = lpCallBack->PurgeProgress(dwlMBFreed,dwlMBToFree-dwlMBFreed, EVCCBF_LASTNOTIFICATION,NULL); if (FAILED(hResult)) { THROW(E_UNEXPECTED); } } }
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException) { hResult = pException->GetResultCode(); delete pException; }
catch(...) { hResult = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////////////////////////
return hResult; }
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Miscellaneous functions
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD CEmptyVolumeCache::VolumeStringToNumber(LPCWSTR lpszVolume) { FUNCTION("CEmptyVolumeCache::VolumeStringToNumber(LPCWSTR lpszVolume)");
WORD wDrive; DWORD dwDrive;
//
// First get the first DWORD which makes up the drive label (i.e. c:\)
//
wDrive = *(WORD *) lpszVolume;
//
// Now convert the character to uppercase
//
dwDrive = toupper((INT) wDrive);
//
// Now Subtract the ASCII index off to have a drive number from 0 - 25.
//
dwDrive -= 65;
return dwDrive; }
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD CEmptyVolumeCache::ElapsedDays(SYSTEMTIME * lpLastUsedDate) {
FUNCTION("CEmptyVolumeCache::ElapsedDays(SYSTEMTIME * lpLastUsedDate)"); SYSTEMTIME stTodaysDate; FILETIME ftTodaysDate, ftLastUsedDate; DWORDLONG dwlTodaysDate, dwlLastUsedDate;
DWORD dwElapsedDays;
GetLocalTime(&stTodaysDate);
//
// Convert from systemtime to filetime
//
SystemTimeToFileTime(&stTodaysDate,&ftTodaysDate); SystemTimeToFileTime(lpLastUsedDate, &ftLastUsedDate);
//
// Copy to a DWORDLONG element
//
memcpy((void *)&dwlTodaysDate,(void *)&ftTodaysDate,sizeof(DWORDLONG)); memcpy((void *)&dwlLastUsedDate,(void *)&ftLastUsedDate,sizeof(DWORDLONG));
// Conversion: 100 nsec to days
//
// 10000000 (100 nsec) 60 sec 60 min 24 hours 864000000000 (100 nsec)
// ------------------- x ------ x ------- x -------- = -----------------------
// sec min hour day day
//
if (dwlTodaysDate <= dwlLastUsedDate) { dwElapsedDays = 0; } else { dwElapsedDays = (DWORD)((dwlTodaysDate - dwlLastUsedDate) / (DWORDLONG) 864000000000); }
return dwElapsedDays; }
|