Leaked source code of windows server 2003
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.
 
 
 
 
 
 

536 lines
17 KiB

/*++
Copyright (c) 1999-2001 Microsoft Corporation
Abstract:
@doc
@module process.cpp | The processing functions for the VSS admin CLI
@end
Author:
Adi Oltean [aoltean] 04/04/2000
TBD:
Add comments.
Revision History:
Name Date Comments
aoltean 04/04/2000 Created
ssteiner 10/20/2000 Changed List SnapshotSets to use more limited VSS queries.
--*/
/////////////////////////////////////////////////////////////////////////////
// Includes
// The rest of includes are specified here
#include "vssadmin.h"
#include "vswriter.h"
#include "vsbackup.h"
////////////////////////////////////////////////////////////////////////
// Standard foo for file name aliasing. This code block must be after
// all includes of VSS header files.
//
#ifdef VSS_FILE_ALIAS
#undef VSS_FILE_ALIAS
#endif
#define VSS_FILE_ALIAS "ADMPROCC"
//
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Implementation
class CVssAdmSnapshotSetEntry {
public:
// Constructor - Throws NOTHING
CVssAdmSnapshotSetEntry(
IN VSS_ID SnapshotSetId,
IN INT nOriginalSnapshotsCount
) : m_SnapshotSetId( SnapshotSetId ),
m_nOriginalSnapshotCount(nOriginalSnapshotsCount){ }
~CVssAdmSnapshotSetEntry()
{
// Have to delete all snapshots entries
int iCount = GetSnapshotCount();
for ( int i = 0; i < iCount; ++i )
{
VSS_SNAPSHOT_PROP *pSSProp;
pSSProp = GetSnapshotAt( i );
::VssFreeSnapshotProperties(pSSProp);
delete pSSProp;
}
}
// Add new snapshot to the snapshot set
HRESULT AddSnapshot(
IN CVssFunctionTracer &ft,
IN VSS_SNAPSHOT_PROP *pVssSnapshotProp )
{
HRESULT hr = S_OK;
try
{
VSS_SNAPSHOT_PROP *pNewVssSnapshotProp = new VSS_SNAPSHOT_PROP;
if ( pNewVssSnapshotProp == NULL )
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
*pNewVssSnapshotProp = *pVssSnapshotProp;
if ( !m_mapSnapshots.Add( pNewVssSnapshotProp->m_SnapshotId, pNewVssSnapshotProp ) )
{
delete pNewVssSnapshotProp;
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
}
}
BS_STANDARD_CATCH();
return hr;
}
INT GetSnapshotCount() { return m_mapSnapshots.GetSize(); }
INT GetOriginalSnapshotCount() { return m_nOriginalSnapshotCount; }
VSS_ID GetSnapshotSetId() { return m_SnapshotSetId; }
VSS_SNAPSHOT_PROP *GetSnapshotAt(
IN int nIndex )
{
BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotCount()) );
return m_mapSnapshots.GetValueAt( nIndex );
}
private:
VSS_ID m_SnapshotSetId;
INT m_nOriginalSnapshotCount;
CVssSimpleMap<VSS_ID, VSS_SNAPSHOT_PROP *> m_mapSnapshots;
};
// This class queries the list of all snapshots and assembles from the query
// the list of snapshotsets and the volumes which are in the snapshotset.
class CVssAdmSnapshotSets
{
public:
// Constructor - Throws HRESULTS
CVssAdmSnapshotSets(
IN VSS_ID FilteredSnapshotSetId = GUID_NULL )
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::CVssAdmSnapshotSets" );
bool bFiltered = !( FilteredSnapshotSetId == GUID_NULL );
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.LogVssStartupAttempt();
ft.hr = pICoord.CoCreateInstance( CLSID_VSSCoordinator );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Connection failed with hr = 0x%08lx", ft.hr);
// Get list all snapshots
CComPtr<IVssEnumObject> pIEnumSnapshots;
ft.hr = pICoord->Query( GUID_NULL,
VSS_OBJECT_NONE,
VSS_OBJECT_SNAPSHOT,
&pIEnumSnapshots );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Query failed with hr = 0x%08lx", ft.hr);
// For all snapshots do...
VSS_OBJECT_PROP Prop;
VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
for(;;) {
// Get next element
ULONG ulFetched;
ft.hr = pIEnumSnapshots->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is finished
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
// If filtering, skip entry if snapshot is not in the specified snapshot set
if ( bFiltered && !( Snap.m_SnapshotSetId == FilteredSnapshotSetId ) )
continue;
ft.Trace( VSSDBG_VSSADMIN, L"Snapshot: %s", Snap.m_pwszOriginalVolumeName );
// Look up the snapshot set id in the list of snapshot sets
CVssAdmSnapshotSetEntry *pcSSE;
pcSSE = m_mapSnapshotSets.Lookup( Snap.m_SnapshotSetId );
if ( pcSSE == NULL )
{
// Haven't seen this snapshot set before, add it to list
pcSSE = new CVssAdmSnapshotSetEntry( Snap.m_SnapshotSetId,
Snap.m_lSnapshotsCount );
if ( pcSSE == NULL )
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
if ( !m_mapSnapshotSets.Add( Snap.m_SnapshotSetId, pcSSE ) )
{
delete pcSSE;
ft.Throw( VSSDBG_VSSADMIN, E_OUTOFMEMORY, L"Out of memory" );
}
}
// Now add the snapshot to the snapshot set
ft.hr = pcSSE->AddSnapshot( ft, &Snap );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, ft.hr, L"AddSnapshot failed" );
}
}
~CVssAdmSnapshotSets()
{
CVssFunctionTracer ft( VSSDBG_VSSADMIN, L"CVssAdmSnapshotSets::~CVssAdmSnapshotSets" );
// Have to delete all
int iCount;
iCount = m_mapSnapshotSets.GetSize();
for ( int i = 0; i < iCount; ++i )
{
delete m_mapSnapshotSets.GetValueAt( i );
}
}
INT GetSnapshotSetCount() { return m_mapSnapshotSets.GetSize(); }
CVssAdmSnapshotSetEntry *GetSnapshotSetAt(
IN int nIndex )
{
BS_ASSERT( !(nIndex < 0 || nIndex >= GetSnapshotSetCount()) );
return m_mapSnapshotSets.GetValueAt( nIndex );
}
private:
CVssSimpleMap<VSS_ID, CVssAdmSnapshotSetEntry *> m_mapSnapshotSets;
};
/////////////////////////////////////////////////////////////////////////////
// Implementation
void CVssAdminCLI::PrintUsage(
IN CVssFunctionTracer& ft
) throw(HRESULT)
{
// Usage:\n\n
// vssadmin list snapshots [-set {snapshot set guid}]\n
// \tWill list all snapshots in the system, grouped by snapshot set Id.\n\n
// vssadmin list writers\n
// \tWill list all writers in the system\n\n
// vssadmin list providers\n
// \tWill list all currently installed snapshot providers\n
Output( ft, IDS_USAGE );
Output( ft, IDS_USAGE_SNAPSHOTS,
wszVssOptVssadmin, wszVssOptList, wszVssOptSnapshots, wszVssOptSet );
Output( ft, IDS_USAGE_WRITERS,
wszVssOptVssadmin, wszVssOptList, wszVssOptWriters );
Output( ft, IDS_USAGE_PROVIDERS,
wszVssOptVssadmin, wszVssOptList, wszVssOptProviders);
}
void CVssAdminCLI::ListSnapshots(
IN CVssFunctionTracer& ft
) throw(HRESULT)
{
bool bNonEmptyResult = false;
// Check the filter type
switch ( m_eFilterObjectType ) {
case VSS_OBJECT_SNAPSHOT_SET:
case VSS_OBJECT_NONE:
break;
default:
BS_ASSERT(false);
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Invalid object type %d", m_eFilterObjectType);
}
CVssAdmSnapshotSets cVssAdmSS( m_FilterSnapshotSetId );
INT iSnapshotSetCount = cVssAdmSS.GetSnapshotSetCount();
// If there are no present snapshots then display a message.
if (iSnapshotSetCount == 0) {
Output( ft,
(m_eFilterObjectType == VSS_OBJECT_SNAPSHOT_SET)?
IDS_NO_SNAPSHOTS_FOR_SET: IDS_NO_SNAPSHOTS );
}
// For all snapshot sets do...
for ( INT iSSS = 0; iSSS < iSnapshotSetCount; ++iSSS )
{
CVssAdmSnapshotSetEntry *pcSSE;
pcSSE = cVssAdmSS.GetSnapshotSetAt( iSSS );
BS_ASSERT( pcSSE != NULL );
// Print each snapshot set
Output( ft, IDS_SNAPSHOT_SET_HEADER,
GUID_PRINTF_ARG( pcSSE->GetSnapshotSetId() ),
pcSSE->GetOriginalSnapshotCount(), pcSSE->GetSnapshotCount());
// TBD: add creation time from the first snapshot.
INT iSnapshotCount = pcSSE->GetSnapshotCount();
VSS_SNAPSHOT_PROP *pSnap;
for( INT iSS = 0; iSS < iSnapshotCount; ++iSS ) {
pSnap = pcSSE->GetSnapshotAt( iSS );
BS_ASSERT( pSnap != NULL );
// Get the provider name
LPCWSTR pwszProviderName =
GetProviderName(ft, pSnap->m_ProviderId);
// Print each snapshot
Output( ft, IDS_SNAPSHOT_CONTENTS,
pwszProviderName? pwszProviderName: L"",
GUID_PRINTF_ARG(pSnap->m_SnapshotId),
pSnap->m_pwszOriginalVolumeName
);
Output( ft, wszVssFmtNewline );
bNonEmptyResult = true;
}
}
m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
}
void CVssAdminCLI::ListWriters(
IN CVssFunctionTracer& ft
) throw(HRESULT)
{
bool bNonEmptyResult = false;
// Get the backup components object
CComPtr<IVssBackupComponents> pBackupComp;
CComPtr<IVssAsync> pAsync;
ft.hr = ::CreateVssBackupComponents(&pBackupComp);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"CreateVssBackupComponents failed with hr = 0x%08lx", ft.hr);
// BUGBUG Initialize for backup
ft.hr = pBackupComp->InitializeForBackup();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"InitializeForBackup failed with hr = 0x%08lx", ft.hr);
UINT unWritersCount;
// get metadata for all writers
ft.hr = pBackupComp->GatherWriterMetadata(&pAsync);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GatherWriterMetadata failed with hr = 0x%08lx", ft.hr);
// Using polling, try to obtain the list of writers as soon as possible
HRESULT hrReturned = S_OK;
for (int nRetries = 0; nRetries < MAX_RETRIES_COUNT; nRetries++ ) {
// Wait a little
::Sleep(nPollingInterval);
// Check if finished
INT nReserved = 0;
ft.hr = pAsync->QueryStatus(
&hrReturned,
&nReserved
);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED,
L"IVssAsync::QueryStatus failed with hr = 0x%08lx", ft.hr);
if (hrReturned == VSS_S_ASYNC_FINISHED)
break;
if (hrReturned == VSS_S_ASYNC_PENDING)
continue;
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED,
L"IVssAsync::QueryStatus returned hr = 0x%08lx", hrReturned);
}
// If still not ready, then print the "waiting for responses" message and wait.
if (hrReturned == VSS_S_ASYNC_PENDING) {
Output( ft, IDS_WAITING_RESPONSES );
ft.hr = pAsync->Wait();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
}
pAsync = NULL;
// Gather the status of all writers
ft.hr = pBackupComp->GatherWriterStatus(&pAsync);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GatherWriterMetadata failed with hr = 0x%08lx", ft.hr);
ft.hr = pAsync->Wait();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"IVssAsync::Wait failed with hr = 0x%08lx", ft.hr);
pAsync = NULL;
ft.hr = pBackupComp->GetWriterStatusCount(&unWritersCount);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GetWriterStatusCount failed with hr = 0x%08lx", ft.hr);
// Print each writer status+supplementary info
for(UINT unIndex = 0; unIndex < unWritersCount; unIndex++)
{
VSS_ID idInstance;
VSS_ID idWriter;
CComBSTR bstrWriter;
VSS_WRITER_STATE eStatus;
HRESULT hrWriterFailure;
// Get the status for the (unIndex)-th writer
ft.hr = pBackupComp->GetWriterStatus(unIndex, &idInstance, &idWriter, &bstrWriter, &eStatus, &hrWriterFailure);
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"GetWriterStatus failed with hr = 0x%08lx", ft.hr);
// Get the status description strings
LPCWSTR pwszStatusDescription;
switch (eStatus) {
case VSS_WS_STABLE:
pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_STABLE);
break;
case VSS_WS_WAITING_FOR_FREEZE:
pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_WAITING_FOR_FREEZE);
break;
case VSS_WS_WAITING_FOR_THAW:
pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_FROZEN);
break;
case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_WAITING_FOR_COMPLETION);
break;
case VSS_WS_FAILED_AT_IDENTIFY:
case VSS_WS_FAILED_AT_PREPARE_BACKUP:
case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
case VSS_WS_FAILED_AT_FREEZE:
case VSS_WS_FAILED_AT_THAW:
pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_FAILED);
break;
default:
pwszStatusDescription = LoadString( ft, IDS_WRITER_STATUS_UNKNOWN);
break;
}
BS_ASSERT(pwszStatusDescription);
// Print status+info about each writer
Output( ft, IDS_WRITER_CONTENTS,
(LPWSTR)bstrWriter? (LPWSTR)bstrWriter: L"",
GUID_PRINTF_ARG(idWriter),
GUID_PRINTF_ARG(idInstance),
(INT)eStatus,
pwszStatusDescription
);
Output( ft, wszVssFmtNewline );
bNonEmptyResult = true;
}
ft.hr = pBackupComp->FreeWriterStatus();
if (ft.HrFailed())
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"FreeWriterStatus failed with hr = 0x%08lx", ft.hr);
m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
}
void CVssAdminCLI::ListProviders(
IN CVssFunctionTracer& ft
) throw(HRESULT)
{
bool bNonEmptyResult = false;
// Check the filter type
switch ( m_eFilterObjectType ) {
case VSS_OBJECT_NONE:
break;
default:
BS_ASSERT(false);
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Invalid object type %d", m_eFilterObjectType);
}
// Create the coordinator object
CComPtr<IVssCoordinator> pICoord;
ft.LogVssStartupAttempt();
ft.hr = pICoord.CoCreateInstance( CLSID_VSSCoordinator );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Connection failed with hr = 0x%08lx", ft.hr);
// Query all (filtered) snapshot sets
CComPtr<IVssEnumObject> pIEnumProv;
ft.hr = pICoord->Query( GUID_NULL,
VSS_OBJECT_NONE,
VSS_OBJECT_PROVIDER,
&pIEnumProv );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Query failed with hr = 0x%08lx", ft.hr);
// For all snapshot sets do...
VSS_OBJECT_PROP Prop;
VSS_PROVIDER_PROP& Prov = Prop.Obj.Prov;
for(;;) {
// Get next element
ULONG ulFetched;
ft.hr = pIEnumProv->Next( 1, &Prop, &ulFetched );
if ( ft.HrFailed() )
ft.Throw( VSSDBG_VSSADMIN, E_UNEXPECTED, L"Next failed with hr = 0x%08lx", ft.hr);
// Test if the cycle is ended
if (ft.hr == S_FALSE) {
BS_ASSERT( ulFetched == 0);
break;
}
// Get the provider type strings
LPCWSTR pwszProviderType;
switch (Prov.m_eProviderType) {
case VSS_PROV_SYSTEM:
pwszProviderType = LoadString( ft, IDS_PROV_TYPE_SYSTEM);
break;
case VSS_PROV_SOFTWARE:
pwszProviderType = LoadString( ft, IDS_PROV_TYPE_SOFTWARE);
break;
case VSS_PROV_HARDWARE:
pwszProviderType = LoadString( ft, IDS_PROV_TYPE_HARDWARE);
break;
default:
pwszProviderType = LoadString( ft, IDS_PROV_TYPE_UNKNOWN);
break;
}
BS_ASSERT(pwszProviderType);
// Print each snapshot set
Output( ft, IDS_PROVIDER_CONTENTS,
Prov.m_pwszProviderName? Prov.m_pwszProviderName: L"",
pwszProviderType,
GUID_PRINTF_ARG(Prov.m_ProviderId),
Prov.m_pwszProviderVersion? Prov.m_pwszProviderVersion: L"");
::CoTaskMemFree(Prov.m_pwszProviderName);
::CoTaskMemFree(Prov.m_pwszProviderVersion);
bNonEmptyResult = true;
}
m_nReturnValue = bNonEmptyResult? VSS_CMDRET_SUCCESS: VSS_CMDRET_EMPTY_RESULT;
}