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.
1390 lines
34 KiB
1390 lines
34 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
backup.cpp
|
|
|
|
Abstract:
|
|
|
|
main module of backup test exe
|
|
|
|
|
|
Brian Berkowitz [brianb] 05/23/2000
|
|
|
|
TBD:
|
|
|
|
|
|
Revision History:
|
|
|
|
Name Date Comments
|
|
brianb 05/23/2000 Created
|
|
brianb 06/16/2000 Added comments
|
|
|
|
--*/
|
|
|
|
#include <stdafx.h>
|
|
#include <vststmsgclient.hxx>
|
|
#include <tstiniconfig.hxx>
|
|
#include <vststprocess.hxx>
|
|
#include <vss.h>
|
|
#include <vswriter.h>
|
|
#include <vsbackup.h>
|
|
#include <vststparser.hxx>
|
|
#include <vststutil.hxx>
|
|
#include <vststvolinfo.hxx>
|
|
#include <backup.h>
|
|
|
|
void LogUnexpectedFailure(LPCWSTR wsz, ...);
|
|
|
|
|
|
// selection of volumes
|
|
static LPCWSTR x_wszVolumeBackup = L"VolumeBackup";
|
|
static LPCWSTR x_wszSome = L"Some";
|
|
static LPCWSTR x_wszOne = L"One";
|
|
static LPCWSTR x_wszAll = L"All";
|
|
|
|
// selection of file system type
|
|
static LPCWSTR x_wszFileSystemBackup = L"FileSystemBackup";
|
|
static LPCWSTR x_wszNTFS = L"NTFS";
|
|
static LPCWSTR x_wszFAT32 = L"FAT32";
|
|
static LPCWSTR x_wszFAT16 = L"FAT16";
|
|
static LPCWSTR x_wszRAW = L"RAW";
|
|
|
|
// what to backup
|
|
static LPCWSTR x_wszBackingUp = L"BackingUp";
|
|
static LPCWSTR x_wszSerialVolumes = L"Serial";
|
|
static LPCWSTR x_wszVolumes = L"Volumes";
|
|
static LPCWSTR x_wszComponents = L"Components";
|
|
|
|
// cancelling async operations
|
|
static LPCWSTR x_wszCancelPrepareBackup = L"CancelPrepareBackup";
|
|
static LPCWSTR x_wszCancelDoSnapshotSet = L"CancelDoSnapshotSet";
|
|
static LPCWSTR x_wszCancelBackupComplete = L"CancelBackupComplete";
|
|
|
|
// wait time interval
|
|
static LPCWSTR x_wszWaitInterval = L"WaitInterval";
|
|
|
|
|
|
// volumes to exclude
|
|
static LPCWSTR x_wszExcludeVolumes = L"ExcludeVolumes";
|
|
|
|
// volumes to include
|
|
static LPCWSTR x_wszVolumeList = L"VolumeList";
|
|
|
|
// volumes to fill with data
|
|
static LPCWSTR x_wszFillVolumes = L"FillVolumes";
|
|
static LPCWSTR x_wszFillVolumesOptRandom = L"Random";
|
|
static LPCWSTR x_wszFillVolumesOptSelected = L"Selected";
|
|
static LPCWSTR x_wszFillVolumesOptNone = L"None";
|
|
|
|
// whether volumes filled with data should be fragmented
|
|
static LPCWSTR x_wszFillVolumesOptFragment = L"Fragment";
|
|
|
|
// which volumes to fill
|
|
static LPCWSTR x_wszFillVolumesList = L"FillVolumesList";
|
|
|
|
// constructor
|
|
CVsBackupTest::CVsBackupTest() :
|
|
m_bTerminateTest(false),
|
|
m_bBackupNTFS(false),
|
|
m_bBackupFAT32(false),
|
|
m_bBackupFAT16(false),
|
|
m_bBackupRAW(false),
|
|
m_bSerialBackup(false),
|
|
m_bVolumeBackup(false),
|
|
m_bComponentBackup(false),
|
|
m_cyclesCancelPrepareBackup(0),
|
|
m_cyclesCancelDoSnapshotSet(0),
|
|
m_cyclesCancelBackupComplete(0),
|
|
m_cVolumes(0),
|
|
m_cVolumesLeft(0),
|
|
m_cSnapshotSets(0),
|
|
m_cExcludedVolumes(0),
|
|
m_rgwszExcludedVolumes(NULL),
|
|
m_cIncludedVolumes(0),
|
|
m_rgwszIncludedVolumes(NULL),
|
|
m_bRandomFills(false),
|
|
m_bFragmentWhenFilling(false),
|
|
m_rgwszFillVolumes(NULL),
|
|
m_cFillVolumes(0)
|
|
{
|
|
}
|
|
|
|
// delete an array of strings
|
|
void CVsBackupTest::DeleteVolumeList(LPWSTR *rgwsz, UINT cwsz)
|
|
{
|
|
if (rgwsz)
|
|
{
|
|
for(UINT iwsz = 0; iwsz < cwsz; iwsz++)
|
|
delete rgwsz[iwsz];
|
|
}
|
|
|
|
delete rgwsz;
|
|
}
|
|
|
|
|
|
// destructor
|
|
CVsBackupTest::~CVsBackupTest()
|
|
{
|
|
// delete any snapshot sets that are cached
|
|
if (m_cSnapshotSets)
|
|
DeleteCachedSnapshotSets();
|
|
|
|
delete m_wszVolumesSnapshot;
|
|
|
|
// delete various lists of volumes (string arrays)
|
|
DeleteVolumeList(m_rgwszExcludedVolumes, m_cExcludedVolumes);
|
|
DeleteVolumeList(m_rgwszIncludedVolumes, m_cIncludedVolumes);
|
|
DeleteVolumeList(m_rgwszFillVolumes, m_cFillVolumes);
|
|
}
|
|
|
|
// enable a privilege
|
|
BOOL CVsBackupTest::AssertPrivilege(LPCWSTR privName)
|
|
{
|
|
HANDLE tokenHandle;
|
|
BOOL stat = FALSE;
|
|
|
|
if (OpenProcessToken
|
|
(
|
|
GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
|
|
&tokenHandle
|
|
))
|
|
{
|
|
LUID value;
|
|
|
|
// obtain privilige value
|
|
if (LookupPrivilegeValue( NULL, privName, &value ))
|
|
{
|
|
TOKEN_PRIVILEGES newState;
|
|
DWORD error;
|
|
|
|
newState.PrivilegeCount = 1;
|
|
newState.Privileges[0].Luid = value;
|
|
newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
|
|
|
|
/*
|
|
* We will always call GetLastError below, so clear
|
|
* any prior error values on this thread.
|
|
*/
|
|
SetLastError( ERROR_SUCCESS );
|
|
|
|
stat = AdjustTokenPrivileges
|
|
(
|
|
tokenHandle,
|
|
FALSE,
|
|
&newState,
|
|
(DWORD)0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
/*
|
|
* Supposedly, AdjustTokenPriveleges always returns TRUE
|
|
* (even when it fails). So, call GetLastError to be
|
|
* extra sure everything's cool.
|
|
*/
|
|
if ((error = GetLastError()) != ERROR_SUCCESS)
|
|
stat = FALSE;
|
|
|
|
if (!stat)
|
|
{
|
|
char buf[128];
|
|
sprintf
|
|
(
|
|
buf,
|
|
"AdjustTokenPrivileges for %s failed with %d",
|
|
privName,
|
|
error
|
|
);
|
|
|
|
LogFailure(buf);
|
|
}
|
|
}
|
|
|
|
CloseHandle(tokenHandle);
|
|
}
|
|
|
|
return stat;
|
|
}
|
|
|
|
// build a list of volumes
|
|
void CVsBackupTest::BuildVolumeList
|
|
(
|
|
LPCWSTR wszOption,
|
|
UINT *pcVolumes,
|
|
LPWSTR **prgwszVolumes
|
|
)
|
|
{
|
|
// delete existing volume list
|
|
DeleteVolumeList(*prgwszVolumes, *pcVolumes);
|
|
*prgwszVolumes = NULL;
|
|
*pcVolumes = 0;
|
|
|
|
// get option value
|
|
CBsString bssVolumes;
|
|
m_pConfig->GetOptionValue(wszOption, &bssVolumes);
|
|
|
|
// split into seperate strings for each volume
|
|
LPCWSTR wszEnd = CVsTstParser::SplitOptions(bssVolumes);
|
|
LPCWSTR wszStart = bssVolumes;
|
|
UINT cVolumes = 0;
|
|
|
|
// count number of volumes in exclude list
|
|
while(wszStart < wszEnd)
|
|
{
|
|
cVolumes++;
|
|
wszStart += wcslen(wszStart) + 1;
|
|
}
|
|
|
|
// allocate array for strings
|
|
*prgwszVolumes = new LPWSTR[cVolumes];
|
|
if (*prgwszVolumes == NULL)
|
|
{
|
|
LogUnexpectedFailure(L"Out of Memory");
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
wszStart = bssVolumes;
|
|
for (UINT iVolume = 0; iVolume < cVolumes; iVolume++)
|
|
{
|
|
// extract a string value
|
|
LPWSTR wszNew = new WCHAR[wcslen(wszStart) + 2];
|
|
if (wszNew == NULL)
|
|
{
|
|
LogUnexpectedFailure(L"Out of Memory");
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
UINT cwc = (UINT) wcslen(wszStart);
|
|
|
|
memcpy(wszNew, wszStart, cwc * sizeof(WCHAR));
|
|
wszStart += cwc + 1;
|
|
|
|
// add trailing backslash if not there in order to convert
|
|
// into a path to the root directory on the voloume
|
|
if (wszNew[cwc-1] != L'\\')
|
|
wszNew[cwc++] = L'\\';
|
|
|
|
wszNew[cwc] = L'\0';
|
|
|
|
WCHAR wsz[MAX_PATH];
|
|
// get unique volume name
|
|
if (!GetVolumeNameForVolumeMountPoint(wszNew, wsz, MAX_PATH))
|
|
{
|
|
delete wszNew;
|
|
LogUnexpectedFailure
|
|
(
|
|
L"Cannot find unique volume name for volume volume %s due to error %d.",
|
|
wszStart,
|
|
GetLastError()
|
|
);
|
|
}
|
|
else
|
|
{
|
|
delete wszNew;
|
|
|
|
// allocate new string for unique volume name
|
|
(*prgwszVolumes)[*pcVolumes] = new WCHAR[wcslen(wsz) + 1];
|
|
if ((*prgwszVolumes)[*pcVolumes] == NULL)
|
|
{
|
|
LogUnexpectedFailure(L"Out of Memory");
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
wcscpy((*prgwszVolumes)[*pcVolumes], wsz);
|
|
|
|
// incrmement count of volumes
|
|
*pcVolumes += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// callback to run the test
|
|
HRESULT CVsBackupTest::RunTest
|
|
(
|
|
CVsTstINIConfig *pConfig, // configuration file (selected section)
|
|
CVsTstClientMsg *pClient, // message pipe
|
|
CVsTstParams *pParams // command line parameters
|
|
)
|
|
{
|
|
// save supplied parameters
|
|
m_pConfig = pConfig;
|
|
m_pParams = pParams;
|
|
SetClientMsg(pClient);
|
|
|
|
try
|
|
{
|
|
// make sure that backup privileges are enabled
|
|
if (!AssertPrivilege(SE_BACKUP_NAME))
|
|
{
|
|
LogFailure("Unable to assert backup privilege");
|
|
throw E_UNEXPECTED;
|
|
}
|
|
|
|
// determine what we are backing up
|
|
CBsString bssBackingUp;
|
|
m_pConfig->GetOptionValue(x_wszBackingUp, &bssBackingUp);
|
|
|
|
// determe the type of volume backup being performed
|
|
CBsString bssVolumeBackup;
|
|
m_pConfig->GetOptionValue(x_wszVolumeBackup, &bssVolumeBackup);
|
|
|
|
// determine which volumes are being backed up
|
|
CBsString bssFilesystemBackup;
|
|
m_pConfig->GetOptionValue(x_wszFileSystemBackup, &bssFilesystemBackup);
|
|
|
|
// get value of FillVolumes option
|
|
CBsString bssFillVolumes;
|
|
m_pConfig->GetOptionValue(x_wszFillVolumes, &bssFillVolumes);
|
|
|
|
|
|
// get cancel test options
|
|
m_pConfig->GetOptionValue(x_wszCancelPrepareBackup, &m_llCancelPrepareBackupLow, &m_llCancelPrepareBackupHigh);
|
|
m_pConfig->GetOptionValue(x_wszCancelDoSnapshotSet, &m_llCancelDoSnapshotSetLow, &m_llCancelDoSnapshotSetHigh);
|
|
m_pConfig->GetOptionValue(x_wszCancelBackupComplete, &m_llCancelBackupCompleteLow, &m_llCancelBackupCompleteHigh);
|
|
|
|
|
|
// get wait time interval
|
|
LONGLONG llWaitTimeLow, llWaitTimeHigh;
|
|
m_pConfig->GetOptionValue(x_wszWaitInterval, &llWaitTimeLow, &llWaitTimeHigh);
|
|
m_waitTime = (UINT) llWaitTimeLow;
|
|
|
|
// determine type of backup
|
|
if (_wcsicmp(bssBackingUp, x_wszComponents) == 0)
|
|
m_bComponentBackup = true;
|
|
else if (_wcsicmp(bssBackingUp, x_wszVolumes) == 0)
|
|
m_bVolumeBackup = true;
|
|
else if (_wcsicmp(bssBackingUp, x_wszSerialVolumes) == 0)
|
|
m_bSerialBackup = true;
|
|
|
|
// determine how many volumes are snapshot
|
|
if (_wcsicmp(bssVolumeBackup, x_wszAll) == 0)
|
|
m_backupVolumes = VSTST_BV_ALL;
|
|
else if (_wcsicmp(bssVolumeBackup, x_wszSome) == 0)
|
|
m_backupVolumes = VSTST_BV_SOME;
|
|
else if (_wcsicmp(bssVolumeBackup, x_wszOne) == 0)
|
|
m_backupVolumes = VSTST_BV_ONE;
|
|
|
|
// determine which file systems are backed up
|
|
LPCWSTR wszEnd = CVsTstParser::SplitOptions(bssFilesystemBackup);
|
|
LPCWSTR wszStart = bssFilesystemBackup;
|
|
while(wszStart < wszEnd)
|
|
{
|
|
if (_wcsicmp(wszStart, x_wszAll) == 0)
|
|
{
|
|
m_bBackupNTFS = true;
|
|
m_bBackupFAT16 = true;
|
|
m_bBackupFAT32 = true;
|
|
m_bBackupRAW = true;
|
|
break;
|
|
}
|
|
|
|
else if (_wcsicmp(wszStart, x_wszNTFS) == 0)
|
|
m_bBackupNTFS = true;
|
|
else if (_wcsicmp(wszStart, x_wszFAT32) == 0)
|
|
m_bBackupFAT32 = true;
|
|
else if (_wcsicmp(wszStart, x_wszFAT16) == 0)
|
|
m_bBackupFAT16 = true;
|
|
else if (_wcsicmp(wszStart, x_wszRAW) == 0)
|
|
m_bBackupRAW = true;
|
|
|
|
wszStart += wcslen(wszStart) + 1;
|
|
}
|
|
|
|
// build list of excluded volumes
|
|
BuildVolumeList
|
|
(
|
|
x_wszExcludeVolumes,
|
|
&m_cExcludedVolumes,
|
|
&m_rgwszExcludedVolumes
|
|
);
|
|
|
|
// build list of included volumes
|
|
BuildVolumeList
|
|
(
|
|
x_wszVolumeList,
|
|
&m_cIncludedVolumes,
|
|
&m_rgwszIncludedVolumes
|
|
);
|
|
|
|
// build list of volumes to fill
|
|
BuildVolumeList
|
|
(
|
|
x_wszFillVolumesList,
|
|
&m_cFillVolumes,
|
|
&m_rgwszFillVolumes
|
|
);
|
|
|
|
// log information about the test
|
|
LogMessage("Starting Backup test.\n");
|
|
if (m_bVolumeBackup || m_bSerialBackup)
|
|
{
|
|
LogMessage("Performing volume backup\n");
|
|
|
|
if (m_bSerialBackup)
|
|
LogMessage("Serially backing up volumes\n");
|
|
|
|
if (m_bBackupNTFS && m_bBackupFAT32 &&
|
|
m_bBackupRAW && m_bBackupFAT16)
|
|
LogMessage("Backing up all file systems\n");
|
|
else
|
|
{
|
|
if (m_bBackupNTFS)
|
|
LogMessage("Backing up NTFS volumes.\n");
|
|
if (m_bBackupFAT32)
|
|
LogMessage("Backing up FAT32 volumes.\n");
|
|
if (m_bBackupFAT16)
|
|
LogMessage("Backing up FAT16 volumes.\n");
|
|
if (m_bBackupRAW)
|
|
LogMessage("Backing up RAW volumes.\n");
|
|
}
|
|
|
|
if (m_backupVolumes == VSTST_BV_ONE)
|
|
LogMessage("Backing up one volume at a time");
|
|
else if (m_backupVolumes == VSTST_BV_SOME)
|
|
LogMessage("Backing up multiple volumes at a time");
|
|
else if (m_backupVolumes == VSTST_BV_ALL)
|
|
LogMessage("Backing up all volumes at once");
|
|
}
|
|
else
|
|
LogMessage("Performing component backup.\n");
|
|
|
|
if (m_llCancelPrepareBackupHigh > 0i64)
|
|
LogMessage("Cancel during PrepareBackup.\n");
|
|
|
|
if (m_llCancelDoSnapshotSetHigh > 0i64)
|
|
LogMessage("Cancel during DoSnapshotSet.\n");
|
|
|
|
if (m_llCancelBackupCompleteHigh > 0i64)
|
|
LogMessage("Cancel during BackupComplete.\n");
|
|
|
|
// run the test until told to terminate the test
|
|
while(!m_bTerminateTest)
|
|
RunBackupTest();
|
|
|
|
LogMessage("Ending backup test.\n");
|
|
}
|
|
catch(...)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// routine to handle waiting for an asynchronous operation to compelte
|
|
HRESULT CVsBackupTest::WaitLoop
|
|
(
|
|
IVssBackupComponents *pvbc,
|
|
IVssAsync *pAsync,
|
|
UINT cycles,
|
|
VSS_WRITER_STATE state1,
|
|
VSS_WRITER_STATE state2,
|
|
VSS_WRITER_STATE state3,
|
|
VSS_WRITER_STATE state4,
|
|
VSS_WRITER_STATE state5,
|
|
VSS_WRITER_STATE state6,
|
|
VSS_WRITER_STATE state7
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
INT nPercentDone;
|
|
HRESULT hrResult;
|
|
|
|
while(TRUE)
|
|
{
|
|
if (cycles == 0)
|
|
{
|
|
hr = pAsync->Cancel();
|
|
ValidateResult(hr, "IVssAsync::Cancel");
|
|
|
|
GetAndValidateWriterState
|
|
(
|
|
pvbc,
|
|
state1,
|
|
state2,
|
|
state3,
|
|
state4,
|
|
state5,
|
|
state6,
|
|
state7
|
|
);
|
|
|
|
while(TRUE)
|
|
{
|
|
hr = pAsync->QueryStatus(&hrResult, &nPercentDone);
|
|
ValidateResult(hr, "IVssAsync::QueryStatus");
|
|
if (hrResult != STG_S_ASYNC_PENDING)
|
|
return hrResult;
|
|
|
|
Sleep(m_waitTime);
|
|
}
|
|
}
|
|
|
|
cycles--;
|
|
hr = pAsync->QueryStatus(&hrResult, &nPercentDone);
|
|
ValidateResult(hr, "IVssAsync::QueryStatus");
|
|
if (hrResult == STG_S_ASYNC_FINISHED)
|
|
break;
|
|
else if (hrResult != STG_S_ASYNC_PENDING)
|
|
return hrResult;
|
|
|
|
Sleep(m_waitTime);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CVsBackupTest::RunBackupTest()
|
|
{
|
|
if (m_wszVolumesSnapshot == NULL)
|
|
{
|
|
m_wszVolumesSnapshot = new WCHAR[1024];
|
|
if (m_wszVolumesSnapshot == NULL)
|
|
{
|
|
LogFailure("Out of memory");
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
m_cwcVolumesSnapshot = 1024;
|
|
}
|
|
|
|
m_wszVolumesSnapshot[0] = L'\0';
|
|
CComPtr<IVssBackupComponents> pvbc;
|
|
HRESULT hr;
|
|
bool bAbortNeeded = false;
|
|
bool bDeleteNeeded = false;
|
|
|
|
|
|
VSS_ID id = GUID_NULL;
|
|
try
|
|
{
|
|
hr = CreateVssBackupComponents(&pvbc);
|
|
ValidateResult(hr, "CreateVssBackupComponents");
|
|
|
|
|
|
hr = pvbc->InitializeForBackup();
|
|
ValidateResult(hr, "IVssBackupComponents::InitializeForBackup");
|
|
hr = pvbc->SetBackupState(true, false, VSS_BT_FULL);
|
|
ValidateResult(hr, "IVssBackupComponents::SetBackupState");
|
|
hr = pvbc->StartSnapshotSet(&id);
|
|
bAbortNeeded = true;
|
|
ValidateResult(hr, "IVssBackupComponents::StartSnapshotSet");
|
|
GetMetadataAndSetupComponents(pvbc);
|
|
if(m_bVolumeBackup || m_bSerialBackup)
|
|
{
|
|
if (m_cVolumes == 0)
|
|
{
|
|
m_volumeList.RefreshVolumeList();
|
|
m_cVolumes = m_volumeList.GetVolumeCount();
|
|
if (m_cVolumes > MAX_VOLUME_COUNT)
|
|
m_cVolumes = MAX_VOLUME_COUNT;
|
|
|
|
m_cVolumesLeft = m_cVolumes;
|
|
memset(m_rgbAssignedVolumes, 0, m_cVolumes * sizeof(bool));
|
|
RemoveNonCandidateVolumes();
|
|
if (m_cVolumesLeft == 0)
|
|
LogFailure("No Volumes to snapshot.");
|
|
}
|
|
|
|
if (m_backupVolumes == VSTST_BV_ONE)
|
|
ChooseVolumeToBackup(pvbc);
|
|
else if (m_backupVolumes == VSTST_BV_ALL)
|
|
{
|
|
// backup all volumes
|
|
while(m_cVolumesLeft > 0)
|
|
ChooseVolumeToBackup(pvbc);
|
|
}
|
|
else
|
|
{
|
|
// choose some subset of volumes to backup
|
|
UINT cVolumesToBackup = CVsTstRandom::RandomChoice(1, m_cVolumes);
|
|
while(cVolumesToBackup-- > 0)
|
|
ChooseVolumeToBackup(pvbc);
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
hr = pvbc->PrepareForBackup(&pAsync);
|
|
ValidateResult(hr, "IVssBackupComponents::PrepareForBackup");
|
|
if (m_llCancelPrepareBackupHigh > 0i64)
|
|
{
|
|
if (m_cyclesCancelPrepareBackup < (UINT) m_llCancelPrepareBackupLow)
|
|
m_cyclesCancelPrepareBackup = (UINT) m_llCancelPrepareBackupLow;
|
|
}
|
|
else
|
|
m_cyclesCancelPrepareBackup = 0xffffffff;
|
|
|
|
|
|
hr = WaitLoop
|
|
(
|
|
pvbc,
|
|
pAsync,
|
|
m_cyclesCancelPrepareBackup,
|
|
VSS_WS_FAILED_AT_PREPARE_BACKUP,
|
|
VSS_WS_STABLE
|
|
);
|
|
|
|
if (m_cyclesCancelPrepareBackup != 0xffffffff)
|
|
m_cyclesCancelPrepareBackup++;
|
|
|
|
if (m_cyclesCancelPrepareBackup > (UINT) m_llCancelPrepareBackupHigh)
|
|
m_cyclesCancelPrepareBackup = 0xffffffff;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
char buf[128];
|
|
sprintf(buf, "PrepareForBackup failed. hr = 0x%08lx", hr);
|
|
LogFailure(buf);
|
|
throw hr;
|
|
}
|
|
|
|
if (hr == STG_S_ASYNC_CANCELLED)
|
|
throw S_OK;
|
|
|
|
LogMessage("PrepareForBackup Succeeded.\n");
|
|
if (!GetAndValidateWriterState(pvbc, VSS_WS_STABLE))
|
|
throw E_FAIL;
|
|
|
|
LogMessage("Starting snapshot");
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
hr = pvbc->DoSnapshotSet(0, &pAsync);
|
|
|
|
if (m_llCancelDoSnapshotSetHigh > 0i64)
|
|
{
|
|
if (m_cyclesCancelDoSnapshotSet < (UINT) m_llCancelDoSnapshotSetLow)
|
|
m_cyclesCancelDoSnapshotSet = (UINT) m_llCancelDoSnapshotSetLow;
|
|
}
|
|
else
|
|
m_cyclesCancelDoSnapshotSet = 0xffffffff;
|
|
|
|
hr = WaitLoop
|
|
(
|
|
pvbc,
|
|
pAsync,
|
|
m_cyclesCancelDoSnapshotSet,
|
|
VSS_WS_FAILED_AT_PREPARE_SYNC,
|
|
VSS_WS_FAILED_AT_FREEZE,
|
|
VSS_WS_FAILED_AT_THAW,
|
|
VSS_WS_WAITING_FOR_COMPLETION,
|
|
VSS_WS_WAITING_FOR_FREEZE,
|
|
VSS_WS_WAITING_FOR_THAW,
|
|
VSS_WS_STABLE
|
|
);
|
|
|
|
if (m_cyclesCancelDoSnapshotSet != 0xffffffff)
|
|
m_cyclesCancelDoSnapshotSet++;
|
|
|
|
if (m_cyclesCancelDoSnapshotSet > (UINT) m_llCancelDoSnapshotSetHigh)
|
|
m_cyclesCancelDoSnapshotSet = 0xffffffff;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
char buf[128];
|
|
sprintf(buf, "DoSnapshotSet failed. hr = 0x%08lx", hr);
|
|
LogFailure(buf);
|
|
throw hr;
|
|
}
|
|
|
|
if (hr == STG_S_ASYNC_CANCELLED)
|
|
throw S_OK;
|
|
|
|
bDeleteNeeded = true;
|
|
LogMessage("DoSnapshotSet Succeeded.\n");
|
|
bAbortNeeded = false;
|
|
if (!GetAndValidateWriterState(pvbc, VSS_WS_WAITING_FOR_COMPLETION, VSS_WS_STABLE))
|
|
throw E_FAIL;
|
|
|
|
SetComponentsSuccessfullyBackedUp(pvbc);
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
hr = pvbc->BackupComplete(&pAsync);
|
|
ValidateResult(hr, "IVssBackupComponents::BackupComplete");
|
|
|
|
if (m_llCancelBackupCompleteHigh > 0i64)
|
|
{
|
|
if (m_cyclesCancelBackupComplete < (UINT) m_llCancelBackupCompleteLow)
|
|
m_cyclesCancelBackupComplete = (UINT) m_llCancelBackupCompleteLow;
|
|
}
|
|
else
|
|
m_cyclesCancelBackupComplete = 0xffffffff;
|
|
|
|
hr = WaitLoop
|
|
(
|
|
pvbc,
|
|
pAsync,
|
|
m_cyclesCancelBackupComplete,
|
|
VSS_WS_WAITING_FOR_COMPLETION,
|
|
VSS_WS_STABLE
|
|
);
|
|
|
|
if (m_cyclesCancelBackupComplete != 0xffffffff)
|
|
m_cyclesCancelBackupComplete++;
|
|
|
|
if (m_cyclesCancelBackupComplete > (UINT) m_llCancelDoSnapshotSetHigh)
|
|
m_cyclesCancelBackupComplete = 0xffffffff;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
char buf[128];
|
|
sprintf(buf, "BackupComplete failed. hr = 0x%08lx", hr);
|
|
LogFailure(buf);
|
|
throw hr;
|
|
}
|
|
|
|
if (hr == STG_S_ASYNC_CANCELLED)
|
|
throw S_OK;
|
|
|
|
LogMessage("BackupComplete Succeeded.\n");
|
|
if (!GetAndValidateWriterState(pvbc, VSS_WS_STABLE, VSS_WS_WAITING_FOR_COMPLETION))
|
|
throw E_FAIL;
|
|
|
|
m_cyclesCancelPrepareBackup = 0;
|
|
m_cyclesCancelDoSnapshotSet = 0;
|
|
m_cyclesCancelBackupComplete = 0;
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
char buf[128];
|
|
|
|
if (bAbortNeeded)
|
|
{
|
|
hr = pvbc->AbortBackup();
|
|
if (FAILED(hr))
|
|
{
|
|
sprintf(buf, "IVssBackupComponents::AbortBackup failed. hr = 0x%08lx", hr);
|
|
LogFailure(buf);
|
|
}
|
|
}
|
|
|
|
if (bDeleteNeeded)
|
|
{
|
|
if (m_bSerialBackup)
|
|
{
|
|
m_rgSnapshotSetIds[m_cSnapshotSets] = id;
|
|
m_rgvbc[m_cSnapshotSets] = pvbc.Detach();
|
|
m_cSnapshotSets++;
|
|
}
|
|
else
|
|
DoDeleteSnapshotSet(pvbc, id);
|
|
}
|
|
|
|
if (!m_bSerialBackup)
|
|
{
|
|
// reset for a new snapshot by causing volume list to be refreshed
|
|
m_cVolumes = 0;
|
|
m_cVolumesLeft = 0;
|
|
}
|
|
else if (m_cVolumesLeft == 0 ||
|
|
m_cSnapshotSets == MAX_SNAPSHOT_SET_COUNT ||
|
|
!bDeleteNeeded)
|
|
{
|
|
// delete existing snapshot sets if there was a failure or
|
|
// if there are no more volumes to add or
|
|
// if we can't create a new snapshot set.
|
|
DeleteCachedSnapshotSets();
|
|
m_cVolumes = 0;
|
|
m_cVolumesLeft = 0;
|
|
m_cSnapshotSets = 0;
|
|
}
|
|
}
|
|
|
|
// delete all snapshot sets that are cached
|
|
void CVsBackupTest::DeleteCachedSnapshotSets()
|
|
{
|
|
for(UINT iSnapshotSet = 0; iSnapshotSet < m_cSnapshotSets; iSnapshotSet++)
|
|
{
|
|
CComPtr<IVssBackupComponents> pvbc;
|
|
pvbc.Attach(m_rgvbc[iSnapshotSet]);
|
|
DoDeleteSnapshotSet(pvbc, m_rgSnapshotSetIds[iSnapshotSet]);
|
|
}
|
|
}
|
|
|
|
|
|
void CVsBackupTest::DoDeleteSnapshotSet(IVssBackupComponents *pvbc, VSS_ID id)
|
|
{
|
|
try
|
|
{
|
|
LONG lSnapshotsNotDeleted;
|
|
VSS_ID rgSnapshotsNotDeleted[10];
|
|
HRESULT hr = pvbc->DeleteSnapshots
|
|
(
|
|
id,
|
|
VSS_OBJECT_SNAPSHOT_SET,
|
|
false,
|
|
&lSnapshotsNotDeleted,
|
|
rgSnapshotsNotDeleted
|
|
);
|
|
|
|
ValidateResult(hr, "IVssBackupComponents::DeleteSnapshots");
|
|
}
|
|
catch(HRESULT)
|
|
{
|
|
}
|
|
catch(...)
|
|
{
|
|
LogUnexpectedException("CVsBackupTest::DoDeleteSnapshotSet");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
bool CVsBackupTest::GetAndValidateWriterState
|
|
(
|
|
IVssBackupComponents *pvbc,
|
|
VSS_WRITER_STATE ws1,
|
|
VSS_WRITER_STATE ws2,
|
|
VSS_WRITER_STATE ws3,
|
|
VSS_WRITER_STATE ws4,
|
|
VSS_WRITER_STATE ws5,
|
|
VSS_WRITER_STATE ws6,
|
|
VSS_WRITER_STATE ws7
|
|
)
|
|
{
|
|
unsigned cWriters;
|
|
|
|
HRESULT hr = pvbc->GatherWriterStatus(&cWriters);
|
|
ValidateResult(hr, "IVssBackupComponents::GatherWriterStatus");
|
|
|
|
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
VSS_ID idInstance;
|
|
VSS_ID idWriter;
|
|
VSS_WRITER_STATE status;
|
|
CComBSTR bstrWriter;
|
|
HRESULT hrWriterFailure;
|
|
|
|
hr = pvbc->GetWriterStatus
|
|
(
|
|
iWriter,
|
|
&idInstance,
|
|
&idWriter,
|
|
&bstrWriter,
|
|
&status,
|
|
&hrWriterFailure
|
|
);
|
|
|
|
ValidateResult(hr, "IVssBackupComponents::GetWriterStatus");
|
|
if (status == VSS_WS_UNKNOWN ||
|
|
(status != ws1 &&
|
|
status != ws2 &&
|
|
status != ws3 &&
|
|
status != ws4 &&
|
|
status != ws5 &&
|
|
status != ws6 &&
|
|
status != ws7))
|
|
{
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Writer is in inappropriate state %d.", status);
|
|
LogFailure(buf);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
hr = pvbc->FreeWriterStatus();
|
|
ValidateResult(hr, "IVssBackupComponents::FreeWriterStatus");
|
|
return true;
|
|
}
|
|
|
|
void CVsBackupTest::SetComponentsSuccessfullyBackedUp
|
|
(
|
|
IVssBackupComponents *pvbc
|
|
)
|
|
{
|
|
unsigned cWriterComponents;
|
|
HRESULT hr = pvbc->GetWriterComponentsCount(&cWriterComponents);
|
|
ValidateResult(hr, "IVssBackupComponents::GetWriterComponentsCount");
|
|
for(UINT iWriter = 0; iWriter < cWriterComponents; iWriter++)
|
|
{
|
|
CComPtr<IVssWriterComponentsExt> pWriter;
|
|
hr = pvbc->GetWriterComponents(iWriter, &pWriter);
|
|
ValidateResult(hr, "IVssBackupComponents::GetWriterComponents");
|
|
|
|
unsigned cComponents;
|
|
hr = pWriter->GetComponentCount(&cComponents);
|
|
ValidateResult(hr, "IVssWriterComponents::GetComponentCount");
|
|
|
|
VSS_ID idWriter, idInstance;
|
|
hr = pWriter->GetWriterInfo(&idInstance, &idWriter);
|
|
ValidateResult(hr, "IVssWriterComponents::GetWriterInfo");
|
|
for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
|
|
{
|
|
CComPtr<IVssComponent> pComponent;
|
|
hr = pWriter->GetComponent(iComponent, &pComponent);
|
|
ValidateResult(hr, "IVssWriterComponents::GetComponent");
|
|
|
|
VSS_COMPONENT_TYPE ct;
|
|
CComBSTR bstrLogicalPath;
|
|
CComBSTR bstrComponentName;
|
|
|
|
hr = pComponent->GetLogicalPath(&bstrLogicalPath);
|
|
ValidateResult(hr, "IVssComponent::GetLogicalPath");
|
|
hr = pComponent->GetComponentType(&ct);
|
|
ValidateResult(hr, "IVssComponent::GetComponentType");
|
|
hr = pComponent->GetComponentName(&bstrComponentName);
|
|
ValidateResult(hr, "IVssComponent::GetComponentName");
|
|
hr = pvbc->SetBackupSucceeded
|
|
(
|
|
idInstance,
|
|
idWriter,
|
|
ct,
|
|
bstrLogicalPath,
|
|
bstrComponentName,
|
|
true
|
|
);
|
|
|
|
ValidateResult(hr, "IVssComponent::SetBackupSucceeded");
|
|
}
|
|
}
|
|
}
|
|
|
|
void CVsBackupTest::GetMetadataAndSetupComponents
|
|
(
|
|
IVssBackupComponents *pvbc
|
|
)
|
|
{
|
|
unsigned cWriters;
|
|
HRESULT hr = pvbc->GatherWriterMetadata(&cWriters);
|
|
ValidateResult(hr, "IVssBackupComponents::GatherWriterMetadata");
|
|
|
|
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
CComPtr<IVssExamineWriterMetadata> pMetadata;
|
|
VSS_ID idInstance;
|
|
|
|
hr = pvbc->GetWriterMetadata(iWriter, &idInstance, &pMetadata);
|
|
ValidateResult(hr, "IVssBackupComponents::GetWriterMetadata");
|
|
|
|
VSS_ID idInstanceT;
|
|
VSS_ID idWriter;
|
|
CComBSTR bstrWriterName;
|
|
VSS_USAGE_TYPE usage;
|
|
VSS_SOURCE_TYPE source;
|
|
|
|
hr = pMetadata->GetIdentity
|
|
(
|
|
&idInstanceT,
|
|
&idWriter,
|
|
&bstrWriterName,
|
|
&usage,
|
|
&source
|
|
);
|
|
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetIdentity");
|
|
|
|
if (memcmp(&idInstance, &idInstanceT, sizeof(VSS_ID)) != 0)
|
|
LogFailure("Id Instance mismatch");
|
|
|
|
unsigned cIncludeFiles, cExcludeFiles, cComponents;
|
|
hr = pMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents);
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetFileCounts");
|
|
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
|
|
for(unsigned i = 0; i < cIncludeFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
hr = pMetadata->GetIncludeFile(i, &pFiledesc);
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetIncludeFile");
|
|
ValidateFiledesc(pFiledesc);
|
|
}
|
|
|
|
for(i = 0; i < cExcludeFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
hr = pMetadata->GetExcludeFile(i, &pFiledesc);
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetExcludeFile");
|
|
ValidateFiledesc(pFiledesc);
|
|
}
|
|
|
|
for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
|
|
{
|
|
CComPtr<IVssWMComponent> pComponent;
|
|
PVSSCOMPONENTINFO pInfo;
|
|
hr = pMetadata->GetComponent(iComponent, &pComponent);
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetComponent");
|
|
hr = pComponent->GetComponentInfo(&pInfo);
|
|
ValidateResult(hr, "IVssWMComponent::GetComponentInfo");
|
|
if (m_bComponentBackup)
|
|
{
|
|
hr = pvbc->AddComponent
|
|
(
|
|
idInstance,
|
|
idWriter,
|
|
pInfo->type,
|
|
pInfo->bstrLogicalPath,
|
|
pInfo->bstrComponentName
|
|
);
|
|
|
|
ValidateResult(hr, "IVssBackupComponents::AddComponent");
|
|
}
|
|
if (pInfo->cFileCount > 0)
|
|
{
|
|
for(i = 0; i < pInfo->cFileCount; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
hr = pComponent->GetFile(i, &pFiledesc);
|
|
ValidateResult(hr, "IVssWMComponent::GetFile");
|
|
|
|
CComBSTR bstrPath;
|
|
hr = pFiledesc->GetPath(&bstrPath);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetPath");
|
|
if (m_bComponentBackup)
|
|
DoAddToSnapshotSet(pvbc, bstrPath);
|
|
|
|
ValidateFiledesc(pFiledesc);
|
|
}
|
|
}
|
|
|
|
if (pInfo->cDatabases > 0)
|
|
{
|
|
for(i = 0; i < pInfo->cDatabases; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
hr = pComponent->GetDatabaseFile(i, &pFiledesc);
|
|
ValidateResult(hr, "IVssWMComponent::GetDatabaseFile");
|
|
|
|
|
|
CComBSTR bstrPath;
|
|
hr = pFiledesc->GetPath(&bstrPath);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetPath");
|
|
|
|
if (m_bComponentBackup)
|
|
DoAddToSnapshotSet(pvbc, bstrPath);
|
|
|
|
ValidateFiledesc(pFiledesc);
|
|
}
|
|
}
|
|
|
|
if (pInfo->cLogFiles > 0)
|
|
{
|
|
for(i = 0; i < pInfo->cLogFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
hr = pComponent->GetDatabaseLogFile(i, &pFiledesc);
|
|
ValidateResult(hr, "IVssWMComponent::GetDatabaseLogFile");
|
|
|
|
|
|
CComBSTR bstrPath;
|
|
hr = pFiledesc->GetPath(&bstrPath);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetPath");
|
|
if (m_bComponentBackup)
|
|
DoAddToSnapshotSet(pvbc, bstrPath);
|
|
|
|
ValidateFiledesc(pFiledesc);
|
|
}
|
|
}
|
|
|
|
hr = pComponent->FreeComponentInfo(pInfo);
|
|
ValidateResult(hr, "IVssWMComponent::FreeComponentInfo");
|
|
}
|
|
|
|
VSS_RESTOREMETHOD_ENUM method;
|
|
CComBSTR bstrUserProcedure;
|
|
CComBSTR bstrService;
|
|
VSS_WRITERRESTORE_ENUM writerRestore;
|
|
unsigned cMappings;
|
|
bool bRebootRequired;
|
|
|
|
hr = pMetadata->GetRestoreMethod
|
|
(
|
|
&method,
|
|
&bstrService,
|
|
&bstrUserProcedure,
|
|
&writerRestore,
|
|
&bRebootRequired,
|
|
&cMappings
|
|
);
|
|
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetRestoreMethod");
|
|
|
|
for(i = 0; i < cMappings; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
|
|
hr = pMetadata->GetAlternateLocationMapping(i, &pFiledesc);
|
|
ValidateResult(hr, "IVssExamineWriterMetadata::GetAlternateLocationMapping");
|
|
ValidateFiledesc(pFiledesc);
|
|
}
|
|
}
|
|
|
|
hr = pvbc->FreeWriterMetadata();
|
|
ValidateResult(hr, "IVssBackupComponents::FreeWriterMetadata");
|
|
}
|
|
|
|
void CVsBackupTest::ValidateFiledesc(IVssWMFiledesc *pFiledesc)
|
|
{
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
bool bRecursive;
|
|
|
|
HRESULT hr = pFiledesc->GetPath(&bstrPath);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetPath");
|
|
hr = pFiledesc->GetFilespec(&bstrFilespec);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetFilespec");
|
|
hr = pFiledesc->GetRecursive(&bRecursive);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetRecursive");
|
|
hr = pFiledesc->GetAlternateLocation(&bstrAlternate);
|
|
ValidateResult(hr, "IVssWMFiledesc::GetAlternateLocation");
|
|
}
|
|
|
|
|
|
// add a component file to the snapshot set by determining which volume
|
|
// contains the file and then adding the file to the snapshot set if it
|
|
// is not already included.
|
|
void CVsBackupTest::DoAddToSnapshotSet
|
|
(
|
|
IN IVssBackupComponents *pvbc,
|
|
IN LPCWSTR wszPath
|
|
)
|
|
{
|
|
WCHAR wszVolume[MAX_PATH];
|
|
UINT cwc = (UINT) wcslen(wszPath) + 1;
|
|
WCHAR *wszVolumeMountPoint = new WCHAR[cwc];
|
|
if (wszVolumeMountPoint == NULL)
|
|
{
|
|
LogFailure("Out of memory");
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (!GetVolumePathName(wszPath, wszVolumeMountPoint, cwc))
|
|
ValidateResult(HRESULT_FROM_WIN32(GetLastError()), "GetVolumePathName");
|
|
|
|
if (!GetVolumeNameForVolumeMountPointW
|
|
(
|
|
wszVolumeMountPoint,
|
|
wszVolume,
|
|
MAX_PATH
|
|
))
|
|
ValidateResult(HRESULT_FROM_WIN32(GetLastError()), "GetVolumeNameForVolumeMountPointW");
|
|
|
|
|
|
|
|
WCHAR *pwc = m_wszVolumesSnapshot;
|
|
while(*pwc != '\0')
|
|
{
|
|
if (wcsncmp(pwc, wszVolume, wcslen(wszVolume)) == 0)
|
|
return;
|
|
|
|
pwc = wcschr(pwc, L';');
|
|
if (pwc == NULL)
|
|
break;
|
|
|
|
pwc++;
|
|
}
|
|
|
|
|
|
HRESULT hr = pvbc->AddToSnapshotSet
|
|
(
|
|
wszVolume,
|
|
GUID_NULL,
|
|
L"",
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
ValidateResult(hr, "IVssBackupComponents::AddToSnaphsotSet");
|
|
if (pwc - m_wszVolumesSnapshot + wcslen(wszVolume) + 1 > m_cwcVolumesSnapshot)
|
|
{
|
|
WCHAR *wszVolumesNew = new WCHAR[m_cwcVolumesSnapshot + 1024];
|
|
if(wszVolumesNew == NULL)
|
|
{
|
|
LogFailure("Out of memory");
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
wcscpy(wszVolumesNew, m_wszVolumesSnapshot);
|
|
delete m_wszVolumesSnapshot;
|
|
m_wszVolumesSnapshot = wszVolumesNew;
|
|
m_cwcVolumesSnapshot += 1024;
|
|
pwc = m_wszVolumesSnapshot + wcslen(m_wszVolumesSnapshot);
|
|
}
|
|
|
|
*pwc++ = L';';
|
|
wcscpy(pwc, wszVolume);
|
|
}
|
|
|
|
// remove volumes for possible set of volume we can choose to backup based
|
|
// on configuration information
|
|
void CVsBackupTest::RemoveNonCandidateVolumes()
|
|
{
|
|
for(UINT iVolume = 0; iVolume < m_cVolumes; iVolume++)
|
|
{
|
|
// get volume information
|
|
const CVsTstVolumeInfo *pVolume = m_volumeList.GetVolumeInfo(iVolume);
|
|
bool bCandidate = false;
|
|
|
|
// validate that file system is one we will backup
|
|
if (pVolume->IsNtfs())
|
|
bCandidate = m_bBackupNTFS;
|
|
else if (pVolume->IsFat32())
|
|
bCandidate = m_bBackupFAT32;
|
|
else if (pVolume->IsFat())
|
|
bCandidate = m_bBackupFAT16;
|
|
else if (pVolume->IsRaw())
|
|
bCandidate = m_bBackupRAW;
|
|
|
|
// candidates must be in the included volumes list
|
|
if (m_cIncludedVolumes > 0)
|
|
{
|
|
LPCWSTR wszVolumeName = pVolume->GetVolumeName();
|
|
|
|
bool fFound = false;
|
|
for(UINT iIncluded = 0; iIncluded < m_cIncludedVolumes; iIncluded++)
|
|
{
|
|
if (wcscmp(wszVolumeName, m_rgwszIncludedVolumes[iIncluded]) == 0)
|
|
fFound = true;
|
|
}
|
|
|
|
if (!fFound)
|
|
bCandidate = false;
|
|
}
|
|
|
|
// candidates must not be in the excluded volumes list
|
|
if (m_cExcludedVolumes > 0)
|
|
{
|
|
LPCWSTR wszVolumeName = pVolume->GetVolumeName();
|
|
|
|
for(UINT iExcluded = 0; iExcluded < m_cExcludedVolumes; iExcluded++)
|
|
{
|
|
if (wcscmp(wszVolumeName, m_rgwszExcludedVolumes[iExcluded]) == 0)
|
|
bCandidate = false;
|
|
}
|
|
}
|
|
|
|
// if it is not a candidate, mark it is if it is already in use. This
|
|
// will prevent us from choosing the volume as part of a snapshot set
|
|
if (!bCandidate)
|
|
{
|
|
m_rgbAssignedVolumes[iVolume] = true;
|
|
m_cVolumesLeft--;
|
|
}
|
|
}
|
|
}
|
|
|
|
// pick a random volume to backup
|
|
void CVsBackupTest::ChooseVolumeToBackup(IVssBackupComponents *pvbc)
|
|
{
|
|
VSTST_ASSERT(m_cVolumesLeft > 0);
|
|
|
|
UINT iVolume;
|
|
while(TRUE)
|
|
{
|
|
// select a volume number
|
|
iVolume = CVsTstRandom::RandomChoice(0, m_cVolumes-1);
|
|
|
|
// check to see if volume is already assigned. If not, then
|
|
// break out of loop
|
|
if (!m_rgbAssignedVolumes[iVolume])
|
|
break;
|
|
}
|
|
|
|
// get volume information about volume
|
|
const CVsTstVolumeInfo *pVolume = m_volumeList.GetVolumeInfo(iVolume);
|
|
|
|
// add the volume to the snapshot set using the default provider
|
|
HRESULT hr = pvbc->AddToSnapshotSet
|
|
(
|
|
(VSS_PWSZ) pVolume->GetVolumeName(),
|
|
GUID_NULL,
|
|
L"",
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
ValidateResult(hr, "IVssBackupComponents::AddToSnapshotSet");
|
|
|
|
// indicate that volume is assigned
|
|
m_rgbAssignedVolumes[iVolume] = true;
|
|
m_cVolumesLeft--;
|
|
}
|
|
|
|
|
|
|
|
// main driver routine
|
|
extern "C" __cdecl wmain(int argc, WCHAR **argv)
|
|
{
|
|
CVsBackupTest *pTest = NULL;
|
|
|
|
bool bCoInitializeSucceeded = false;
|
|
try
|
|
{
|
|
// setup to use OLE
|
|
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
if (FAILED(hr))
|
|
{
|
|
LogUnexpectedFailure(L"CoInitialize Failed hr = 0x%08lx", hr);
|
|
throw hr;
|
|
}
|
|
|
|
bCoInitializeSucceeded = true;
|
|
|
|
// create test object
|
|
pTest = new CVsBackupTest;
|
|
if (pTest == NULL)
|
|
{
|
|
LogUnexpectedFailure(L"Cannot create test object.");
|
|
throw(E_OUTOFMEMORY);
|
|
}
|
|
|
|
|
|
// run test using the test object
|
|
hr = CVsTstRunner::RunVsTest(argv, argc, pTest, true);
|
|
if (FAILED(hr))
|
|
LogUnexpectedFailure(L"CVsTstRunner::RunTest failed. hr = 0x%08lx", hr);
|
|
}
|
|
catch(HRESULT)
|
|
{
|
|
}
|
|
catch(...)
|
|
{
|
|
LogUnexpectedFailure(L"Unexpected exception in wmain");
|
|
}
|
|
|
|
// delete test object
|
|
delete pTest;
|
|
|
|
// uninitialize OLE
|
|
if (bCoInitializeSucceeded)
|
|
CoUninitialize();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// log an unexpected failure from the test.
|
|
void LogUnexpectedFailure(LPCWSTR wsz, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, wsz);
|
|
|
|
VSTST_ASSERT(FALSE);
|
|
vwprintf(wsz, args);
|
|
}
|
|
|
|
|