Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

511 lines
14 KiB

/******************************************************************
Copyright (c) 2000 Microsoft Corporation
diskcleanup.cpp -- disk cleanup COM object for SR
Description:
delete datastores from stale builds
******************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windef.h>
#include <wtypes.h>
#include <winuser.h>
#include "diskcleanup.h"
#include "resource.h"
#include <utils.h>
#include <srdefs.h>
extern HMODULE ghModule;
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::LoadBootIni
//
// Synopsis: parse the boot.ini file
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CSREmptyVolumeCache2::LoadBootIni()
{
HANDLE hFile = INVALID_HANDLE_VALUE;
WCHAR *pwszThisGuid = NULL;
CHAR *pszContent = NULL;
CHAR *pszLine = NULL;
DWORD dwErr = ERROR_SUCCESS;
CHAR szArcName[MAX_PATH];
CHAR szOptions[MAX_PATH];
pwszThisGuid = GetMachineGuid (); // always exclude the current datastore
if (pwszThisGuid != NULL && pwszThisGuid[0] != L'\0')
{
lstrcpyW (_wszGuid[_ulGuids], s_cszRestoreDir);
lstrcatW (_wszGuid[_ulGuids], pwszThisGuid );
_ulGuids++;
}
// Read the contents of the boot.ini file into a string.
hFile = CreateFileW (L"c:\\boot.ini",
GENERIC_READ,
FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwErr = GetLastError();
return dwErr;
}
DWORD dwBytesRead = 0;
DWORD dwBytesToRead = GetFileSize(hFile, NULL);
if (dwBytesToRead == 0xFFFFFFFF || 0 == dwBytesToRead)
{
dwErr = GetLastError();
goto Err;
}
pszContent = new CHAR [dwBytesToRead];
if (pszContent == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto Err;
}
if (FALSE==ReadFile(hFile, pszContent, dwBytesToRead, &dwBytesRead, NULL))
{
dwErr = GetLastError();
goto Err;
}
if (dwBytesToRead != dwBytesRead)
{
dwErr = ERROR_READ_FAULT;
goto Err;
}
CloseHandle (hFile);
hFile = INVALID_HANDLE_VALUE;
pszLine = pszContent;
for (UINT i = 0; i < dwBytesRead; i++)
{
if (pszContent[i] == '=') // field indicator
pszContent[i] = '\0'; // process only the 1st field
if (pszContent[i] == '\n') // end-of-line indicator
{
pszContent[i] = '\0';
if (strncmp (pszLine, "multi", 5) == 0)
{
HANDLE hGuidFile;
WCHAR wcsPath[MAX_PATH];
WCHAR wcsGuid [RESTOREGUID_STRLEN];
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
IO_STATUS_BLOCK iosb;
wsprintfW (wcsPath, L"\\ArcName\\%hs\\System32\\Restore\\"
L"MachineGuid.txt", pszLine);
RtlInitUnicodeString (&us, wcsPath);
InitializeObjectAttributes ( &oa, &us, OBJ_CASE_INSENSITIVE,
NULL, NULL);
NTSTATUS nts = NtCreateFile (&hGuidFile,
FILE_GENERIC_READ,
&oa,
&iosb,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE | FILE_SHARE_DELETE | FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(nts))
{
dwErr = RtlNtStatusToDosError (nts);
}
else
{
dwBytesToRead = RESTOREGUID_STRLEN * sizeof(WCHAR);
DWORD dwRead = 0;
dwErr = ERROR_SUCCESS;
if (FALSE == ReadFile (hGuidFile, (BYTE *) wcsGuid,
dwBytesToRead, &dwRead, NULL))
{
dwErr = GetLastError();
}
if (_ulGuids < ARRAYSIZE && ERROR_SUCCESS == dwErr)
{
lstrcpyW (_wszGuid[_ulGuids], s_cszRestoreDir);
lstrcatW (_wszGuid[_ulGuids], (wcsGuid[0]==0xFEFF) ?
&wcsGuid[1] : wcsGuid );
_ulGuids++;
}
NtClose (hGuidFile);
}
}
pszLine = &pszContent [i+1]; // skip to next line
}
}
Err:
if (pszContent != NULL)
delete [] pszContent;
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle (hFile);
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::EnumDataStores
//
// Synopsis: enumerate the data store on a volume
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CSREmptyVolumeCache2::EnumDataStores (DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb,
BOOL fPurge,
WCHAR *pwszVolume)
{
HANDLE hFind = NULL;
DWORD dwErr = ERROR_SUCCESS;
WIN32_FIND_DATA wfd;
WCHAR wcsPath [MAX_PATH];
*pdwlSpaceUsed = 0;
if (pwszVolume == NULL || pwszVolume[0] == L'\0') // no volume defined
return dwErr;
wsprintfW (wcsPath, L"%s%s\\%s*", pwszVolume,
s_cszSysVolInfo, s_cszRestoreDir);
hFind = FindFirstFileW (wcsPath, &wfd);
if (hFind == INVALID_HANDLE_VALUE) // no files
return dwErr;
do
{
if (TRUE == _fStop)
{
FindClose (hFind);
return ERROR_OPERATION_ABORTED;
}
if (!lstrcmp(wfd.cFileName, L".") || !lstrcmp(wfd.cFileName, L".."))
continue;
for (UINT i=0; i < _ulGuids; i++)
{
if (lstrcmpi (_wszGuid[i], wfd.cFileName) == 0)
{
break; // data store match
}
}
if (i >= _ulGuids) // no data store match
{
if (picb != NULL)
{
WCHAR wcsDataStore[MAX_PATH];
lstrcpyW (wcsPath, pwszVolume);
lstrcatW (wcsPath, s_cszSysVolInfo);
lstrcatW (wcsPath, L"\\");
lstrcatW (wcsPath, wfd.cFileName);
if (!fPurge) // calculate space usage
{
dwErr = GetFileSize_Recurse (wcsPath,
(INT64*) pdwlSpaceUsed,
&_fStop);
}
else // delete the data store
{
dwErr = Delnode_Recurse (wcsPath, TRUE, &_fStop);
}
}
else
{
*pdwlSpaceUsed = 1; // indicate something to clean up
}
}
}
while (FindNextFileW (hFind, &wfd));
FindClose (hFind);
if (picb != NULL) // update the progress bar
{
if (!fPurge)
picb->ScanProgress (*pdwlSpaceUsed, EVCCBF_LASTNOTIFICATION , NULL);
else
picb->PurgeProgress (*pdwlSpaceUsed,0,EVCCBF_LASTNOTIFICATION,NULL);
}
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::ForAllMountPoints
//
// Synopsis: call EnumerateDataStores for each mount point
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
HRESULT CSREmptyVolumeCache2::ForAllMountPoints (DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb,
BOOL fPurge)
{
DWORD dwErr = ERROR_SUCCESS;
dwErr = EnumDataStores (pdwlSpaceUsed, picb, fPurge, _wszVolume);
if (ERROR_SUCCESS == dwErr)
{
WCHAR wszMount [MAX_PATH];
HANDLE hFind = FindFirstVolumeMountPoint (_wszVolume,wszMount,MAX_PATH);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
dwErr = EnumDataStores (pdwlSpaceUsed, picb, fPurge, wszMount);
if (dwErr != ERROR_SUCCESS)
break;
}
while (FindNextVolumeMountPoint (hFind, wszMount, MAX_PATH));
FindVolumeMountPointClose (hFind);
}
}
return HRESULT_FROM_WIN32 (dwErr);
}
//+---------------------------------------------------------------------------
//
// Function: CSRClassFactory::CreateInstance
//
// Synopsis: create the disk cleanup plugin object
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
HRESULT CSRClassFactory::CreateInstance (IUnknown *pUnkOuter,
REFIID riid,
void **ppvObject)
{
HRESULT hr = S_OK;
if (pUnkOuter != NULL)
return CLASS_E_NOAGGREGATION;
CSREmptyVolumeCache2 *pevc = new CSREmptyVolumeCache2();
if (pevc == NULL)
return E_OUTOFMEMORY;
hr = pevc->QueryInterface (riid, ppvObject);
pevc->Release(); // release constructor's reference
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::InitializeEx
//
// Synopsis: initialize the disk cleanup plugin object
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
HRESULT CSREmptyVolumeCache2::InitializeEx (
HKEY hkRegKey,
const WCHAR *pcwszVolume,
const WCHAR *pcwszKeyName,
WCHAR **ppwszDisplayName,
WCHAR **ppwszDescription,
WCHAR **ppwszBtnText,
DWORD *pdwFlags)
{
DWORDLONG dwlSpaceUsed = 0;
WCHAR *pwszDisplay = NULL;
WCHAR *pwszDescription = NULL;
HRESULT hr=S_OK;
pwszDisplay = (WCHAR *) CoTaskMemAlloc (MAX_PATH / 2 * sizeof(WCHAR));
if (NULL == pwszDisplay)
{
hr = E_OUTOFMEMORY;
goto Err;
}
pwszDescription = (WCHAR *) CoTaskMemAlloc (MAX_PATH * 2 * sizeof(WCHAR));
if (NULL == pwszDescription)
{
hr = E_OUTOFMEMORY;
goto Err;
}
if (0 == LoadStringW (ghModule, IDS_DISKCLEANUP_DISPLAY,
pwszDisplay, MAX_PATH / 2))
{
hr = HRESULT_FROM_WIN32 (GetLastError());
goto Err;
}
if (0 == LoadStringW (ghModule, IDS_DISKCLEANUP_DESCRIPTION,
pwszDescription, MAX_PATH * 2))
{
hr = HRESULT_FROM_WIN32 (GetLastError());
goto Err;
}
lstrcpyW (_wszVolume, pcwszVolume);
LoadBootIni(); // best effort, okay to fail
ForAllMountPoints (&dwlSpaceUsed, NULL, FALSE);
if (pdwFlags)
{
*pdwFlags |= (EVCF_ENABLEBYDEFAULT |
EVCF_ENABLEBYDEFAULT_AUTO |
EVCF_DONTSHOWIFZERO);
}
if (dwlSpaceUsed == 0)
hr = S_FALSE;
Err:
if (FAILED(hr))
{
if (pwszDisplay)
CoTaskMemFree (pwszDisplay);
if (pwszDescription)
CoTaskMemFree (pwszDescription);
if (ppwszDisplayName)
*ppwszDisplayName = NULL;
if (ppwszDescription)
*ppwszDescription = NULL;
}
else
{
if (ppwszDisplayName)
*ppwszDisplayName = pwszDisplay;
if (ppwszDescription)
*ppwszDescription = pwszDescription;
}
if (ppwszBtnText) // no advanced button text
*ppwszBtnText = NULL;
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::GetSpaceUsed
//
// Synopsis: returns how much space can be freed on a volume
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
HRESULT CSREmptyVolumeCache2::GetSpaceUsed ( DWORDLONG *pdwlSpaceUsed,
IEmptyVolumeCacheCallBack *picb)
{
return ForAllMountPoints (pdwlSpaceUsed, picb, FALSE);
}
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::Purge
//
// Synopsis: frees the disk space on a volume
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
HRESULT CSREmptyVolumeCache2::Purge ( DWORDLONG dwlSpaceToFree,
IEmptyVolumeCacheCallBack *picb)
{
return ForAllMountPoints (&dwlSpaceToFree, picb, TRUE);
}
//+---------------------------------------------------------------------------
//
// Function: CSREmptyVolumeCache2::Deactivate
//
// Synopsis: signal the disk cleanup plugin to stop processing
//
// Arguments:
//
// History: 20-Jul-2000 HenryLee Created
//
//----------------------------------------------------------------------------
HRESULT CSREmptyVolumeCache2::Deactivate (DWORD *pdwFlags)
{
HRESULT hr=S_OK;
if (pdwFlags)
*pdwFlags = 0; // no flags to be returned
_fStop = TRUE;
return hr;
}